diff --git a/initia_stdlib/doc/account.md b/initia_stdlib/doc/account.md index 5f23719..43802ef 100644 --- a/initia_stdlib/doc/account.md +++ b/initia_stdlib/doc/account.md @@ -5,20 +5,29 @@ +- [Struct `AccountInfo`](#0x1_account_AccountInfo) - [Constants](#@Constants_0) - [Function `create_account_script`](#0x1_account_create_account_script) - [Function `create_account`](#0x1_account_create_account) - [Function `create_table_account`](#0x1_account_create_table_account) - [Function `create_object_account`](#0x1_account_create_object_account) - [Function `exists_at`](#0x1_account_exists_at) +- [Function `is_blocked`](#0x1_account_is_blocked) - [Function `get_account_number`](#0x1_account_get_account_number) - [Function `get_sequence_number`](#0x1_account_get_sequence_number) - [Function `is_base_account`](#0x1_account_is_base_account) - [Function `is_object_account`](#0x1_account_is_object_account) - [Function `is_table_account`](#0x1_account_is_table_account) - [Function `is_module_account`](#0x1_account_is_module_account) -- [Function `request_create_account`](#0x1_account_request_create_account) - [Function `get_account_info`](#0x1_account_get_account_info) +- [Function `is_module_account_with_info`](#0x1_account_is_module_account_with_info) +- [Function `is_base_account_with_info`](#0x1_account_is_base_account_with_info) +- [Function `is_object_account_with_info`](#0x1_account_is_object_account_with_info) +- [Function `is_table_account_with_info`](#0x1_account_is_table_account_with_info) +- [Function `is_blocked_with_info`](#0x1_account_is_blocked_with_info) +- [Function `get_account_number_with_info`](#0x1_account_get_account_number_with_info) +- [Function `get_sequence_number_with_info`](#0x1_account_get_sequence_number_with_info) +- [Function `account_info`](#0x1_account_account_info) - [Function `create_address`](#0x1_account_create_address) - [Function `create_signer`](#0x1_account_create_signer) @@ -28,6 +37,48 @@ + + +## Struct `AccountInfo` + + + +
struct AccountInfo has copy, drop
+
+ + + +##### Fields + + +
+
+account_number: u64 +
+
+ +
+
+sequence_number: u64 +
+
+ +
+
+account_type: u8 +
+
+ +
+
+is_blocked: bool +
+
+ +
+
+ + ## Constants @@ -100,8 +151,7 @@ This error type is used in native function. -
-Implementation +##### Implementation
public entry fun create_account_script(addr: address) {
@@ -111,8 +161,6 @@ This error type is used in native function.
 
 
 
-
- ## Function `create_account` @@ -124,22 +172,22 @@ This error type is used in native function. -
-Implementation +##### Implementation
public fun create_account(addr: address): u64 {
-    let (found, _, _, _) = get_account_info(addr);
-    assert!(!found, error::already_exists(EACCOUNT_ALREADY_EXISTS));
+    let (found, _, _, _, _) = account_info(addr);
+    assert!(
+        !found,
+        error::already_exists(EACCOUNT_ALREADY_EXISTS)
+    );
 
-    request_create_account(addr, ACCOUNT_TYPE_BASE)
+    request_create_account(addr, 0, ACCOUNT_TYPE_BASE)
 }
 
-
- ## Function `create_table_account` @@ -153,22 +201,26 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public(friend) fun create_table_account(addr: address): u64 {
-    let (found, _, _, _) = get_account_info(addr);
-    assert!(!found, error::already_exists(EACCOUNT_ALREADY_EXISTS));
-
-    request_create_account(addr, ACCOUNT_TYPE_TABLE)
+    let (found, account_number, sequence, account_type, _) = account_info(addr);
+    assert!(
+        !found || (account_type == ACCOUNT_TYPE_BASE && sequence == 0),
+        error::already_exists(EACCOUNT_ALREADY_EXISTS)
+    );
+
+    request_create_account(
+        addr,
+        account_number,
+        ACCOUNT_TYPE_TABLE
+    )
 }
 
-
- ## Function `create_object_account` @@ -182,13 +234,20 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public(friend) fun create_object_account(addr: address): u64 {
-    let (found, account_number, _, account_type) = get_account_info(addr);
-    if (found) {
+    let (found, account_number, sequence, account_type, _) = account_info(addr);
+
+    // base account with sequence 0 is considered as not created.
+    if (!found || (account_type == ACCOUNT_TYPE_BASE && sequence == 0)) {
+        request_create_account(
+            addr,
+            account_number,
+            ACCOUNT_TYPE_OBJECT
+        )
+    } else {
         // When an Object is deleted, the ObjectAccount in CosmosSDK is designed
         // not to be deleted in order to prevent unexpected issues. Therefore,
         // in this case, the creation of an account is omitted.
@@ -199,16 +258,12 @@ as both cannot have a pubkey, there is no way to use the account externally.
         } else {
             abort(error::already_exists(EACCOUNT_ALREADY_EXISTS))
         }
-    } else {
-        request_create_account(addr, ACCOUNT_TYPE_OBJECT)
     }
 }
 
-
- ## Function `exists_at` @@ -221,19 +276,39 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public fun exists_at(addr: address): bool {
-    let (found, _, _, _) = get_account_info(addr);
+    let (found, _, _, _, _) = account_info(addr);
     found
 }
 
-
+ + +## Function `is_blocked` + + + +
#[view]
+public fun is_blocked(addr: address): bool
+
+ + + +##### Implementation + + +
public fun is_blocked(addr: address): bool {
+    let (_, _, _, _, blocked) = account_info(addr);
+    blocked
+}
+
+ + @@ -247,12 +322,11 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public fun get_account_number(addr: address): u64 {
-    let (found, account_number, _, _) = get_account_info(addr);
+    let (found, account_number, _, _, _) = account_info(addr);
     assert!(found, error::not_found(EACCOUNT_NOT_FOUND));
 
     account_number
@@ -261,8 +335,6 @@ as both cannot have a pubkey, there is no way to use the account externally.
 
 
 
-
- ## Function `get_sequence_number` @@ -275,12 +347,11 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public fun get_sequence_number(addr: address): u64 {
-    let (found, _, sequence_number, _) = get_account_info(addr);
+    let (found, _, sequence_number, _, _) = account_info(addr);
     assert!(found, error::not_found(EACCOUNT_NOT_FOUND));
 
     sequence_number
@@ -289,8 +360,6 @@ as both cannot have a pubkey, there is no way to use the account externally.
 
 
 
-
- ## Function `is_base_account` @@ -303,12 +372,11 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public fun is_base_account(addr: address): bool {
-    let (found, _, _, account_type) = get_account_info(addr);
+    let (found, _, _, account_type, _) = account_info(addr);
     assert!(found, error::not_found(EACCOUNT_NOT_FOUND));
 
     account_type == ACCOUNT_TYPE_BASE
@@ -317,8 +385,6 @@ as both cannot have a pubkey, there is no way to use the account externally.
 
 
 
-
- ## Function `is_object_account` @@ -331,12 +397,11 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public fun is_object_account(addr: address): bool {
-    let (found, _, _, account_type) = get_account_info(addr);
+    let (found, _, _, account_type, _) = account_info(addr);
     assert!(found, error::not_found(EACCOUNT_NOT_FOUND));
 
     account_type == ACCOUNT_TYPE_OBJECT
@@ -345,8 +410,6 @@ as both cannot have a pubkey, there is no way to use the account externally.
 
 
 
-
- ## Function `is_table_account` @@ -359,12 +422,11 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public fun is_table_account(addr: address): bool {
-    let (found, _, _, account_type) = get_account_info(addr);
+    let (found, _, _, account_type, _) = account_info(addr);
     assert!(found, error::not_found(EACCOUNT_NOT_FOUND));
 
     account_type == ACCOUNT_TYPE_TABLE
@@ -373,8 +435,6 @@ as both cannot have a pubkey, there is no way to use the account externally.
 
 
 
-
- ## Function `is_module_account` @@ -387,12 +447,11 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public fun is_module_account(addr: address): bool {
-    let (found, _, _, account_type) = get_account_info(addr);
+    let (found, _, _, account_type, _) = account_info(addr);
     assert!(found, error::not_found(EACCOUNT_NOT_FOUND));
 
     account_type == ACCOUNT_TYPE_MODULE
@@ -401,51 +460,203 @@ as both cannot have a pubkey, there is no way to use the account externally.
 
 
 
-
+ + +## Function `get_account_info` + + + +
#[view]
+public fun get_account_info(addr: address): (bool, account::AccountInfo)
+
+ - -## Function `request_create_account` +##### Implementation +
public fun get_account_info(addr: address): (bool, AccountInfo) {
+    let (found, account_number, sequence_number, account_type, is_blocked) =
+        account_info(addr);
 
-
fun request_create_account(addr: address, account_type: u8): u64
+    (found, AccountInfo { account_number, sequence_number, account_type, is_blocked })
+}
 
-
-Implementation + + +## Function `is_module_account_with_info` -
native fun request_create_account(addr: address, account_type: u8): u64;
+
+
public fun is_module_account_with_info(info: &account::AccountInfo): bool
 
-
+##### Implementation - -## Function `get_account_info` +
public fun is_module_account_with_info(info: &AccountInfo): bool {
+    info.account_type == ACCOUNT_TYPE_MODULE
+}
+
+ + + + + +## Function `is_base_account_with_info` + + + +
public fun is_base_account_with_info(info: &account::AccountInfo): bool
+
+ + + +##### Implementation + + +
public fun is_base_account_with_info(info: &AccountInfo): bool {
+    info.account_type == ACCOUNT_TYPE_BASE
+}
+
+ + + + + +## Function `is_object_account_with_info` -
public fun get_account_info(addr: address): (bool, u64, u64, u8)
+
public fun is_object_account_with_info(info: &account::AccountInfo): bool
 
-
-Implementation +##### Implementation -
native public fun get_account_info(addr: address): (bool /* found */, u64 /* account_number */, u64 /* sequence_number */, u8 /* account_type */);
+
public fun is_object_account_with_info(info: &AccountInfo): bool {
+    info.account_type == ACCOUNT_TYPE_OBJECT
+}
+
+ + + + + +## Function `is_table_account_with_info` + + + +
public fun is_table_account_with_info(info: &account::AccountInfo): bool
+
+ + + +##### Implementation + + +
public fun is_table_account_with_info(info: &AccountInfo): bool {
+    info.account_type == ACCOUNT_TYPE_TABLE
+}
+
+ + + + + +## Function `is_blocked_with_info` + + + +
public fun is_blocked_with_info(info: &account::AccountInfo): bool
+
+ + + +##### Implementation + + +
public fun is_blocked_with_info(info: &AccountInfo): bool {
+    info.is_blocked
+}
+
+ + + + + +## Function `get_account_number_with_info` + + + +
public fun get_account_number_with_info(info: &account::AccountInfo): u64
 
-
+##### Implementation + + +
public fun get_account_number_with_info(info: &AccountInfo): u64 {
+    info.account_number
+}
+
+ + + + + +## Function `get_sequence_number_with_info` + + + +
public fun get_sequence_number_with_info(info: &account::AccountInfo): u64
+
+ + + +##### Implementation + + +
public fun get_sequence_number_with_info(info: &AccountInfo): u64 {
+    info.sequence_number
+}
+
+ + + + + +## Function `account_info` + + + +
public fun account_info(addr: address): (bool, u64, u64, u8, bool)
+
+ + + +##### Implementation + + +
native public fun account_info(addr: address):
+    (
+    bool /* found */,
+    u64 /* account_number */,
+    u64 /* sequence_number */,
+    u8 /* account_type */,
+    bool /* is_blocked */
+);
+
+ + @@ -458,8 +669,7 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
native public(friend) fun create_address(bytes: vector<u8>): address;
@@ -467,8 +677,6 @@ as both cannot have a pubkey, there is no way to use the account externally.
 
 
 
-
- ## Function `create_signer` @@ -480,13 +688,8 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
native public(friend) fun create_signer(addr: address): signer;
 
- - - -
diff --git a/initia_stdlib/doc/address.md b/initia_stdlib/doc/address.md index da7f19c..36be855 100644 --- a/initia_stdlib/doc/address.md +++ b/initia_stdlib/doc/address.md @@ -5,94 +5,180 @@ +- [Struct `FromSdkRequest`](#0x1_address_FromSdkRequest) +- [Struct `FromSdkResponse`](#0x1_address_FromSdkResponse) +- [Struct `ToSdkRequest`](#0x1_address_ToSdkRequest) +- [Struct `ToSdkResponse`](#0x1_address_ToSdkResponse) - [Function `from_sdk`](#0x1_address_from_sdk) - [Function `to_sdk`](#0x1_address_to_sdk) - [Function `to_string`](#0x1_address_to_string) - [Function `from_string`](#0x1_address_from_string) +- [Function `to_bytes`](#0x1_address_to_bytes) +- [Function `from_bytes`](#0x1_address_from_bytes) -
use 0x1::json;
-use 0x1::option;
+
use 0x1::bcs;
+use 0x1::from_bcs;
+use 0x1::json;
 use 0x1::query;
-use 0x1::simple_json;
 use 0x1::string;
 
- + -## Function `from_sdk` +## Struct `FromSdkRequest` -
public fun from_sdk(sdk_addr: string::String): address
+
struct FromSdkRequest has copy, drop
 
-
-Implementation +##### Fields -
public fun from_sdk(sdk_addr: String): address {
-    let obj = simple_json::empty();
-    simple_json::set_object(&mut obj, option::none<String>());
-    simple_json::increase_depth(&mut obj);
+
+
+sdk_addr: string::String +
+
- simple_json::set_string(&mut obj, option::some(string::utf8(b"sdk_addr")), sdk_addr); +
+
- let req = json::stringify(simple_json::to_json_object(&obj)); - let res = query::query_custom(b"from_sdk_address", *string::bytes(&req)); - let res = simple_json::from_json_object(json::parse(string::utf8(res))); - simple_json::increase_depth(&mut res); - let (_, data) = json::unpack_elem(simple_json::borrow(&mut res)); + - from_string(json::as_string(data)) -} +## Struct `FromSdkResponse` + + + +
struct FromSdkResponse has copy, drop
 
-
+##### Fields - -## Function `to_sdk` +
+
+vm_addr: address +
+
+
+
-
public fun to_sdk(vm_addr: address): string::String
+
+
+## Struct `ToSdkRequest`
+
+
+
+
struct ToSdkRequest has copy, drop
 
-
-Implementation +##### Fields + + +
+
+vm_addr: address +
+
+ +
+
+ + + + +## Struct `ToSdkResponse` -
public fun to_sdk(vm_addr: address): String {
-    let obj = simple_json::empty();
-    simple_json::set_object(&mut obj, option::none<String>());
-    simple_json::increase_depth(&mut obj);
 
-    simple_json::set_string(&mut obj, option::some(string::utf8(b"vm_addr")), to_string(vm_addr));
+
struct ToSdkResponse has copy, drop
+
+ + + +##### Fields + + +
+
+sdk_addr: string::String +
+
+ +
+
+ + + + +## Function `from_sdk` + + + +
public fun from_sdk(sdk_addr: string::String): address
+
- let req = json::stringify(simple_json::to_json_object(&obj)); - let res = query::query_custom(b"to_sdk_address", *string::bytes(&req)); - let res = simple_json::from_json_object(json::parse(string::utf8(res))); - simple_json::increase_depth(&mut res); - let (_, data) = json::unpack_elem(simple_json::borrow(&mut res)); - json::as_string(data) +##### Implementation + + +
public fun from_sdk(sdk_addr: String): address {
+    let res =
+        json::unmarshal<FromSdkResponse>(
+            query::query_custom(
+                b"from_sdk_address",
+                json::marshal(&FromSdkRequest { sdk_addr: sdk_addr })
+            )
+        );
+
+    res.vm_addr
 }
 
-
+ + +## Function `to_sdk` + + + +
public fun to_sdk(vm_addr: address): string::String
+
+ + + +##### Implementation + + +
public fun to_sdk(vm_addr: address): String {
+    let res =
+        json::unmarshal<ToSdkResponse>(
+            query::query_custom(
+                b"to_sdk_address",
+                json::marshal(&ToSdkRequest { vm_addr: vm_addr })
+            )
+        );
+
+    res.sdk_addr
+}
+
+ + @@ -105,17 +191,14 @@ -
-Implementation +##### Implementation -
public native fun to_string(addr: address): String;
+
native public fun to_string(addr: address): String;
 
-
- ## Function `from_string` @@ -127,13 +210,50 @@ -
-Implementation +##### Implementation + + +
native public fun from_string(addr_str: String): address;
+
+ + + + + +## Function `to_bytes` + + + +
public fun to_bytes(addr: address): vector<u8>
+
+ + + +##### Implementation + + +
public fun to_bytes(addr: address): vector<u8> {
+    bcs::to_bytes(&addr)
+}
+
+ + + + + +## Function `from_bytes` -
public native fun from_string(addr_str: String): address;
+
+
public fun from_bytes(bytes: vector<u8>): address
 
-
+##### Implementation + + +
public fun from_bytes(bytes: vector<u8>): address {
+    from_bcs::to_address(bytes)
+}
+
diff --git a/initia_stdlib/doc/any.md b/initia_stdlib/doc/any.md index 635cf3b..5c68c68 100644 --- a/initia_stdlib/doc/any.md +++ b/initia_stdlib/doc/any.md @@ -43,8 +43,7 @@ extension: Option -
-Fields +##### Fields
@@ -63,8 +62,6 @@ extension: Option
-
- ## Constants @@ -93,8 +90,7 @@ also required from T. -
-Implementation +##### Implementation
public fun pack<T: drop + store>(x: T): Any {
@@ -107,8 +103,6 @@ also required from T.
 
 
 
-
- ## Function `unpack` @@ -121,20 +115,20 @@ Unpack a value from the Any repres -
-Implementation +##### Implementation
public fun unpack<T>(x: Any): T {
-    assert!(type_info::type_name<T>() == x.type_name, error::invalid_argument(ETYPE_MISMATCH));
+    assert!(
+        type_info::type_name<T>() == x.type_name,
+        error::invalid_argument(ETYPE_MISMATCH)
+    );
     from_bytes<T>(x.data)
 }
 
-
- ## Function `type_name` @@ -147,15 +141,10 @@ Returns the type name of this Any -
-Implementation +##### Implementation
public fun type_name(x: &Any): &String {
     &x.type_name
 }
 
- - - -
diff --git a/initia_stdlib/doc/aptos_hash.md b/initia_stdlib/doc/aptos_hash.md new file mode 100644 index 0000000..e1de452 --- /dev/null +++ b/initia_stdlib/doc/aptos_hash.md @@ -0,0 +1,79 @@ + + + +# Module `0x1::aptos_hash` + +AptosHash module exists to provide compatibility with aptos. + + +- [Function `sha2_256`](#0x1_aptos_hash_sha2_256) +- [Function `sha3_256`](#0x1_aptos_hash_sha3_256) +- [Function `keccak256`](#0x1_aptos_hash_keccak256) + + +
use 0x1::hash;
+use 0x1::keccak;
+
+ + + + + +## Function `sha2_256` + + + +
public fun sha2_256(data: vector<u8>): vector<u8>
+
+ + + +##### Implementation + + +
public fun sha2_256(data: vector<u8>): vector<u8> {
+    s2_256(data)
+}
+
+ + + + + +## Function `sha3_256` + + + +
public fun sha3_256(data: vector<u8>): vector<u8>
+
+ + + +##### Implementation + + +
public fun sha3_256(data: vector<u8>): vector<u8> {
+    s3_256(data)
+}
+
+ + + + + +## Function `keccak256` + + + +
public fun keccak256(data: vector<u8>): vector<u8>
+
+ + + +##### Implementation + + +
public fun keccak256(data: vector<u8>): vector<u8> {
+    k256(data)
+}
+
diff --git a/initia_stdlib/doc/base64.md b/initia_stdlib/doc/base64.md index bb9ad92..f81b263 100644 --- a/initia_stdlib/doc/base64.md +++ b/initia_stdlib/doc/base64.md @@ -27,8 +27,7 @@ -
-Implementation +##### Implementation
public fun to_string(bytes: vector<u8>): String {
@@ -38,8 +37,6 @@
 
 
 
-
- ## Function `from_string` @@ -51,8 +48,7 @@ -
-Implementation +##### Implementation
public fun from_string(str: String): vector<u8> {
@@ -62,8 +58,6 @@
 
 
 
-
- ## Function `encode` @@ -75,17 +69,14 @@ -
-Implementation +##### Implementation -
public native fun encode(bytes: vector<u8>): vector<u8>;
+
native public fun encode(bytes: vector<u8>): vector<u8>;
 
-
- ## Function `decode` @@ -97,13 +88,8 @@ -
-Implementation +##### Implementation -
public native fun decode(bytes: vector<u8>): vector<u8>;
+
native public fun decode(bytes: vector<u8>): vector<u8>;
 
- - - -
diff --git a/initia_stdlib/doc/bigdecimal.md b/initia_stdlib/doc/bigdecimal.md new file mode 100644 index 0000000..1c35a5e --- /dev/null +++ b/initia_stdlib/doc/bigdecimal.md @@ -0,0 +1,1424 @@ + + + +# Module `0x1::bigdecimal` + + + +- [Struct `BigDecimal`](#0x1_bigdecimal_BigDecimal) +- [Constants](#@Constants_0) +- [Function `from_u64`](#0x1_bigdecimal_from_u64) +- [Function `from_u128`](#0x1_bigdecimal_from_u128) +- [Function `from_u256`](#0x1_bigdecimal_from_u256) +- [Function `new`](#0x1_bigdecimal_new) +- [Function `from_scaled`](#0x1_bigdecimal_from_scaled) +- [Function `get_scaled`](#0x1_bigdecimal_get_scaled) +- [Function `from_scaled_le_bytes`](#0x1_bigdecimal_from_scaled_le_bytes) +- [Function `get_scaled_le_bytes`](#0x1_bigdecimal_get_scaled_le_bytes) +- [Function `from_ratio`](#0x1_bigdecimal_from_ratio) +- [Function `from_ratio_u64`](#0x1_bigdecimal_from_ratio_u64) +- [Function `from_ratio_u128`](#0x1_bigdecimal_from_ratio_u128) +- [Function `from_ratio_u256`](#0x1_bigdecimal_from_ratio_u256) +- [Function `rev`](#0x1_bigdecimal_rev) +- [Function `one`](#0x1_bigdecimal_one) +- [Function `zero`](#0x1_bigdecimal_zero) +- [Function `eq`](#0x1_bigdecimal_eq) +- [Function `lt`](#0x1_bigdecimal_lt) +- [Function `le`](#0x1_bigdecimal_le) +- [Function `gt`](#0x1_bigdecimal_gt) +- [Function `ge`](#0x1_bigdecimal_ge) +- [Function `is_zero`](#0x1_bigdecimal_is_zero) +- [Function `is_one`](#0x1_bigdecimal_is_one) +- [Function `add`](#0x1_bigdecimal_add) +- [Function `add_by_u64`](#0x1_bigdecimal_add_by_u64) +- [Function `add_by_u128`](#0x1_bigdecimal_add_by_u128) +- [Function `add_by_u256`](#0x1_bigdecimal_add_by_u256) +- [Function `sub`](#0x1_bigdecimal_sub) +- [Function `sub_by_u64`](#0x1_bigdecimal_sub_by_u64) +- [Function `sub_by_u128`](#0x1_bigdecimal_sub_by_u128) +- [Function `sub_by_u256`](#0x1_bigdecimal_sub_by_u256) +- [Function `mul`](#0x1_bigdecimal_mul) +- [Function `mul_truncate`](#0x1_bigdecimal_mul_truncate) +- [Function `mul_ceil`](#0x1_bigdecimal_mul_ceil) +- [Function `mul_by_u64`](#0x1_bigdecimal_mul_by_u64) +- [Function `mul_by_u64_truncate`](#0x1_bigdecimal_mul_by_u64_truncate) +- [Function `mul_by_u64_ceil`](#0x1_bigdecimal_mul_by_u64_ceil) +- [Function `mul_by_u128`](#0x1_bigdecimal_mul_by_u128) +- [Function `mul_by_u128_truncate`](#0x1_bigdecimal_mul_by_u128_truncate) +- [Function `mul_by_u128_ceil`](#0x1_bigdecimal_mul_by_u128_ceil) +- [Function `mul_by_u256`](#0x1_bigdecimal_mul_by_u256) +- [Function `mul_by_u256_truncate`](#0x1_bigdecimal_mul_by_u256_truncate) +- [Function `mul_by_u256_ceil`](#0x1_bigdecimal_mul_by_u256_ceil) +- [Function `div`](#0x1_bigdecimal_div) +- [Function `div_by_u64`](#0x1_bigdecimal_div_by_u64) +- [Function `div_by_u128`](#0x1_bigdecimal_div_by_u128) +- [Function `div_by_u256`](#0x1_bigdecimal_div_by_u256) +- [Function `truncate`](#0x1_bigdecimal_truncate) +- [Function `truncate_u64`](#0x1_bigdecimal_truncate_u64) +- [Function `truncate_u128`](#0x1_bigdecimal_truncate_u128) +- [Function `truncate_u256`](#0x1_bigdecimal_truncate_u256) +- [Function `round_up`](#0x1_bigdecimal_round_up) +- [Function `round_up_u64`](#0x1_bigdecimal_round_up_u64) +- [Function `round_up_u128`](#0x1_bigdecimal_round_up_u128) +- [Function `round_up_u256`](#0x1_bigdecimal_round_up_u256) +- [Function `ceil`](#0x1_bigdecimal_ceil) +- [Function `ceil_u64`](#0x1_bigdecimal_ceil_u64) +- [Function `ceil_u128`](#0x1_bigdecimal_ceil_u128) +- [Function `ceil_u256`](#0x1_bigdecimal_ceil_u256) + + +
use 0x1::biguint;
+use 0x1::error;
+
+ + + + + +## Struct `BigDecimal` + + + +
struct BigDecimal has copy, drop, store
+
+ + + +##### Fields + + +
+
+scaled: biguint::BigUint +
+
+ +
+
+ + + + +## Constants + + + + + + +
const EDIVISION_BY_ZERO: u64 = 101;
+
+ + + + + + + +
const NEGATIVE_RESULT: u64 = 100;
+
+ + + + + + + +
const DECIMAL_FRACTIONAL: u64 = 1000000000000000000;
+
+ + + + + + + +
const FRACTIONAL_LENGTH: u64 = 18;
+
+ + + + + +## Function `from_u64` + +Create a BigDecimal from a u64 value by multiplying it by the fractional part. + + +
public fun from_u64(value: u64): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_u64(value: u64): BigDecimal {
+    BigDecimal {
+        scaled: biguint::mul(biguint::from_u64(value), f())
+    }
+}
+
+ + + + + +## Function `from_u128` + +Create a BigDecimal from a u128 value by multiplying it by the fractional part. + + +
public fun from_u128(value: u128): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_u128(value: u128): BigDecimal {
+    BigDecimal {
+        scaled: biguint::mul(biguint::from_u128(value), f())
+    }
+}
+
+ + + + + +## Function `from_u256` + +Create a BigDecimal from a u256 value by multiplying it by the fractional part. + + +
public fun from_u256(value: u256): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_u256(value: u256): BigDecimal {
+    BigDecimal {
+        scaled: biguint::mul(biguint::from_u256(value), f())
+    }
+}
+
+ + + + + +## Function `new` + +Create a BigDecimal from a BigUint value by multiplying it by the fractional part. + + +
public fun new(value: biguint::BigUint): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun new(value: BigUint): BigDecimal {
+    BigDecimal {
+        scaled: biguint::mul(value, f())
+    }
+}
+
+ + + + + +## Function `from_scaled` + +Create a BigDecimal from a scaled BigUint value. + + +
public fun from_scaled(scaled: biguint::BigUint): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_scaled(scaled: BigUint): BigDecimal {
+    BigDecimal { scaled: scaled }
+}
+
+ + + + + +## Function `get_scaled` + +Get the scaled value of a BigDecimal. + + +
public fun get_scaled(num: bigdecimal::BigDecimal): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun get_scaled(num: BigDecimal): BigUint {
+    num.scaled
+}
+
+ + + + + +## Function `from_scaled_le_bytes` + +Create a BigDecimal from a scaled BigUint le_bytes value. + + +
public fun from_scaled_le_bytes(le_bytes: vector<u8>): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_scaled_le_bytes(le_bytes: vector<u8>): BigDecimal {
+    BigDecimal { scaled: biguint::from_le_bytes(le_bytes) }
+}
+
+ + + + + +## Function `get_scaled_le_bytes` + + + +
public fun get_scaled_le_bytes(num: bigdecimal::BigDecimal): vector<u8>
+
+ + + +##### Implementation + + +
public fun get_scaled_le_bytes(num: BigDecimal): vector<u8> {
+    biguint::to_le_bytes(num.scaled)
+}
+
+ + + + + +## Function `from_ratio` + + + +
public fun from_ratio(numerator: biguint::BigUint, denominator: biguint::BigUint): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_ratio(numerator: BigUint, denominator: BigUint): BigDecimal {
+    assert!(
+        !biguint::is_zero(denominator), error::invalid_argument(EDIVISION_BY_ZERO)
+    );
+
+    let numerator = biguint::mul(numerator, f());
+    BigDecimal { scaled: biguint::div(numerator, denominator) }
+}
+
+ + + + + +## Function `from_ratio_u64` + + + +
public fun from_ratio_u64(numerator: u64, denominator: u64): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_ratio_u64(numerator: u64, denominator: u64): BigDecimal {
+    assert!(denominator != 0, error::invalid_argument(EDIVISION_BY_ZERO));
+
+    let numerator = biguint::from_u128(
+        (numerator as u128) * (DECIMAL_FRACTIONAL as u128)
+    );
+    let denominator = biguint::from_u64(denominator);
+
+    BigDecimal { scaled: biguint::div(numerator, denominator) }
+}
+
+ + + + + +## Function `from_ratio_u128` + + + +
public fun from_ratio_u128(numerator: u128, denominator: u128): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_ratio_u128(numerator: u128, denominator: u128): BigDecimal {
+    assert!(denominator != 0, error::invalid_argument(EDIVISION_BY_ZERO));
+
+    let numerator = biguint::from_u256(
+        (numerator as u256) * (DECIMAL_FRACTIONAL as u256)
+    );
+    let denominator = biguint::from_u128(denominator);
+
+    BigDecimal { scaled: biguint::div(numerator, denominator) }
+}
+
+ + + + + +## Function `from_ratio_u256` + + + +
public fun from_ratio_u256(numerator: u256, denominator: u256): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_ratio_u256(numerator: u256, denominator: u256): BigDecimal {
+    assert!(denominator != 0, error::invalid_argument(EDIVISION_BY_ZERO));
+
+    let numerator = biguint::mul(biguint::from_u256(numerator), f());
+    let denominator = biguint::from_u256(denominator);
+
+    BigDecimal { scaled: biguint::div(numerator, denominator) }
+}
+
+ + + + + +## Function `rev` + + + +
public fun rev(num: bigdecimal::BigDecimal): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun rev(num: BigDecimal): BigDecimal {
+    let fractional = f();
+    BigDecimal {
+        scaled: biguint::div(biguint::mul(fractional, fractional), num.scaled)
+    }
+}
+
+ + + + + +## Function `one` + + + +
public fun one(): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun one(): BigDecimal {
+    BigDecimal { scaled: f() }
+}
+
+ + + + + +## Function `zero` + + + +
public fun zero(): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun zero(): BigDecimal {
+    BigDecimal { scaled: biguint::zero() }
+}
+
+ + + + + +## Function `eq` + + + +
public fun eq(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bool
+
+ + + +##### Implementation + + +
public fun eq(num1: BigDecimal, num2: BigDecimal): bool {
+    biguint::eq(num1.scaled, num2.scaled)
+}
+
+ + + + + +## Function `lt` + + + +
public fun lt(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bool
+
+ + + +##### Implementation + + +
public fun lt(num1: BigDecimal, num2: BigDecimal): bool {
+    biguint::lt(num1.scaled, num2.scaled)
+}
+
+ + + + + +## Function `le` + + + +
public fun le(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bool
+
+ + + +##### Implementation + + +
public fun le(num1: BigDecimal, num2: BigDecimal): bool {
+    biguint::le(num1.scaled, num2.scaled)
+}
+
+ + + + + +## Function `gt` + + + +
public fun gt(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bool
+
+ + + +##### Implementation + + +
public fun gt(num1: BigDecimal, num2: BigDecimal): bool {
+    biguint::gt(num1.scaled, num2.scaled)
+}
+
+ + + + + +## Function `ge` + + + +
public fun ge(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bool
+
+ + + +##### Implementation + + +
public fun ge(num1: BigDecimal, num2: BigDecimal): bool {
+    biguint::ge(num1.scaled, num2.scaled)
+}
+
+ + + + + +## Function `is_zero` + + + +
public fun is_zero(num: bigdecimal::BigDecimal): bool
+
+ + + +##### Implementation + + +
public fun is_zero(num: BigDecimal): bool {
+    biguint::is_zero(num.scaled)
+}
+
+ + + + + +## Function `is_one` + + + +
public fun is_one(num: bigdecimal::BigDecimal): bool
+
+ + + +##### Implementation + + +
public fun is_one(num: BigDecimal): bool {
+    biguint::eq(num.scaled, f())
+}
+
+ + + + + +## Function `add` + + + +
public fun add(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun add(num1: BigDecimal, num2: BigDecimal): BigDecimal {
+    BigDecimal { scaled: biguint::add(num1.scaled, num2.scaled) }
+}
+
+ + + + + +## Function `add_by_u64` + + + +
public fun add_by_u64(num1: bigdecimal::BigDecimal, num2: u64): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun add_by_u64(num1: BigDecimal, num2: u64): BigDecimal {
+    BigDecimal {
+        scaled: biguint::add(num1.scaled, from_u64(num2).scaled)
+    }
+}
+
+ + + + + +## Function `add_by_u128` + + + +
public fun add_by_u128(num1: bigdecimal::BigDecimal, num2: u128): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun add_by_u128(num1: BigDecimal, num2: u128): BigDecimal {
+    BigDecimal {
+        scaled: biguint::add(num1.scaled, from_u128(num2).scaled)
+    }
+}
+
+ + + + + +## Function `add_by_u256` + + + +
public fun add_by_u256(num1: bigdecimal::BigDecimal, num2: u256): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun add_by_u256(num1: BigDecimal, num2: u256): BigDecimal {
+    BigDecimal {
+        scaled: biguint::add(num1.scaled, from_u256(num2).scaled)
+    }
+}
+
+ + + + + +## Function `sub` + + + +
public fun sub(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun sub(num1: BigDecimal, num2: BigDecimal): BigDecimal {
+    assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT));
+    BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) }
+}
+
+ + + + + +## Function `sub_by_u64` + + + +
public fun sub_by_u64(num1: bigdecimal::BigDecimal, num2: u64): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun sub_by_u64(num1: BigDecimal, num2: u64): BigDecimal {
+    let num2 = from_u64(num2);
+    assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT));
+    BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) }
+}
+
+ + + + + +## Function `sub_by_u128` + + + +
public fun sub_by_u128(num1: bigdecimal::BigDecimal, num2: u128): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun sub_by_u128(num1: BigDecimal, num2: u128): BigDecimal {
+    let num2 = from_u128(num2);
+    assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT));
+    BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) }
+}
+
+ + + + + +## Function `sub_by_u256` + + + +
public fun sub_by_u256(num1: bigdecimal::BigDecimal, num2: u256): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun sub_by_u256(num1: BigDecimal, num2: u256): BigDecimal {
+    let num2 = from_u256(num2);
+    assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT));
+    BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) }
+}
+
+ + + + + +## Function `mul` + + + +
public fun mul(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun mul(num1: BigDecimal, num2: BigDecimal): BigDecimal {
+    BigDecimal {
+        scaled: biguint::div(biguint::mul(num1.scaled, num2.scaled), f())
+    }
+}
+
+ + + + + +## Function `mul_truncate` + + + +
public fun mul_truncate(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun mul_truncate(num1: BigDecimal, num2: BigDecimal): BigUint {
+    truncate(mul(num1, num2))
+}
+
+ + + + + +## Function `mul_ceil` + + + +
public fun mul_ceil(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun mul_ceil(num1: BigDecimal, num2: BigDecimal): BigUint {
+    ceil(mul(num1, num2))
+}
+
+ + + + + +## Function `mul_by_u64` + + + +
public fun mul_by_u64(num1: bigdecimal::BigDecimal, num2: u64): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun mul_by_u64(num1: BigDecimal, num2: u64): BigDecimal {
+    BigDecimal { scaled: biguint::mul_by_u64(num1.scaled, num2) }
+}
+
+ + + + + +## Function `mul_by_u64_truncate` + + + +
public fun mul_by_u64_truncate(num1: bigdecimal::BigDecimal, num2: u64): u64
+
+ + + +##### Implementation + + +
public fun mul_by_u64_truncate(num1: BigDecimal, num2: u64): u64 {
+    truncate_u64(mul_by_u64(num1, num2))
+}
+
+ + + + + +## Function `mul_by_u64_ceil` + + + +
public fun mul_by_u64_ceil(num1: bigdecimal::BigDecimal, num2: u64): u64
+
+ + + +##### Implementation + + +
public fun mul_by_u64_ceil(num1: BigDecimal, num2: u64): u64 {
+    ceil_u64(mul_by_u64(num1, num2))
+}
+
+ + + + + +## Function `mul_by_u128` + + + +
public fun mul_by_u128(num1: bigdecimal::BigDecimal, num2: u128): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun mul_by_u128(num1: BigDecimal, num2: u128): BigDecimal {
+    BigDecimal { scaled: biguint::mul_by_u128(num1.scaled, num2) }
+}
+
+ + + + + +## Function `mul_by_u128_truncate` + + + +
public fun mul_by_u128_truncate(num1: bigdecimal::BigDecimal, num2: u128): u128
+
+ + + +##### Implementation + + +
public fun mul_by_u128_truncate(num1: BigDecimal, num2: u128): u128 {
+    truncate_u128(mul_by_u128(num1, num2))
+}
+
+ + + + + +## Function `mul_by_u128_ceil` + + + +
public fun mul_by_u128_ceil(num1: bigdecimal::BigDecimal, num2: u128): u128
+
+ + + +##### Implementation + + +
public fun mul_by_u128_ceil(num1: BigDecimal, num2: u128): u128 {
+    ceil_u128(mul_by_u128(num1, num2))
+}
+
+ + + + + +## Function `mul_by_u256` + + + +
public fun mul_by_u256(num1: bigdecimal::BigDecimal, num2: u256): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun mul_by_u256(num1: BigDecimal, num2: u256): BigDecimal {
+    BigDecimal { scaled: biguint::mul_by_u256(num1.scaled, num2) }
+}
+
+ + + + + +## Function `mul_by_u256_truncate` + + + +
public fun mul_by_u256_truncate(num1: bigdecimal::BigDecimal, num2: u256): u256
+
+ + + +##### Implementation + + +
public fun mul_by_u256_truncate(num1: BigDecimal, num2: u256): u256 {
+    truncate_u256(mul_by_u256(num1, num2))
+}
+
+ + + + + +## Function `mul_by_u256_ceil` + + + +
public fun mul_by_u256_ceil(num1: bigdecimal::BigDecimal, num2: u256): u256
+
+ + + +##### Implementation + + +
public fun mul_by_u256_ceil(num1: BigDecimal, num2: u256): u256 {
+    ceil_u256(mul_by_u256(num1, num2))
+}
+
+ + + + + +## Function `div` + + + +
public fun div(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun div(num1: BigDecimal, num2: BigDecimal): BigDecimal {
+    assert!(
+        !biguint::is_zero(num2.scaled), error::invalid_argument(EDIVISION_BY_ZERO)
+    );
+
+    BigDecimal {
+        scaled: biguint::div(biguint::mul(num1.scaled, f()), num2.scaled)
+    }
+}
+
+ + + + + +## Function `div_by_u64` + + + +
public fun div_by_u64(num1: bigdecimal::BigDecimal, num2: u64): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun div_by_u64(num1: BigDecimal, num2: u64): BigDecimal {
+    assert!(num2 != 0, error::invalid_argument(EDIVISION_BY_ZERO));
+
+    BigDecimal { scaled: biguint::div_by_u64(num1.scaled, num2) }
+}
+
+ + + + + +## Function `div_by_u128` + + + +
public fun div_by_u128(num1: bigdecimal::BigDecimal, num2: u128): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun div_by_u128(num1: BigDecimal, num2: u128): BigDecimal {
+    assert!(num2 != 0, error::invalid_argument(EDIVISION_BY_ZERO));
+
+    BigDecimal { scaled: biguint::div_by_u128(num1.scaled, num2) }
+}
+
+ + + + + +## Function `div_by_u256` + + + +
public fun div_by_u256(num1: bigdecimal::BigDecimal, num2: u256): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun div_by_u256(num1: BigDecimal, num2: u256): BigDecimal {
+    assert!(num2 != 0, error::invalid_argument(EDIVISION_BY_ZERO));
+
+    BigDecimal { scaled: biguint::div_by_u256(num1.scaled, num2) }
+}
+
+ + + + + +## Function `truncate` + + + +
public fun truncate(num: bigdecimal::BigDecimal): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun truncate(num: BigDecimal): BigUint {
+    biguint::div(num.scaled, f())
+}
+
+ + + + + +## Function `truncate_u64` + + + +
public fun truncate_u64(num: bigdecimal::BigDecimal): u64
+
+ + + +##### Implementation + + +
public fun truncate_u64(num: BigDecimal): u64 {
+    biguint::to_u64(truncate(num))
+}
+
+ + + + + +## Function `truncate_u128` + + + +
public fun truncate_u128(num: bigdecimal::BigDecimal): u128
+
+ + + +##### Implementation + + +
public fun truncate_u128(num: BigDecimal): u128 {
+    biguint::to_u128(truncate(num))
+}
+
+ + + + + +## Function `truncate_u256` + + + +
public fun truncate_u256(num: bigdecimal::BigDecimal): u256
+
+ + + +##### Implementation + + +
public fun truncate_u256(num: BigDecimal): u256 {
+    biguint::to_u256(truncate(num))
+}
+
+ + + + + +## Function `round_up` + + + +
public fun round_up(num: bigdecimal::BigDecimal): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun round_up(num: BigDecimal): BigUint {
+    biguint::div(biguint::add(num.scaled, hf()), f())
+}
+
+ + + + + +## Function `round_up_u64` + + + +
public fun round_up_u64(num: bigdecimal::BigDecimal): u64
+
+ + + +##### Implementation + + +
public fun round_up_u64(num: BigDecimal): u64 {
+    biguint::to_u64(round_up(num))
+}
+
+ + + + + +## Function `round_up_u128` + + + +
public fun round_up_u128(num: bigdecimal::BigDecimal): u128
+
+ + + +##### Implementation + + +
public fun round_up_u128(num: BigDecimal): u128 {
+    biguint::to_u128(round_up(num))
+}
+
+ + + + + +## Function `round_up_u256` + + + +
public fun round_up_u256(num: bigdecimal::BigDecimal): u256
+
+ + + +##### Implementation + + +
public fun round_up_u256(num: BigDecimal): u256 {
+    biguint::to_u256(round_up(num))
+}
+
+ + + + + +## Function `ceil` + + + +
public fun ceil(num: bigdecimal::BigDecimal): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun ceil(num: BigDecimal): BigUint {
+    biguint::div(biguint::add(num.scaled, f_1()), f())
+}
+
+ + + + + +## Function `ceil_u64` + + + +
public fun ceil_u64(num: bigdecimal::BigDecimal): u64
+
+ + + +##### Implementation + + +
public fun ceil_u64(num: BigDecimal): u64 {
+    biguint::to_u64(ceil(num))
+}
+
+ + + + + +## Function `ceil_u128` + + + +
public fun ceil_u128(num: bigdecimal::BigDecimal): u128
+
+ + + +##### Implementation + + +
public fun ceil_u128(num: BigDecimal): u128 {
+    biguint::to_u128(ceil(num))
+}
+
+ + + + + +## Function `ceil_u256` + + + +
public fun ceil_u256(num: bigdecimal::BigDecimal): u256
+
+ + + +##### Implementation + + +
public fun ceil_u256(num: BigDecimal): u256 {
+    biguint::to_u256(ceil(num))
+}
+
diff --git a/initia_stdlib/doc/biguint.md b/initia_stdlib/doc/biguint.md new file mode 100644 index 0000000..2a8038b --- /dev/null +++ b/initia_stdlib/doc/biguint.md @@ -0,0 +1,823 @@ + + + +# Module `0x1::biguint` + + + +- [Struct `BigUint`](#0x1_biguint_BigUint) +- [Constants](#@Constants_0) +- [Function `from_le_bytes`](#0x1_biguint_from_le_bytes) +- [Function `zero`](#0x1_biguint_zero) +- [Function `one`](#0x1_biguint_one) +- [Function `from_u64`](#0x1_biguint_from_u64) +- [Function `to_u64`](#0x1_biguint_to_u64) +- [Function `from_u128`](#0x1_biguint_from_u128) +- [Function `to_u128`](#0x1_biguint_to_u128) +- [Function `from_u256`](#0x1_biguint_from_u256) +- [Function `to_u256`](#0x1_biguint_to_u256) +- [Function `to_le_bytes`](#0x1_biguint_to_le_bytes) +- [Function `add`](#0x1_biguint_add) +- [Function `add_by_u64`](#0x1_biguint_add_by_u64) +- [Function `add_by_u128`](#0x1_biguint_add_by_u128) +- [Function `add_by_u256`](#0x1_biguint_add_by_u256) +- [Function `sub`](#0x1_biguint_sub) +- [Function `sub_by_u64`](#0x1_biguint_sub_by_u64) +- [Function `sub_by_u128`](#0x1_biguint_sub_by_u128) +- [Function `sub_by_u256`](#0x1_biguint_sub_by_u256) +- [Function `mul`](#0x1_biguint_mul) +- [Function `mul_by_u64`](#0x1_biguint_mul_by_u64) +- [Function `mul_by_u128`](#0x1_biguint_mul_by_u128) +- [Function `mul_by_u256`](#0x1_biguint_mul_by_u256) +- [Function `div`](#0x1_biguint_div) +- [Function `div_by_u64`](#0x1_biguint_div_by_u64) +- [Function `div_by_u128`](#0x1_biguint_div_by_u128) +- [Function `div_by_u256`](#0x1_biguint_div_by_u256) +- [Function `eq`](#0x1_biguint_eq) +- [Function `lt`](#0x1_biguint_lt) +- [Function `le`](#0x1_biguint_le) +- [Function `gt`](#0x1_biguint_gt) +- [Function `ge`](#0x1_biguint_ge) +- [Function `is_zero`](#0x1_biguint_is_zero) +- [Function `is_one`](#0x1_biguint_is_one) + + +
+ + + + + +## Struct `BigUint` + + + +
struct BigUint has copy, drop, store
+
+ + + +##### Fields + + +
+
+bytes: vector<u8> +
+
+ +
+
+ + + + +## Constants + + + + + + +
const CAST_OVERFLOW: u64 = 102;
+
+ + + + + + + +
const EDIVISION_BY_ZERO: u64 = 101;
+
+ + + + + + + +
const INVALID_NUMERIC_TYPE: u64 = 103;
+
+ + + + + + + +
const NEGATIVE_RESULT: u64 = 100;
+
+ + + + + +## Function `from_le_bytes` + +Create a new BigUint from little-endian bytes. + + +
public fun from_le_bytes(le_bytes: vector<u8>): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun from_le_bytes(le_bytes: vector<u8>): BigUint {
+    BigUint { bytes: le_bytes }
+}
+
+ + + + + +## Function `zero` + + + +
public fun zero(): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun zero(): BigUint {
+    from_u64(0)
+}
+
+ + + + + +## Function `one` + + + +
public fun one(): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun one(): BigUint {
+    from_u64(1)
+}
+
+ + + + + +## Function `from_u64` + + + +
public fun from_u64(num: u64): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun from_u64(num: u64): BigUint {
+    let num_bytes = new_internal(num);
+    BigUint { bytes: num_bytes }
+}
+
+ + + + + +## Function `to_u64` + + + +
public fun to_u64(num: biguint::BigUint): u64
+
+ + + +##### Implementation + + +
public fun to_u64(num: BigUint): u64 {
+    cast_internal<u64>(num.bytes)
+}
+
+ + + + + +## Function `from_u128` + + + +
public fun from_u128(num: u128): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun from_u128(num: u128): BigUint {
+    let num_bytes = new_internal(num);
+    BigUint { bytes: num_bytes }
+}
+
+ + + + + +## Function `to_u128` + + + +
public fun to_u128(num: biguint::BigUint): u128
+
+ + + +##### Implementation + + +
public fun to_u128(num: BigUint): u128 {
+    cast_internal<u128>(num.bytes)
+}
+
+ + + + + +## Function `from_u256` + + + +
public fun from_u256(num: u256): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun from_u256(num: u256): BigUint {
+    let num_bytes = new_internal(num);
+    BigUint { bytes: num_bytes }
+}
+
+ + + + + +## Function `to_u256` + + + +
public fun to_u256(num: biguint::BigUint): u256
+
+ + + +##### Implementation + + +
public fun to_u256(num: BigUint): u256 {
+    cast_internal<u256>(num.bytes)
+}
+
+ + + + + +## Function `to_le_bytes` + + + +
public fun to_le_bytes(num: biguint::BigUint): vector<u8>
+
+ + + +##### Implementation + + +
public fun to_le_bytes(num: BigUint): vector<u8> {
+    num.bytes
+}
+
+ + + + + +## Function `add` + + + +
public fun add(num1: biguint::BigUint, num2: biguint::BigUint): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun add(num1: BigUint, num2: BigUint): BigUint {
+    let result_bytes = add_internal(num1.bytes, num2.bytes);
+    BigUint { bytes: result_bytes }
+}
+
+ + + + + +## Function `add_by_u64` + + + +
public fun add_by_u64(num1: biguint::BigUint, num2: u64): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun add_by_u64(num1: BigUint, num2: u64): BigUint {
+    let num2 = from_u64(num2);
+    add(num1, num2)
+}
+
+ + + + + +## Function `add_by_u128` + + + +
public fun add_by_u128(num1: biguint::BigUint, num2: u128): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun add_by_u128(num1: BigUint, num2: u128): BigUint {
+    let num2 = from_u128(num2);
+    add(num1, num2)
+}
+
+ + + + + +## Function `add_by_u256` + + + +
public fun add_by_u256(num1: biguint::BigUint, num2: u256): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun add_by_u256(num1: BigUint, num2: u256): BigUint {
+    let num2 = from_u256(num2);
+    add(num1, num2)
+}
+
+ + + + + +## Function `sub` + + + +
public fun sub(num1: biguint::BigUint, num2: biguint::BigUint): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun sub(num1: BigUint, num2: BigUint): BigUint {
+    let result_bytes = sub_internal(num1.bytes, num2.bytes);
+    BigUint { bytes: result_bytes }
+}
+
+ + + + + +## Function `sub_by_u64` + + + +
public fun sub_by_u64(num1: biguint::BigUint, num2: u64): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun sub_by_u64(num1: BigUint, num2: u64): BigUint {
+    let num2 = from_u64(num2);
+    sub(num1, num2)
+}
+
+ + + + + +## Function `sub_by_u128` + + + +
public fun sub_by_u128(num1: biguint::BigUint, num2: u128): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun sub_by_u128(num1: BigUint, num2: u128): BigUint {
+    let num2 = from_u128(num2);
+    sub(num1, num2)
+}
+
+ + + + + +## Function `sub_by_u256` + + + +
public fun sub_by_u256(num1: biguint::BigUint, num2: u256): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun sub_by_u256(num1: BigUint, num2: u256): BigUint {
+    let num2 = from_u256(num2);
+    sub(num1, num2)
+}
+
+ + + + + +## Function `mul` + + + +
public fun mul(num1: biguint::BigUint, num2: biguint::BigUint): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun mul(num1: BigUint, num2: BigUint): BigUint {
+    let result_bytes = mul_internal(num1.bytes, num2.bytes);
+    BigUint { bytes: result_bytes }
+}
+
+ + + + + +## Function `mul_by_u64` + + + +
public fun mul_by_u64(num1: biguint::BigUint, num2: u64): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun mul_by_u64(num1: BigUint, num2: u64): BigUint {
+    let num2 = from_u64(num2);
+    mul(num1, num2)
+}
+
+ + + + + +## Function `mul_by_u128` + + + +
public fun mul_by_u128(num1: biguint::BigUint, num2: u128): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun mul_by_u128(num1: BigUint, num2: u128): BigUint {
+    let num2 = from_u128(num2);
+    mul(num1, num2)
+}
+
+ + + + + +## Function `mul_by_u256` + + + +
public fun mul_by_u256(num1: biguint::BigUint, num2: u256): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun mul_by_u256(num1: BigUint, num2: u256): BigUint {
+    let num2 = from_u256(num2);
+    mul(num1, num2)
+}
+
+ + + + + +## Function `div` + + + +
public fun div(num1: biguint::BigUint, num2: biguint::BigUint): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun div(num1: BigUint, num2: BigUint): BigUint {
+    let result_bytes = div_internal(num1.bytes, num2.bytes);
+    BigUint { bytes: result_bytes }
+}
+
+ + + + + +## Function `div_by_u64` + + + +
public fun div_by_u64(num1: biguint::BigUint, num2: u64): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun div_by_u64(num1: BigUint, num2: u64): BigUint {
+    let num2 = from_u64(num2);
+    div(num1, num2)
+}
+
+ + + + + +## Function `div_by_u128` + + + +
public fun div_by_u128(num1: biguint::BigUint, num2: u128): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun div_by_u128(num1: BigUint, num2: u128): BigUint {
+    let num2 = from_u128(num2);
+    div(num1, num2)
+}
+
+ + + + + +## Function `div_by_u256` + + + +
public fun div_by_u256(num1: biguint::BigUint, num2: u256): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun div_by_u256(num1: BigUint, num2: u256): BigUint {
+    let num2 = from_u256(num2);
+    div(num1, num2)
+}
+
+ + + + + +## Function `eq` + + + +
public fun eq(num1: biguint::BigUint, num2: biguint::BigUint): bool
+
+ + + +##### Implementation + + +
public fun eq(num1: BigUint, num2: BigUint): bool {
+    num1.bytes == num2.bytes
+}
+
+ + + + + +## Function `lt` + + + +
public fun lt(num1: biguint::BigUint, num2: biguint::BigUint): bool
+
+ + + +##### Implementation + + +
public fun lt(num1: BigUint, num2: BigUint): bool {
+    lt_internal(num1.bytes, num2.bytes)
+}
+
+ + + + + +## Function `le` + + + +
public fun le(num1: biguint::BigUint, num2: biguint::BigUint): bool
+
+ + + +##### Implementation + + +
public fun le(num1: BigUint, num2: BigUint): bool {
+    le_internal(num1.bytes, num2.bytes)
+}
+
+ + + + + +## Function `gt` + + + +
public fun gt(num1: biguint::BigUint, num2: biguint::BigUint): bool
+
+ + + +##### Implementation + + +
public fun gt(num1: BigUint, num2: BigUint): bool {
+    gt_internal(num1.bytes, num2.bytes)
+}
+
+ + + + + +## Function `ge` + + + +
public fun ge(num1: biguint::BigUint, num2: biguint::BigUint): bool
+
+ + + +##### Implementation + + +
public fun ge(num1: BigUint, num2: BigUint): bool {
+    ge_internal(num1.bytes, num2.bytes)
+}
+
+ + + + + +## Function `is_zero` + + + +
public fun is_zero(num: biguint::BigUint): bool
+
+ + + +##### Implementation + + +
public fun is_zero(num: BigUint): bool {
+    eq(num, zero())
+}
+
+ + + + + +## Function `is_one` + + + +
public fun is_one(num: biguint::BigUint): bool
+
+ + + +##### Implementation + + +
public fun is_one(num: BigUint): bool {
+    eq(num, one())
+}
+
diff --git a/initia_stdlib/doc/block.md b/initia_stdlib/doc/block.md index 133c6d0..e521ad6 100644 --- a/initia_stdlib/doc/block.md +++ b/initia_stdlib/doc/block.md @@ -6,6 +6,8 @@ - [Function `get_block_info`](#0x1_block_get_block_info) +- [Function `get_current_block_height`](#0x1_block_get_current_block_height) +- [Function `get_current_block_timestamp`](#0x1_block_get_current_block_timestamp)
@@ -23,8 +25,7 @@ -
-Implementation +##### Implementation
native public fun get_block_info(): (u64, u64);
@@ -32,4 +33,46 @@
 
 
 
-
+ + +## Function `get_current_block_height` + + + +
#[view]
+public fun get_current_block_height(): u64
+
+ + + +##### Implementation + + +
public fun get_current_block_height(): u64 {
+    let (height, _) = get_block_info();
+    height
+}
+
+ + + + + +## Function `get_current_block_timestamp` + + + +
#[view]
+public fun get_current_block_timestamp(): u64
+
+ + + +##### Implementation + + +
public fun get_current_block_timestamp(): u64 {
+    let (_, timestamp) = get_block_info();
+    timestamp
+}
+
diff --git a/initia_stdlib/doc/code.md b/initia_stdlib/doc/code.md index bbb0dd6..dceb074 100644 --- a/initia_stdlib/doc/code.md +++ b/initia_stdlib/doc/code.md @@ -11,17 +11,20 @@ - [Struct `ModulePublishedEvent`](#0x1_code_ModulePublishedEvent) - [Constants](#@Constants_0) - [Function `can_change_upgrade_policy_to`](#0x1_code_can_change_upgrade_policy_to) -- [Function `init_module`](#0x1_code_init_module) +- [Function `allowed_publishers`](#0x1_code_allowed_publishers) +- [Function `total_modules`](#0x1_code_total_modules) - [Function `init_genesis`](#0x1_code_init_genesis) - [Function `set_allowed_publishers`](#0x1_code_set_allowed_publishers) -- [Function `assert_allowed`](#0x1_code_assert_allowed) +- [Function `freeze_code_object`](#0x1_code_freeze_code_object) - [Function `publish`](#0x1_code_publish) -- [Function `request_publish`](#0x1_code_request_publish)
use 0x1::error;
 use 0x1::event;
+use 0x1::object;
+use 0x1::option;
 use 0x1::signer;
+use 0x1::simple_map;
 use 0x1::string;
 use 0x1::table;
 use 0x1::vector;
@@ -40,8 +43,7 @@
 
 
 
-
-Fields +##### Fields
@@ -52,11 +54,15 @@ It is a list of addresses with permission to distribute contracts, and an empty list is interpreted as allowing anyone to distribute. +
+total_modules: u64 +
+
+ The total number of modules published. +
-
- ## Resource `MetadataStore` @@ -68,8 +74,7 @@ -
-Fields +##### Fields
@@ -82,8 +87,6 @@
-
- ## Struct `ModuleMetadata` @@ -96,8 +99,7 @@ Describes an upgrade policy -
-Fields +##### Fields
@@ -110,8 +112,6 @@ Describes an upgrade policy
-
- ## Struct `ModulePublishedEvent` @@ -124,8 +124,7 @@ Describes an upgrade policy -
-Fields +##### Fields
@@ -144,13 +143,31 @@ Describes an upgrade policy
-
- ## Constants + + +code_object does not exist. + + +
const ECODE_OBJECT_DOES_NOT_EXIST: u64 = 9;
+
+ + + + + +The module ID is duplicated. + + +
const EDUPLICATE_MODULE_ID: u64 = 7;
+
+ + + allowed_publishers argument is invalid. @@ -181,6 +198,16 @@ The operation is expected to be executed by chain signer. + + +Not the owner of the package registry. + + +
const ENOT_PACKAGE_OWNER: u64 = 8;
+
+ + + Cannot upgrade an immutable package. @@ -232,16 +259,6 @@ Whether the modules in the package are immutable and cannot be upgraded. - - -The upgrade policy is unspecified. - - -
const UPGRADE_POLICY_UNSPECIFIED: u8 = 0;
-
- - - ## Function `can_change_upgrade_policy_to` @@ -255,8 +272,7 @@ strengthened but not weakened. -
-Implementation +##### Implementation
public fun can_change_upgrade_policy_to(from: u8, to: u8): bool {
@@ -266,33 +282,51 @@ strengthened but not weakened.
 
 
 
-
- - + -## Function `init_module` +## Function `allowed_publishers` -
fun init_module(chain: &signer)
+
#[view]
+public fun allowed_publishers(): vector<address>
 
-
-Implementation +##### Implementation -
fun init_module(chain: &signer) {
-    move_to(chain, ModuleStore {
-        allowed_publishers: vector[],
-    });
+
public fun allowed_publishers(): vector<address> acquires ModuleStore {
+    let module_store = borrow_global<ModuleStore>(@initia_std);
+    module_store.allowed_publishers
 }
 
-
+ + +## Function `total_modules` + + + +
#[view]
+public fun total_modules(): u64
+
+ + + +##### Implementation + + +
public fun total_modules(): u64 acquires ModuleStore {
+    let module_store = borrow_global<ModuleStore>(@initia_std);
+    module_store.total_modules
+}
+
+ + @@ -305,38 +339,41 @@ strengthened but not weakened. -
-Implementation +##### Implementation
public entry fun init_genesis(
-    chain: &signer,
-    module_ids: vector<String>,
-    allowed_publishers: vector<address>,
+    chain: &signer, module_ids: vector<String>, allowed_publishers: vector<address>
 ) acquires ModuleStore {
-    assert!(signer::address_of(chain) == @initia_std, error::permission_denied(EINVALID_CHAIN_OPERATOR));
+    assert!(
+        signer::address_of(chain) == @initia_std,
+        error::permission_denied(EINVALID_CHAIN_OPERATOR)
+    );
 
     let metadata_table = table::new<String, ModuleMetadata>();
-    vector::for_each_ref(&module_ids,
+    vector::for_each_ref(
+        &module_ids,
         |module_id| {
-            table::add<String, ModuleMetadata>(&mut metadata_table, *module_id, ModuleMetadata {
-                upgrade_policy: UPGRADE_POLICY_COMPATIBLE,
-            });
+            table::add<String, ModuleMetadata>(
+                &mut metadata_table,
+                *module_id,
+                ModuleMetadata { upgrade_policy: UPGRADE_POLICY_COMPATIBLE }
+            );
         }
     );
 
-    move_to<MetadataStore>(chain, MetadataStore {
-        metadata: metadata_table,
-    });
+    move_to<MetadataStore>(
+        chain,
+        MetadataStore { metadata: metadata_table }
+    );
 
     set_allowed_publishers(chain, allowed_publishers);
+    increase_total_modules(vector::length(&module_ids));
 }
 
-
- ## Function `set_allowed_publishers` @@ -348,12 +385,16 @@ strengthened but not weakened. -
-Implementation +##### Implementation -
public entry fun set_allowed_publishers(chain: &signer, allowed_publishers: vector<address>) acquires ModuleStore {
-    assert!(signer::address_of(chain) == @initia_std, error::permission_denied(EINVALID_CHAIN_OPERATOR));
+
public entry fun set_allowed_publishers(
+    chain: &signer, allowed_publishers: vector<address>
+) acquires ModuleStore {
+    assert!(
+        signer::address_of(chain) == @initia_std,
+        error::permission_denied(EINVALID_CHAIN_OPERATOR)
+    );
     assert_allowed(&allowed_publishers, @initia_std);
 
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
@@ -363,35 +404,48 @@ strengthened but not weakened.
 
 
 
-
+ - +## Function `freeze_code_object` -## Function `assert_allowed` - -
fun assert_allowed(allowed_publishers: &vector<address>, addr: address)
+
public fun freeze_code_object(publisher: &signer, code_object: object::Object<code::MetadataStore>)
 
-
-Implementation +##### Implementation -
fun assert_allowed(allowed_publishers: &vector<address>, addr: address) {
+
public fun freeze_code_object(
+    publisher: &signer, code_object: Object<MetadataStore>
+) acquires MetadataStore {
+    let code_object_addr = object::object_address(&code_object);
+    assert!(
+        exists<MetadataStore>(code_object_addr),
+        error::not_found(ECODE_OBJECT_DOES_NOT_EXIST)
+    );
     assert!(
-        vector::is_empty(allowed_publishers) || vector::contains(allowed_publishers, &addr),
-        error::invalid_argument(EINVALID_ALLOWED_PUBLISHERS),
-    )
+        object::is_owner(code_object, signer::address_of(publisher)),
+        error::permission_denied(ENOT_PACKAGE_OWNER)
+    );
+
+    let registry = borrow_global_mut<MetadataStore>(code_object_addr);
+    let iter = table::iter_mut(
+        &mut registry.metadata, option::none(), option::none(), 1
+    );
+    loop {
+        if (!table::prepare_mut(iter)) { break };
+
+        let (_, metadata) = table::next_mut(iter);
+        metadata.upgrade_policy = UPGRADE_POLICY_IMMUTABLE;
+    }
 }
 
-
- ## Function `publish` @@ -405,93 +459,95 @@ package. -
-Implementation +##### Implementation
public entry fun publish(
     owner: &signer,
     module_ids: vector<String>, // 0x1::coin
     code: vector<vector<u8>>,
-    upgrade_policy: u8,
+    upgrade_policy: u8
 ) acquires ModuleStore, MetadataStore {
     // Disallow incompatible upgrade mode. Governance can decide later if this should be reconsidered.
-    assert!(vector::length(&code) == vector::length(&module_ids), error::invalid_argument(EINVALID_ARGUMENTS));
+    assert!(
+        vector::length(&code) == vector::length(&module_ids),
+        error::invalid_argument(EINVALID_ARGUMENTS)
+    );
+
+    // duplication check
+    let module_ids_set = simple_map::create<String, bool>();
+    vector::for_each_ref(
+        &module_ids,
+        |module_id| {
+            assert!(
+                !simple_map::contains_key(&module_ids_set, module_id),
+                error::invalid_argument(EDUPLICATE_MODULE_ID)
+            );
+            simple_map::add(
+                &mut module_ids_set,
+                *module_id,
+                true
+            );
+        }
+    );
 
     // Check whether arbitrary publish is allowed or not.
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
     assert!(
-        upgrade_policy > UPGRADE_POLICY_UNSPECIFIED,
-        error::invalid_argument(EUPGRADE_POLICY_UNSPECIFIED),
+        upgrade_policy == UPGRADE_POLICY_COMPATIBLE
+            || upgrade_policy == UPGRADE_POLICY_IMMUTABLE,
+        error::invalid_argument(EUPGRADE_POLICY_UNSPECIFIED)
     );
 
     let addr = signer::address_of(owner);
     assert_allowed(&module_store.allowed_publishers, addr);
 
     if (!exists<MetadataStore>(addr)) {
-        move_to<MetadataStore>(owner, MetadataStore {
-            metadata: table::new(),
-        });
+        move_to<MetadataStore>(
+            owner,
+            MetadataStore { metadata: table::new() }
+        );
     };
 
     // Check upgradability
     let metadata_table = &mut borrow_global_mut<MetadataStore>(addr).metadata;
-    vector::for_each_ref(&module_ids,
+    vector::for_each_ref(
+        &module_ids,
         |module_id| {
             if (table::contains<String, ModuleMetadata>(metadata_table, *module_id)) {
-                let metadata = table::borrow_mut<String, ModuleMetadata>(metadata_table, *module_id);
-                assert!(metadata.upgrade_policy < UPGRADE_POLICY_IMMUTABLE,
-                    error::invalid_argument(EUPGRADE_IMMUTABLE));
-                assert!(can_change_upgrade_policy_to(metadata.upgrade_policy, upgrade_policy),
-                    error::invalid_argument(EUPGRADE_WEAKER_POLICY));
+                let metadata =
+                    table::borrow_mut<String, ModuleMetadata>(
+                        metadata_table, *module_id
+                    );
+                assert!(
+                    metadata.upgrade_policy < UPGRADE_POLICY_IMMUTABLE,
+                    error::invalid_argument(EUPGRADE_IMMUTABLE)
+                );
+                assert!(
+                    can_change_upgrade_policy_to(
+                        metadata.upgrade_policy,
+                        upgrade_policy
+                    ),
+                    error::invalid_argument(EUPGRADE_WEAKER_POLICY)
+                );
 
                 metadata.upgrade_policy = upgrade_policy;
             } else {
-                table::add<String, ModuleMetadata>(metadata_table, *module_id, ModuleMetadata {
-                    upgrade_policy,
-                });
+                table::add<String, ModuleMetadata>(
+                    metadata_table,
+                    *module_id,
+                    ModuleMetadata { upgrade_policy }
+                );
             };
 
-            event::emit(ModulePublishedEvent {
-                module_id: *module_id,
-                upgrade_policy,
-            });
+            event::emit(
+                ModulePublishedEvent { module_id: *module_id, upgrade_policy }
+            );
         }
     );
 
     // Request publish
-    request_publish(addr, module_ids, code, upgrade_policy)
+    increase_total_modules(vector::length(&module_ids));
+    request_publish(addr, module_ids, code)
 }
 
- - - -
- - - -## Function `request_publish` - -Native function to initiate module loading - - -
fun request_publish(owner: address, expected_modules: vector<string::String>, code: vector<vector<u8>>, policy: u8)
-
- - - -
-Implementation - - -
native fun request_publish(
-    owner: address,
-    expected_modules: vector<String>,
-    code: vector<vector<u8>>,
-    policy: u8
-);
-
- - - -
diff --git a/initia_stdlib/doc/coin.md b/initia_stdlib/doc/coin.md index a7e3c4b..c50801a 100644 --- a/initia_stdlib/doc/coin.md +++ b/initia_stdlib/doc/coin.md @@ -12,6 +12,8 @@ TODO - make is_module_account or some blacklist from freeze. - [Struct `BurnCapability`](#0x1_coin_BurnCapability) - [Struct `FreezeCapability`](#0x1_coin_FreezeCapability) - [Constants](#@Constants_0) +- [Function `sudo_transfer`](#0x1_coin_sudo_transfer) +- [Function `sudo_deposit`](#0x1_coin_sudo_deposit) - [Function `initialize`](#0x1_coin_initialize) - [Function `initialize_and_generate_extend_ref`](#0x1_coin_initialize_and_generate_extend_ref) - [Function `withdraw`](#0x1_coin_withdraw) @@ -32,7 +34,6 @@ TODO - make is_module_account or some blacklist from freeze. - [Function `decimals`](#0x1_coin_decimals) - [Function `metadata_address`](#0x1_coin_metadata_address) - [Function `metadata`](#0x1_coin_metadata) -- [Function `is_coin_initialized`](#0x1_coin_is_coin_initialized) - [Function `is_coin`](#0x1_coin_is_coin) - [Function `is_coin_by_symbol`](#0x1_coin_is_coin_by_symbol) - [Function `metadata_to_denom`](#0x1_coin_metadata_to_denom) @@ -40,6 +41,7 @@ TODO - make is_module_account or some blacklist from freeze.
use 0x1::bcs;
+use 0x1::error;
 use 0x1::event;
 use 0x1::from_bcs;
 use 0x1::fungible_asset;
@@ -47,6 +49,7 @@ TODO - make is_module_account or some blacklist from freeze.
 use 0x1::object;
 use 0x1::option;
 use 0x1::primary_fungible_store;
+use 0x1::signer;
 use 0x1::string;
 
@@ -63,8 +66,7 @@ TODO - make is_module_account or some blacklist from freeze. -
-Fields +##### Fields
@@ -89,8 +91,6 @@ TODO - make is_module_account or some blacklist from freeze.
-
- ## Struct `CoinCreatedEvent` @@ -103,8 +103,7 @@ TODO - make is_module_account or some blacklist from freeze. -
-Fields +##### Fields
@@ -117,8 +116,6 @@ TODO - make is_module_account or some blacklist from freeze.
-
- ## Struct `MintCapability` @@ -130,8 +127,7 @@ TODO - make is_module_account or some blacklist from freeze. -
-Fields +##### Fields
@@ -144,8 +140,6 @@ TODO - make is_module_account or some blacklist from freeze.
-
- ## Struct `BurnCapability` @@ -157,8 +151,7 @@ TODO - make is_module_account or some blacklist from freeze. -
-Fields +##### Fields
@@ -171,8 +164,6 @@ TODO - make is_module_account or some blacklist from freeze.
-
- ## Struct `FreezeCapability` @@ -184,8 +175,7 @@ TODO - make is_module_account or some blacklist from freeze. -
-Fields +##### Fields
@@ -198,8 +188,6 @@ TODO - make is_module_account or some blacklist from freeze.
-
- ## Constants @@ -225,6 +213,67 @@ Only fungible asset metadata owner can make changes. + + + + +
const EUNAUTHORIZED: u64 = 1;
+
+ + + + + +## Function `sudo_transfer` + + + +
public entry fun sudo_transfer(chain: &signer, sender: &signer, recipient: address, metadata: object::Object<fungible_asset::Metadata>, amount: u64)
+
+ + + +##### Implementation + + +
public entry fun sudo_transfer(
+    chain: &signer,
+    sender: &signer,
+    recipient: address,
+    metadata: Object<Metadata>,
+    amount: u64
+) {
+    check_sudo(chain);
+
+    primary_fungible_store::sudo_transfer(sender, metadata, recipient, amount)
+}
+
+ + + + + +## Function `sudo_deposit` + + + +
public(friend) fun sudo_deposit(account_addr: address, fa: fungible_asset::FungibleAsset)
+
+ + + +##### Implementation + + +
public(friend) fun sudo_deposit(
+    account_addr: address, fa: FungibleAsset
+) {
+    primary_fungible_store::sudo_deposit(account_addr, fa)
+}
+
+ + + ## Function `initialize` @@ -236,28 +285,28 @@ Only fungible asset metadata owner can make changes. -
-Implementation +##### Implementation -
public fun initialize (
+
public fun initialize(
     creator: &signer,
     maximum_supply: Option<u128>,
     name: String,
     symbol: String,
     decimals: u8,
     icon_uri: String,
-    project_uri: String,
+    project_uri: String
 ): (MintCapability, BurnCapability, FreezeCapability) {
-    let (mint_cap, burn_cap, freeze_cap, _) = initialize_and_generate_extend_ref(
-        creator,
-        maximum_supply,
-        name,
-        symbol,
-        decimals,
-        icon_uri,
-        project_uri,
-    );
+    let (mint_cap, burn_cap, freeze_cap, _) =
+        initialize_and_generate_extend_ref(
+            creator,
+            maximum_supply,
+            name,
+            symbol,
+            decimals,
+            icon_uri,
+            project_uri
+        );
 
     (mint_cap, burn_cap, freeze_cap)
 }
@@ -265,8 +314,6 @@ Only fungible asset metadata owner can make changes.
 
 
 
-
- ## Function `initialize_and_generate_extend_ref` @@ -278,21 +325,24 @@ Only fungible asset metadata owner can make changes. -
-Implementation +##### Implementation -
public fun initialize_and_generate_extend_ref (
+
public fun initialize_and_generate_extend_ref(
     creator: &signer,
     maximum_supply: Option<u128>,
     name: String,
     symbol: String,
     decimals: u8,
     icon_uri: String,
-    project_uri: String,
+    project_uri: String
 ): (MintCapability, BurnCapability, FreezeCapability, ExtendRef) {
     // create object for fungible asset metadata
-    let constructor_ref = &object::create_named_object(creator, *string::bytes(&symbol), false);
+    let constructor_ref =
+        &object::create_named_object(
+            creator,
+            *string::bytes(&symbol)
+        );
 
     primary_fungible_store::create_primary_store_enabled_fungible_asset(
         constructor_ref,
@@ -301,7 +351,7 @@ Only fungible asset metadata owner can make changes.
         symbol,
         decimals,
         icon_uri,
-        project_uri,
+        project_uri
     );
 
     let mint_ref = fungible_asset::generate_mint_ref(constructor_ref);
@@ -309,26 +359,26 @@ Only fungible asset metadata owner can make changes.
     let transfer_ref = fungible_asset::generate_transfer_ref(constructor_ref);
 
     let object_signer = object::generate_signer(constructor_ref);
-    move_to(&object_signer, ManagingRefs {
-        mint_ref,
-        burn_ref,
-        transfer_ref,
-    });
+    move_to(
+        &object_signer,
+        ManagingRefs { mint_ref, burn_ref, transfer_ref }
+    );
 
     let metadata_addr = object::address_from_constructor_ref(constructor_ref);
-    event::emit(CoinCreatedEvent {
-        metadata_addr,
-    });
+    event::emit(CoinCreatedEvent { metadata_addr });
 
     let metadata = object::object_from_constructor_ref<Metadata>(constructor_ref);
-    (MintCapability { metadata }, BurnCapability { metadata }, FreezeCapability { metadata }, object::generate_extend_ref(constructor_ref))
+    (
+        MintCapability { metadata },
+        BurnCapability { metadata },
+        FreezeCapability { metadata },
+        object::generate_extend_ref(constructor_ref)
+    )
 }
 
-
- ## Function `withdraw` @@ -340,14 +390,11 @@ Only fungible asset metadata owner can make changes. -
-Implementation +##### Implementation -
public fun withdraw (
-    account: &signer,
-    metadata: Object<Metadata>,
-    amount: u64,
+
public fun withdraw(
+    account: &signer, metadata: Object<Metadata>, amount: u64
 ): FungibleAsset {
     primary_fungible_store::withdraw(account, metadata, amount)
 }
@@ -355,8 +402,6 @@ Only fungible asset metadata owner can make changes.
 
 
 
-
- ## Function `deposit` @@ -368,22 +413,16 @@ Only fungible asset metadata owner can make changes. -
-Implementation +##### Implementation -
public fun deposit (
-    account_addr: address,
-    fa: FungibleAsset,
-) {
+
public fun deposit(account_addr: address, fa: FungibleAsset) {
     primary_fungible_store::deposit(account_addr, fa)
 }
 
-
- ## Function `transfer` @@ -395,15 +434,14 @@ Only fungible asset metadata owner can make changes. -
-Implementation +##### Implementation -
public entry fun transfer (
+
public entry fun transfer(
     sender: &signer,
     recipient: address,
     metadata: Object<Metadata>,
-    amount: u64,
+    amount: u64
 ) {
     primary_fungible_store::transfer(sender, metadata, recipient, amount)
 }
@@ -411,8 +449,6 @@ Only fungible asset metadata owner can make changes.
 
 
 
-
- ## Function `mint` @@ -425,18 +461,17 @@ Mint FAs as the owner of metadat object. -
-Implementation +##### Implementation -
public fun mint(
-    mint_cap: &MintCapability,
-    amount: u64,
-): FungibleAsset acquires ManagingRefs {
+
public fun mint(mint_cap: &MintCapability, amount: u64): FungibleAsset acquires ManagingRefs {
     let metadata = mint_cap.metadata;
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
 
-    assert!(exists<ManagingRefs>(metadata_addr), ERR_MANAGING_REFS_NOT_FOUND);
+    assert!(
+        exists<ManagingRefs>(metadata_addr),
+        ERR_MANAGING_REFS_NOT_FOUND
+    );
     let refs = borrow_global<ManagingRefs>(metadata_addr);
 
     fungible_asset::mint(&refs.mint_ref, amount)
@@ -445,8 +480,6 @@ Mint FAs as the owner of metadat object.
 
 
 
-
- ## Function `mint_to` @@ -459,19 +492,19 @@ Mint FAs as the owner of metadat object to the primary fungible store of the giv -
-Implementation +##### Implementation
public fun mint_to(
-    mint_cap: &MintCapability,
-    recipient: address,
-    amount: u64,
+    mint_cap: &MintCapability, recipient: address, amount: u64
 ) acquires ManagingRefs {
     let metadata = mint_cap.metadata;
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
 
-    assert!(exists<ManagingRefs>(metadata_addr), ERR_MANAGING_REFS_NOT_FOUND);
+    assert!(
+        exists<ManagingRefs>(metadata_addr),
+        ERR_MANAGING_REFS_NOT_FOUND
+    );
     let refs = borrow_global<ManagingRefs>(metadata_addr);
 
     primary_fungible_store::mint(&refs.mint_ref, recipient, amount)
@@ -480,8 +513,6 @@ Mint FAs as the owner of metadat object to the primary fungible store of the giv
 
 
 
-
- ## Function `burn` @@ -494,18 +525,17 @@ Burn FAs as the owner of metadat object. -
-Implementation +##### Implementation -
public fun burn(
-    burn_cap: &BurnCapability,
-    fa: FungibleAsset,
-) acquires ManagingRefs {
+
public fun burn(burn_cap: &BurnCapability, fa: FungibleAsset) acquires ManagingRefs {
     let metadata = burn_cap.metadata;
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
 
-    assert!(exists<ManagingRefs>(metadata_addr), ERR_MANAGING_REFS_NOT_FOUND);
+    assert!(
+        exists<ManagingRefs>(metadata_addr),
+        ERR_MANAGING_REFS_NOT_FOUND
+    );
     let refs = borrow_global<ManagingRefs>(metadata_addr);
 
     fungible_asset::burn(&refs.burn_ref, fa)
@@ -514,8 +544,6 @@ Burn FAs as the owner of metadat object.
 
 
 
-
- ## Function `freeze_coin_store` @@ -528,28 +556,31 @@ Freeze the primary store of an account. -
-Implementation +##### Implementation
public fun freeze_coin_store(
-    freeze_cap: &FreezeCapability,
-    account_addr: address,
+    freeze_cap: &FreezeCapability, account_addr: address
 ) acquires ManagingRefs {
     let metadata = freeze_cap.metadata;
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
 
-    assert!(exists<ManagingRefs>(metadata_addr), ERR_MANAGING_REFS_NOT_FOUND);
+    assert!(
+        exists<ManagingRefs>(metadata_addr),
+        ERR_MANAGING_REFS_NOT_FOUND
+    );
     let refs = borrow_global<ManagingRefs>(metadata_addr);
 
-    primary_fungible_store::set_frozen_flag(&refs.transfer_ref, account_addr, true)
+    primary_fungible_store::set_frozen_flag(
+        &refs.transfer_ref,
+        account_addr,
+        true
+    )
 }
 
-
- ## Function `unfreeze_coin_store` @@ -562,28 +593,31 @@ Unfreeze the primary store of an account. -
-Implementation +##### Implementation
public fun unfreeze_coin_store(
-    freeze_cap: &FreezeCapability,
-    account_addr: address,
+    freeze_cap: &FreezeCapability, account_addr: address
 ) acquires ManagingRefs {
     let metadata = freeze_cap.metadata;
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
 
-    assert!(exists<ManagingRefs>(metadata_addr), ERR_MANAGING_REFS_NOT_FOUND);
+    assert!(
+        exists<ManagingRefs>(metadata_addr),
+        ERR_MANAGING_REFS_NOT_FOUND
+    );
     let refs = borrow_global<ManagingRefs>(metadata_addr);
 
-    primary_fungible_store::set_frozen_flag(&refs.transfer_ref, account_addr, false)
+    primary_fungible_store::set_frozen_flag(
+        &refs.transfer_ref,
+        account_addr,
+        false
+    )
 }
 
-
- ## Function `balance` @@ -596,8 +630,7 @@ Unfreeze the primary store of an account. -
-Implementation +##### Implementation
public fun balance(account: address, metadata: Object<Metadata>): u64 {
@@ -607,8 +640,6 @@ Unfreeze the primary store of an account.
 
 
 
-
- ## Function `is_frozen` @@ -621,8 +652,7 @@ Unfreeze the primary store of an account. -
-Implementation +##### Implementation
public fun is_frozen(account: address, metadata: Object<Metadata>): bool {
@@ -632,8 +662,6 @@ Unfreeze the primary store of an account.
 
 
 
-
- ## Function `balances` @@ -646,14 +674,11 @@ Unfreeze the primary store of an account. -
-Implementation +##### Implementation
public fun balances(
-    account: address,
-    start_after: Option<address>,
-    limit: u8,
+    account: address, start_after: Option<address>, limit: u8
 ): (vector<Object<Metadata>>, vector<u64>) {
     primary_fungible_store::balances(account, start_after, limit)
 }
@@ -661,8 +686,6 @@ Unfreeze the primary store of an account.
 
 
 
-
- ## Function `supply` @@ -676,8 +699,7 @@ Get the current supply from the metadata object. -
-Implementation +##### Implementation
public fun supply(metadata: Object<Metadata>): Option<u128> {
@@ -687,8 +709,6 @@ Get the current supply from the metadata object.
 
 
 
-
- ## Function `maximum` @@ -702,8 +722,7 @@ Get the maximum supply from the metadata object. -
-Implementation +##### Implementation
public fun maximum(metadata: Object<Metadata>): Option<u128> {
@@ -713,8 +732,6 @@ Get the maximum supply from the metadata object.
 
 
 
-
- ## Function `name` @@ -728,8 +745,7 @@ Get the name of the fungible asset from the metadata object. -
-Implementation +##### Implementation
public fun name(metadata: Object<Metadata>): String {
@@ -739,8 +755,6 @@ Get the name of the fungible asset from the metadata object.
 
 
 
-
- ## Function `symbol` @@ -754,8 +768,7 @@ Get the symbol of the fungible asset from the metadata object. -
-Implementation +##### Implementation
public fun symbol(metadata: Object<Metadata>): String {
@@ -765,8 +778,6 @@ Get the symbol of the fungible asset from the metadata object.
 
 
 
-
- ## Function `decimals` @@ -780,8 +791,7 @@ Get the decimals from the metadata object. -
-Implementation +##### Implementation
public fun decimals(metadata: Object<Metadata>): u8 {
@@ -791,8 +801,6 @@ Get the decimals from the metadata object.
 
 
 
-
- ## Function `metadata_address` @@ -805,19 +813,16 @@ Get the decimals from the metadata object. -
-Implementation +##### Implementation
public fun metadata_address(creator: address, symbol: String): address {
-    object::create_object_address(creator, *string::bytes(&symbol))
+    object::create_object_address(&creator, *string::bytes(&symbol))
 }
 
-
- ## Function `metadata` @@ -830,8 +835,7 @@ Get the decimals from the metadata object. -
-Implementation +##### Implementation
public fun metadata(creator: address, symbol: String): Object<Metadata> {
@@ -841,34 +845,6 @@ Get the decimals from the metadata object.
 
 
 
-
- - - -## Function `is_coin_initialized` - - - -
#[view]
-public fun is_coin_initialized(metadata: object::Object<fungible_asset::Metadata>): bool
-
- - - -
-Implementation - - -
public fun is_coin_initialized(metadata: Object<Metadata>): bool {
-    let metadata_addr = object::object_address(metadata);
-    exists<ManagingRefs>(metadata_addr)
-}
-
- - - -
- ## Function `is_coin` @@ -881,8 +857,7 @@ Get the decimals from the metadata object. -
-Implementation +##### Implementation
public fun is_coin(metadata_addr: address): bool {
@@ -892,8 +867,6 @@ Get the decimals from the metadata object.
 
 
 
-
- ## Function `is_coin_by_symbol` @@ -906,8 +879,7 @@ Get the decimals from the metadata object. -
-Implementation +##### Implementation
public fun is_coin_by_symbol(creator: address, symbol: String): bool {
@@ -918,8 +890,6 @@ Get the decimals from the metadata object.
 
 
 
-
- ## Function `metadata_to_denom` @@ -932,12 +902,11 @@ Get the decimals from the metadata object. -
-Implementation +##### Implementation
public fun metadata_to_denom(metadata: Object<Metadata>): String {
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
     let symbol = symbol(metadata);
     let std_metadata_addr = metadata_address(@initia_std, symbol);
 
@@ -955,8 +924,6 @@ Get the decimals from the metadata object.
 
 
 
-
- ## Function `denom_to_metadata` @@ -969,23 +936,20 @@ Get the decimals from the metadata object. -
-Implementation +##### Implementation
public fun denom_to_metadata(denom: String): Object<Metadata> {
-    let addr = if (string::length(&denom) > 5 && &b"move/" == string::bytes(&string::sub_string(&denom, 0, 5))) {
-        let len = string::length(&denom);
-        let hex_string = string::sub_string(&denom, 5, len);
-        from_bcs::to_address(hex::decode_string(&hex_string))
-    } else {
-        metadata_address(@initia_std, denom)
-    };
+    let addr =
+        if (string::length(&denom) > 5
+            && &b"move/" == string::bytes(&string::sub_string(&denom, 0, 5))) {
+            let len = string::length(&denom);
+            let hex_string = string::sub_string(&denom, 5, len);
+            from_bcs::to_address(hex::decode_string(&hex_string))
+        } else {
+            metadata_address(@initia_std, denom)
+        };
 
     object::address_to_object(addr)
 }
 
- - - -
diff --git a/initia_stdlib/doc/collection.md b/initia_stdlib/doc/collection.md index 73f535e..4949e3b 100644 --- a/initia_stdlib/doc/collection.md +++ b/initia_stdlib/doc/collection.md @@ -35,15 +35,11 @@ require adding the field original_name. - [Constants](#@Constants_0) - [Function `create_fixed_collection`](#0x1_collection_create_fixed_collection) - [Function `create_unlimited_collection`](#0x1_collection_create_unlimited_collection) -- [Function `create_untracked_collection`](#0x1_collection_create_untracked_collection) -- [Function `create_collection_internal`](#0x1_collection_create_collection_internal) - [Function `create_collection_address`](#0x1_collection_create_collection_address) - [Function `create_collection_seed`](#0x1_collection_create_collection_seed) - [Function `increment_supply`](#0x1_collection_increment_supply) - [Function `decrement_supply`](#0x1_collection_decrement_supply) - [Function `generate_mutator_ref`](#0x1_collection_generate_mutator_ref) -- [Function `check_collection_exists`](#0x1_collection_check_collection_exists) -- [Function `borrow`](#0x1_collection_borrow) - [Function `count`](#0x1_collection_count) - [Function `creator`](#0x1_collection_creator) - [Function `description`](#0x1_collection_description) @@ -51,7 +47,6 @@ require adding the field original_name. - [Function `uri`](#0x1_collection_uri) - [Function `nfts`](#0x1_collection_nfts) - [Function `decompose_nft_response`](#0x1_collection_decompose_nft_response) -- [Function `borrow_mut`](#0x1_collection_borrow_mut) - [Function `set_description`](#0x1_collection_set_description) - [Function `set_uri`](#0x1_collection_set_uri) @@ -80,8 +75,7 @@ Represents the common fields for a collection. -
-Fields +##### Fields
@@ -119,8 +113,6 @@ Represents the common fields for a collection.
-
- ## Struct `MutatorRef` @@ -133,8 +125,7 @@ This enables mutating description and URI by higher level services. -
-Fields +##### Fields
@@ -147,8 +138,6 @@ This enables mutating description and URI by higher level services.
-
- ## Struct `MutationEvent` @@ -163,8 +152,7 @@ directly understand the behavior in a writeset. -
-Fields +##### Fields
@@ -195,8 +183,6 @@ directly understand the behavior in a writeset.
-
- ## Resource `FixedSupply` @@ -210,8 +196,7 @@ and adding events and supply tracking to a collection. -
-Fields +##### Fields
@@ -236,8 +221,6 @@ and adding events and supply tracking to a collection.
-
- ## Resource `UnlimitedSupply` @@ -250,8 +233,7 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t -
-Fields +##### Fields
@@ -270,8 +252,6 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t
-
- ## Struct `NftResponse` @@ -283,8 +263,7 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t -
-Fields +##### Fields
@@ -303,8 +282,6 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t
-
- ## Struct `CreateCollectionEvent` @@ -317,8 +294,7 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t -
-Fields +##### Fields
@@ -343,8 +319,6 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t
-
- ## Struct `BurnEvent` @@ -357,8 +331,7 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t -
-Fields +##### Fields
@@ -383,8 +356,6 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t
-
- ## Struct `MintEvent` @@ -397,8 +368,7 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t -
-Fields +##### Fields
@@ -423,8 +393,6 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t
-
- ## Constants @@ -489,6 +457,16 @@ The description is over the maximum length + + +The collection name is invalid + + +
const EINVALID_COLLECTION_NAME: u64 = 7;
+
+ + + The max supply must be positive @@ -542,8 +520,7 @@ Beyond that, it adds supply tracking with events. -
-Implementation +##### Implementation
public fun create_fixed_collection(
@@ -552,17 +529,16 @@ Beyond that, it adds supply tracking with events.
     max_supply: u64,
     name: String,
     royalty: Option<Royalty>,
-    uri: String,
+    uri: String
 ): ConstructorRef {
-    assert!(max_supply != 0, error::invalid_argument(EMAX_SUPPLY_CANNOT_BE_ZERO));
+    assert!(
+        max_supply != 0,
+        error::invalid_argument(EMAX_SUPPLY_CANNOT_BE_ZERO)
+    );
     let collection_seed = create_collection_seed(&name);
-    let constructor_ref = object::create_named_object(creator, collection_seed, false);
+    let constructor_ref = object::create_named_object(creator, collection_seed);
 
-    let supply = FixedSupply {
-        current_supply: 0,
-        max_supply,
-        total_minted: 0,
-    };
+    let supply = FixedSupply { current_supply: 0, max_supply, total_minted: 0 };
 
     create_collection_internal(
         creator,
@@ -571,15 +547,13 @@ Beyond that, it adds supply tracking with events.
         name,
         royalty,
         uri,
-        option::some(supply),
+        option::some(supply)
     )
 }
 
-
- ## Function `create_unlimited_collection` @@ -593,8 +567,7 @@ the supply of nfts. -
-Implementation +##### Implementation
public fun create_unlimited_collection(
@@ -602,15 +575,12 @@ the supply of nfts.
     description: String,
     name: String,
     royalty: Option<Royalty>,
-    uri: String,
+    uri: String
 ): ConstructorRef {
     let collection_seed = create_collection_seed(&name);
-    let constructor_ref = object::create_named_object(creator, collection_seed, false);
+    let constructor_ref = object::create_named_object(creator, collection_seed);
 
-    let supply = UnlimitedSupply {
-        current_supply: 0,
-        total_minted: 0,
-    };
+    let supply = UnlimitedSupply { current_supply: 0, total_minted: 0 };
 
     create_collection_internal(
         creator,
@@ -619,122 +589,13 @@ the supply of nfts.
         name,
         royalty,
         uri,
-        option::some(supply),
-    )
-}
-
- - - -
- - - -## Function `create_untracked_collection` - -Creates an untracked collection, or a collection that supports an arbitrary amount of -nfts. This is useful for mass airdrops that fully leverage Aptos parallelization. -TODO: Hide this until we bring back meaningful way to enforce burns - - -
fun create_untracked_collection(creator: &signer, description: string::String, name: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
-
- - - -
-Implementation - - -
fun create_untracked_collection(
-    creator: &signer,
-    description: String,
-    name: String,
-    royalty: Option<Royalty>,
-    uri: String,
-): ConstructorRef {
-    let collection_seed = create_collection_seed(&name);
-    let constructor_ref = object::create_named_object(creator, collection_seed, false);
-
-    create_collection_internal<FixedSupply>(
-        creator,
-        constructor_ref,
-        description,
-        name,
-        royalty,
-        uri,
-        option::none(),
+        option::some(supply)
     )
 }
 
-
- - - -## Function `create_collection_internal` - - - -
fun create_collection_internal<Supply: key>(creator: &signer, constructor_ref: object::ConstructorRef, description: string::String, name: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String, supply: option::Option<Supply>): object::ConstructorRef
-
- - - -
-Implementation - - -
inline fun create_collection_internal<Supply: key>(
-    creator: &signer,
-    constructor_ref: ConstructorRef,
-    description: String,
-    name: String,
-    royalty: Option<Royalty>,
-    uri: String,
-    supply: Option<Supply>,
-): ConstructorRef {
-    assert!(string::length(&name) <= MAX_COLLECTION_NAME_LENGTH, error::out_of_range(ECOLLECTION_NAME_TOO_LONG));
-    assert!(string::length(&uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
-    assert!(string::length(&description) <= MAX_DESCRIPTION_LENGTH, error::out_of_range(EDESCRIPTION_TOO_LONG));
-
-    let object_signer = &object::generate_signer(&constructor_ref);
-    let creator_addr = signer::address_of(creator);
-
-    let collection = Collection {
-        creator: creator_addr,
-        description,
-        name,
-        uri,
-        nfts: table::new(),
-    };
-    move_to(object_signer, collection);
-
-    if (option::is_some(&supply)) {
-        move_to(object_signer, option::destroy_some(supply));
-        let collection_addr = signer::address_of(object_signer);
-        event::emit(CreateCollectionEvent { collection: collection_addr, creator: creator_addr, name });
-    } else {
-        option::destroy_none(supply)
-    };
-
-    if (option::is_some(&royalty)) {
-        royalty::init(&constructor_ref, option::extract(&mut royalty))
-    };
-
-    let transfer_ref = object::generate_transfer_ref(&constructor_ref);
-    object::disable_ungated_transfer(&transfer_ref);
-
-    constructor_ref
-}
-
- - - -
- ## Function `create_collection_address` @@ -747,19 +608,16 @@ Generates the collections address based upon the creators address and the collec -
-Implementation +##### Implementation
public fun create_collection_address(creator: address, name: &String): address {
-    object::create_object_address(creator, create_collection_seed(name))
+    object::create_object_address(&creator, create_collection_seed(name))
 }
 
-
- ## Function `create_collection_seed` @@ -772,20 +630,20 @@ Named objects are derived from a seed, the collection's seed is its name. -
-Implementation +##### Implementation
public fun create_collection_seed(name: &String): vector<u8> {
-    assert!(string::length(name) <= MAX_COLLECTION_NAME_LENGTH, error::out_of_range(ECOLLECTION_NAME_TOO_LONG));
+    assert!(
+        string::length(name) <= MAX_COLLECTION_NAME_LENGTH,
+        error::out_of_range(ECOLLECTION_NAME_TOO_LONG)
+    );
     *string::bytes(name)
 }
 
-
- ## Function `increment_supply` @@ -798,16 +656,13 @@ Called by nft on mint to increment supply if there's an appropriate Supply struc -
-Implementation +##### Implementation
public(friend) fun increment_supply(
-    collection: Object<Collection>,
-    token_id: String,
-    nft: address,
+    collection: Object<Collection>, token_id: String, nft: address
 ) acquires Collection, FixedSupply, UnlimitedSupply {
-    let collection_addr = object::object_address(collection);
+    let collection_addr = object::object_address(&collection);
     let collection = borrow_global_mut<Collection>(collection_addr);
     if (exists<FixedSupply>(collection_addr)) {
         let supply = borrow_global_mut<FixedSupply>(collection_addr);
@@ -815,28 +670,22 @@ Called by nft on mint to increment supply if there's an appropriate Supply struc
         supply.total_minted = supply.total_minted + 1;
         assert!(
             supply.current_supply <= supply.max_supply,
-            error::out_of_range(ECOLLECTION_SUPPLY_EXCEEDED),
+            error::out_of_range(ECOLLECTION_SUPPLY_EXCEEDED)
         );
         table::add(&mut collection.nfts, token_id, nft);
-        event::emit(
-            MintEvent { collection: collection_addr, token_id, nft },
-        );
+        event::emit(MintEvent { collection: collection_addr, token_id, nft });
     } else if (exists<UnlimitedSupply>(collection_addr)) {
         let supply = borrow_global_mut<UnlimitedSupply>(collection_addr);
         supply.current_supply = supply.current_supply + 1;
         supply.total_minted = supply.total_minted + 1;
         table::add(&mut collection.nfts, token_id, nft);
-        event::emit(
-            MintEvent { collection: collection_addr, token_id, nft },
-        );
+        event::emit(MintEvent { collection: collection_addr, token_id, nft });
     }
 }
 
-
- ## Function `decrement_supply` @@ -849,39 +698,30 @@ Called by nft on burn to decrement supply if there's an appropriate Supply struc -
-Implementation +##### Implementation
public(friend) fun decrement_supply(
-    collection: Object<Collection>,
-    token_id: String,
-    nft: address,
+    collection: Object<Collection>, token_id: String, nft: address
 ) acquires Collection, FixedSupply, UnlimitedSupply {
-    let collection_addr = object::object_address(collection);
+    let collection_addr = object::object_address(&collection);
     let collection = borrow_global_mut<Collection>(collection_addr);
     if (exists<FixedSupply>(collection_addr)) {
         let supply = borrow_global_mut<FixedSupply>(collection_addr);
         supply.current_supply = supply.current_supply - 1;
         table::remove(&mut collection.nfts, token_id);
-        event::emit(
-            BurnEvent { collection: collection_addr, token_id, nft },
-        );
+        event::emit(BurnEvent { collection: collection_addr, token_id, nft });
     } else if (exists<UnlimitedSupply>(collection_addr)) {
         let supply = borrow_global_mut<UnlimitedSupply>(collection_addr);
         supply.current_supply = supply.current_supply - 1;
         table::remove(&mut collection.nfts, token_id);
-        event::emit(
-            BurnEvent { collection: collection_addr, token_id, nft },
-        );
+        event::emit(BurnEvent { collection: collection_addr, token_id, nft });
     }
 }
 
-
- ## Function `generate_mutator_ref` @@ -894,73 +734,17 @@ Creates a MutatorRef, which gates the ability to mutate any fields that support -
-Implementation +##### Implementation
public fun generate_mutator_ref(ref: &ConstructorRef): MutatorRef {
     let object = object::object_from_constructor_ref<Collection>(ref);
-    MutatorRef { self: object::object_address(object) }
-}
-
- - - -
- - - -## Function `check_collection_exists` - - - -
fun check_collection_exists(addr: address)
-
- - - -
-Implementation - - -
inline fun check_collection_exists(addr: address) {
-    assert!(
-        exists<Collection>(addr),
-        error::not_found(ECOLLECTION_DOES_NOT_EXIST),
-    );
-}
-
- - - -
- - - -## Function `borrow` - - - -
fun borrow<T: key>(collection: object::Object<T>): &collection::Collection
-
- - - -
-Implementation - - -
inline fun borrow<T: key>(collection: Object<T>): &Collection {
-    let collection_address = object::object_address(collection);
-    check_collection_exists(collection_address);
-    borrow_global<Collection>(collection_address)
+    MutatorRef { self: object::object_address(&object) }
 }
 
-
- ## Function `count` @@ -974,12 +758,11 @@ Provides the count of the current selection if supply tracking is used -
-Implementation +##### Implementation
public fun count<T: key>(collection: Object<T>): Option<u64> acquires FixedSupply, UnlimitedSupply {
-    let collection_address = object::object_address(collection);
+    let collection_address = object::object_address(&collection);
     check_collection_exists(collection_address);
 
     if (exists<FixedSupply>(collection_address)) {
@@ -996,8 +779,6 @@ Provides the count of the current selection if supply tracking is used
 
 
 
-
- ## Function `creator` @@ -1010,8 +791,7 @@ Provides the count of the current selection if supply tracking is used -
-Implementation +##### Implementation
public fun creator<T: key>(collection: Object<T>): address acquires Collection {
@@ -1021,8 +801,6 @@ Provides the count of the current selection if supply tracking is used
 
 
 
-
- ## Function `description` @@ -1035,8 +813,7 @@ Provides the count of the current selection if supply tracking is used -
-Implementation +##### Implementation
public fun description<T: key>(collection: Object<T>): String acquires Collection {
@@ -1046,8 +823,6 @@ Provides the count of the current selection if supply tracking is used
 
 
 
-
- ## Function `name` @@ -1060,8 +835,7 @@ Provides the count of the current selection if supply tracking is used -
-Implementation +##### Implementation
public fun name<T: key>(collection: Object<T>): String acquires Collection {
@@ -1071,8 +845,6 @@ Provides the count of the current selection if supply tracking is used
 
 
 
-
- ## Function `uri` @@ -1085,8 +857,7 @@ Provides the count of the current selection if supply tracking is used -
-Implementation +##### Implementation
public fun uri<T: key>(collection: Object<T>): String acquires Collection {
@@ -1096,8 +867,6 @@ Provides the count of the current selection if supply tracking is used
 
 
 
-
- ## Function `nfts` @@ -1112,14 +881,11 @@ if start_after is not none, seach nfts in range (start_after, ...] -
-Implementation +##### Implementation
public fun nfts<T: key>(
-    collection: Object<T>,
-    start_after: Option<String>,
-    limit: u64,
+    collection: Object<T>, start_after: Option<String>, limit: u64
 ): vector<NftResponse> acquires Collection {
     let collection = borrow(collection);
 
@@ -1131,20 +897,18 @@ if start_after is not none, seach nfts in range (start_after, ...]
         &collection.nfts,
         option::none(),
         start_after,
-        2,
+        2
     );
 
     let res: vector<NftResponse> = vector[];
 
-    while (table::prepare<String, address>(&mut nfts_iter) && vector::length(&res) < (limit as u64)) {
-        let (token_id, nft) = table::next<String, address>(&mut nfts_iter);
+    while (table::prepare<String, address>(nfts_iter)
+        && vector::length(&res) < (limit as u64)) {
+        let (token_id, nft) = table::next<String, address>(nfts_iter);
 
         vector::push_back(
             &mut res,
-            NftResponse {
-                token_id,
-                nft: *nft,
-            },
+            NftResponse { token_id, nft: *nft }
         );
     };
 
@@ -1154,8 +918,6 @@ if start_after is not none, seach nfts in range (start_after, ...]
 
 
 
-
- ## Function `decompose_nft_response` @@ -1167,8 +929,7 @@ if start_after is not none, seach nfts in range (start_after, ...] -
-Implementation +##### Implementation
public fun decompose_nft_response(nft_response: &NftResponse): (String, address) {
@@ -1178,33 +939,6 @@ if start_after is not none, seach nfts in range (start_after, ...]
 
 
 
-
- - - -## Function `borrow_mut` - - - -
fun borrow_mut(mutator_ref: &collection::MutatorRef): &mut collection::Collection
-
- - - -
-Implementation - - -
inline fun borrow_mut(mutator_ref: &MutatorRef): &mut Collection {
-    check_collection_exists(mutator_ref.self);
-    borrow_global_mut<Collection>(mutator_ref.self)
-}
-
- - - -
- ## Function `set_description` @@ -1216,12 +950,16 @@ if start_after is not none, seach nfts in range (start_after, ...] -
-Implementation +##### Implementation -
public fun set_description(mutator_ref: &MutatorRef, description: String) acquires Collection {
-    assert!(string::length(&description) <= MAX_DESCRIPTION_LENGTH, error::out_of_range(EDESCRIPTION_TOO_LONG));
+
public fun set_description(
+    mutator_ref: &MutatorRef, description: String
+) acquires Collection {
+    assert!(
+        string::length(&description) <= MAX_DESCRIPTION_LENGTH,
+        error::out_of_range(EDESCRIPTION_TOO_LONG)
+    );
     let collection = borrow_mut(mutator_ref);
     event::emit(
         MutationEvent {
@@ -1229,7 +967,7 @@ if start_after is not none, seach nfts in range (start_after, ...]
             mutated_field_name: string::utf8(b"description"),
             old_value: collection.description,
             new_value: description
-        },
+        }
     );
     collection.description = description;
 }
@@ -1237,8 +975,6 @@ if start_after is not none, seach nfts in range (start_after, ...]
 
 
 
-
- ## Function `set_uri` @@ -1250,12 +986,14 @@ if start_after is not none, seach nfts in range (start_after, ...] -
-Implementation +##### Implementation
public fun set_uri(mutator_ref: &MutatorRef, uri: String) acquires Collection {
-    assert!(string::length(&uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
+    assert!(
+        string::length(&uri) <= MAX_URI_LENGTH,
+        error::out_of_range(EURI_TOO_LONG)
+    );
     let collection = borrow_mut(mutator_ref);
     event::emit(
         MutationEvent {
@@ -1263,12 +1001,8 @@ if start_after is not none, seach nfts in range (start_after, ...]
             mutated_field_name: string::utf8(b"uri"),
             old_value: collection.uri,
             new_value: uri
-        },
+        }
     );
     collection.uri = uri;
 }
 
- - - -
diff --git a/initia_stdlib/doc/comparator.md b/initia_stdlib/doc/comparator.md index f62a107..59afdc2 100644 --- a/initia_stdlib/doc/comparator.md +++ b/initia_stdlib/doc/comparator.md @@ -31,8 +31,7 @@ Provides a framework for comparing two elements -
-Fields +##### Fields
@@ -45,8 +44,6 @@ Provides a framework for comparing two elements
-
- ## Constants @@ -90,8 +87,7 @@ Provides a framework for comparing two elements -
-Implementation +##### Implementation
public fun is_equal(result: &Result): bool {
@@ -101,8 +97,6 @@ Provides a framework for comparing two elements
 
 
 
-
- ## Function `is_smaller_than` @@ -114,8 +108,7 @@ Provides a framework for comparing two elements -
-Implementation +##### Implementation
public fun is_smaller_than(result: &Result): bool {
@@ -125,8 +118,6 @@ Provides a framework for comparing two elements
 
 
 
-
- ## Function `is_greater_than` @@ -138,8 +129,7 @@ Provides a framework for comparing two elements -
-Implementation +##### Implementation
public fun is_greater_than(result: &Result): bool {
@@ -149,8 +139,6 @@ Provides a framework for comparing two elements
 
 
 
-
- ## Function `compare` @@ -162,8 +150,7 @@ Provides a framework for comparing two elements -
-Implementation +##### Implementation
public fun compare<T>(left: &T, right: &T): Result {
@@ -176,8 +163,6 @@ Provides a framework for comparing two elements
 
 
 
-
- ## Function `compare_u8_vector` @@ -189,8 +174,7 @@ Provides a framework for comparing two elements -
-Implementation +##### Implementation
public fun compare_u8_vector(left: vector<u8>, right: vector<u8>): Result {
@@ -220,7 +204,3 @@ Provides a framework for comparing two elements
     }
 }
 
- - - -
diff --git a/initia_stdlib/doc/copyable_any.md b/initia_stdlib/doc/copyable_any.md index 36ce028..ae04079 100644 --- a/initia_stdlib/doc/copyable_any.md +++ b/initia_stdlib/doc/copyable_any.md @@ -33,8 +33,7 @@ The same as any::Any but with the -
-Fields +##### Fields
@@ -53,8 +52,6 @@ The same as any::Any but with the
-
- ## Constants @@ -83,8 +80,7 @@ also required from T. -
-Implementation +##### Implementation
public fun pack<T: drop + store + copy>(x: T): Any {
@@ -97,8 +93,6 @@ also required from T.
 
 
 
-
- ## Function `unpack` @@ -111,20 +105,20 @@ Unpack a value from the Any -
-Implementation +##### Implementation
public fun unpack<T>(x: Any): T {
-    assert!(type_info::type_name<T>() == x.type_name, error::invalid_argument(ETYPE_MISMATCH));
+    assert!(
+        type_info::type_name<T>() == x.type_name,
+        error::invalid_argument(ETYPE_MISMATCH)
+    );
     from_bytes<T>(x.data)
 }
 
-
- ## Function `type_name` @@ -137,15 +131,10 @@ Returns the type name of this Any -
-Implementation +##### Implementation
public fun type_name(x: &Any): &String {
     &x.type_name
 }
 
- - - -
diff --git a/initia_stdlib/doc/cosmos.md b/initia_stdlib/doc/cosmos.md index 87cd5ea..689c9ba 100644 --- a/initia_stdlib/doc/cosmos.md +++ b/initia_stdlib/doc/cosmos.md @@ -7,6 +7,7 @@ This module provides interfaces to allow CosmosMessage execution after the move execution finished. +- [Struct `VoteRequest`](#0x1_cosmos_VoteRequest) - [Function `stargate_vote`](#0x1_cosmos_stargate_vote) - [Function `stargate`](#0x1_cosmos_stargate) - [Function `move_execute`](#0x1_cosmos_move_execute) @@ -18,28 +19,66 @@ execution after the move execution finished. - [Function `transfer`](#0x1_cosmos_transfer) - [Function `nft_transfer`](#0x1_cosmos_nft_transfer) - [Function `pay_fee`](#0x1_cosmos_pay_fee) -- [Function `stargate_internal`](#0x1_cosmos_stargate_internal) -- [Function `move_execute_internal`](#0x1_cosmos_move_execute_internal) -- [Function `move_script_internal`](#0x1_cosmos_move_script_internal) -- [Function `delegate_internal`](#0x1_cosmos_delegate_internal) -- [Function `fund_community_pool_internal`](#0x1_cosmos_fund_community_pool_internal) -- [Function `transfer_internal`](#0x1_cosmos_transfer_internal) -- [Function `nft_transfer_internal`](#0x1_cosmos_nft_transfer_internal) -- [Function `pay_fee_internal`](#0x1_cosmos_pay_fee_internal)
use 0x1::collection;
 use 0x1::fungible_asset;
 use 0x1::json;
 use 0x1::object;
-use 0x1::option;
 use 0x1::signer;
-use 0x1::simple_json;
 use 0x1::string;
 
+ + +## Struct `VoteRequest` + + + +
struct VoteRequest has copy, drop
+
+ + + +##### Fields + + +
+
+_type_: string::String +
+
+ +
+
+proposal_id: u64 +
+
+ +
+
+voter: string::String +
+
+ +
+
+option: u64 +
+
+ +
+
+metadata: string::String +
+
+ +
+
+ + ## Function `stargate_vote` @@ -51,8 +90,7 @@ execution after the move execution finished. -
-Implementation +##### Implementation
public entry fun stargate_vote(
@@ -62,54 +100,44 @@ execution after the move execution finished.
     option: u64,
     metadata: String
 ) {
-    let obj = simple_json::empty();
-    simple_json::set_object(&mut obj, option::none<String>());
-    simple_json::increase_depth(&mut obj);
-    simple_json::set_int_raw(&mut obj, option::some(string::utf8(b"proposal_id")), true, (proposal_id as u256));
-    simple_json::set_string(&mut obj, option::some(string::utf8(b"voter")), voter);
-    simple_json::set_int_raw(&mut obj, option::some(string::utf8(b"option")), true, (option as u256));
-    simple_json::set_string(&mut obj, option::some(string::utf8(b"metadata")), metadata);
-    simple_json::set_string(&mut obj, option::some(string::utf8(b"@type")), string::utf8(b"/cosmos.gov.v1.MsgVote"));
-
-    let req = json::stringify(simple_json::to_json_object(&obj));
-    stargate(sender, req);
+    stargate(
+        sender,
+        json::marshal(
+            &VoteRequest {
+                _type_: string::utf8(b"/cosmos.gov.v1.MsgVote"),
+                proposal_id,
+                voter,
+                option,
+                metadata
+            }
+        )
+    );
 }
 
-
- ## Function `stargate` -
public entry fun stargate(sender: &signer, data: string::String)
+
public entry fun stargate(sender: &signer, data: vector<u8>)
 
-
-Implementation +##### Implementation -
public entry fun stargate (
-    sender: &signer,
-    data: String,
-) {
-    stargate_internal(
-        signer::address_of(sender),
-        *string::bytes(&data),
-    )
+
public entry fun stargate(sender: &signer, data: vector<u8>) {
+    stargate_internal(signer::address_of(sender), data)
 }
 
-
- ## Function `move_execute` @@ -121,17 +149,16 @@ execution after the move execution finished. -
-Implementation +##### Implementation -
public entry fun move_execute (
+
public entry fun move_execute(
     sender: &signer,
     module_address: address,
     module_name: String,
     function_name: String,
     type_args: vector<String>,
-    args: vector<vector<u8>>,
+    args: vector<vector<u8>>
 ) {
     move_execute_internal(
         signer::address_of(sender),
@@ -140,15 +167,13 @@ execution after the move execution finished.
         *string::bytes(&function_name),
         vector::map_ref(&type_args, |v| *string::bytes(v)),
         args,
-        false,
+        false
     )
 }
 
-
- ## Function `move_execute_with_json` @@ -160,17 +185,16 @@ execution after the move execution finished. -
-Implementation +##### Implementation -
public entry fun move_execute_with_json (
+
public entry fun move_execute_with_json(
     sender: &signer,
     module_address: address,
     module_name: String,
     function_name: String,
     type_args: vector<String>,
-    args: vector<String>,
+    args: vector<String>
 ) {
     move_execute_internal(
         signer::address_of(sender),
@@ -179,15 +203,13 @@ execution after the move execution finished.
         *string::bytes(&function_name),
         vector::map_ref(&type_args, |v| *string::bytes(v)),
         vector::map_ref(&args, |v| *string::bytes(v)),
-        true,
+        true
     )
 }
 
-
- ## Function `move_script` @@ -199,30 +221,27 @@ execution after the move execution finished. -
-Implementation +##### Implementation -
public entry fun move_script (
+
public entry fun move_script(
     sender: &signer,
     code_bytes: vector<u8>,
     type_args: vector<String>,
-    args: vector<vector<u8>>,
+    args: vector<vector<u8>>
 ) {
     move_script_internal(
         signer::address_of(sender),
         code_bytes,
         vector::map_ref(&type_args, |v| *string::bytes(v)),
         args,
-        false,
+        false
     )
 }
 
-
- ## Function `move_script_with_json` @@ -234,30 +253,27 @@ execution after the move execution finished. -
-Implementation +##### Implementation -
public entry fun move_script_with_json (
+
public entry fun move_script_with_json(
     sender: &signer,
     code_bytes: vector<u8>,
     type_args: vector<String>,
-    args: vector<String>,
+    args: vector<String>
 ) {
     move_script_internal(
         signer::address_of(sender),
         code_bytes,
         vector::map_ref(&type_args, |v| *string::bytes(v)),
         vector::map_ref(&args, |v| *string::bytes(v)),
-        true,
+        true
     )
 }
 
-
- ## Function `delegate` @@ -269,29 +285,26 @@ execution after the move execution finished. -
-Implementation +##### Implementation -
public entry fun delegate (
+
public entry fun delegate(
     delegator: &signer,
     validator: String,
     metadata: Object<Metadata>,
-    amount: u64,
+    amount: u64
 ) {
     delegate_internal(
         signer::address_of(delegator),
         *string::bytes(&validator),
         &metadata,
-        amount,
+        amount
     )
 }
 
-
- ## Function `fund_community_pool` @@ -303,27 +316,22 @@ execution after the move execution finished. -
-Implementation +##### Implementation -
public entry fun fund_community_pool (
-    sender: &signer,
-    metadata: Object<Metadata>,
-    amount: u64,
+
public entry fun fund_community_pool(
+    sender: &signer, metadata: Object<Metadata>, amount: u64
 ) {
     fund_community_pool_internal(
         signer::address_of(sender),
         &metadata,
-        amount,
+        amount
     )
 }
 
-
- ## Function `transfer` @@ -337,11 +345,10 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-020-fungible-token-transfer -
-Implementation +##### Implementation -
public entry fun transfer (
+
public entry fun transfer(
     sender: &signer,
     receiver: String,
     metadata: Object<Metadata>,
@@ -351,7 +358,7 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-020-fungible-token-transfer
     revision_number: u64,
     revision_height: u64,
     timeout_timestamp: u64,
-    memo: String,
+    memo: String
 ) {
     transfer_internal(
         signer::address_of(sender),
@@ -363,15 +370,13 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-020-fungible-token-transfer
         revision_number,
         revision_height,
         timeout_timestamp,
-        *string::bytes(&memo),
+        *string::bytes(&memo)
     )
 }
 
-
- ## Function `nft_transfer` @@ -385,11 +390,10 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-721-nft-transfer -
-Implementation +##### Implementation -
public entry fun nft_transfer (
+
public entry fun nft_transfer(
     sender: &signer,
     receiver: String,
     collection: Object<Collection>,
@@ -399,7 +403,7 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-721-nft-transfer
     revision_number: u64,
     revision_height: u64,
     timeout_timestamp: u64,
-    memo: String,
+    memo: String
 ) {
     nft_transfer_internal(
         signer::address_of(sender),
@@ -411,15 +415,13 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-721-nft-transfer
         revision_number,
         revision_height,
         timeout_timestamp,
-        *string::bytes(&memo),
+        *string::bytes(&memo)
     )
 }
 
-
- ## Function `pay_fee` @@ -433,11 +435,10 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-029-fee-payment -
-Implementation +##### Implementation -
public entry fun pay_fee (
+
public entry fun pay_fee(
     sender: &signer,
     source_port: String,
     source_channel: String,
@@ -446,7 +447,7 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-029-fee-payment
     ack_fee_metadata: Object<Metadata>,
     ack_fee_amount: u64,
     timeout_fee_metadata: Object<Metadata>,
-    timeout_fee_amount: u64,
+    timeout_fee_amount: u64
 ) {
     pay_fee_internal(
         signer::address_of(sender),
@@ -457,245 +458,7 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-029-fee-payment
         &ack_fee_metadata,
         ack_fee_amount,
         &timeout_fee_metadata,
-        timeout_fee_amount,
+        timeout_fee_amount
     )
 }
 
- - - -
- - - -## Function `stargate_internal` - - - -
fun stargate_internal(sender: address, data: vector<u8>)
-
- - - -
-Implementation - - -
native fun stargate_internal (
-    sender: address,
-    data: vector<u8>,
-);
-
- - - -
- - - -## Function `move_execute_internal` - - - -
fun move_execute_internal(sender: address, module_address: address, module_name: vector<u8>, function_name: vector<u8>, type_args: vector<vector<u8>>, args: vector<vector<u8>>, is_json: bool)
-
- - - -
-Implementation - - -
native fun move_execute_internal (
-    sender: address,
-    module_address: address,
-    module_name: vector<u8>,
-    function_name: vector<u8>,
-    type_args: vector<vector<u8>>,
-    args: vector<vector<u8>>,
-    is_json: bool,
-);
-
- - - -
- - - -## Function `move_script_internal` - - - -
fun move_script_internal(sender: address, code_bytes: vector<u8>, type_args: vector<vector<u8>>, args: vector<vector<u8>>, is_json: bool)
-
- - - -
-Implementation - - -
native fun move_script_internal (
-    sender: address,
-    code_bytes: vector<u8>,
-    type_args: vector<vector<u8>>,
-    args: vector<vector<u8>>,
-    is_json: bool,
-);
-
- - - -
- - - -## Function `delegate_internal` - - - -
fun delegate_internal(delegator: address, validator: vector<u8>, metadata: &object::Object<fungible_asset::Metadata>, amount: u64)
-
- - - -
-Implementation - - -
native fun delegate_internal (
-    delegator: address,
-    validator: vector<u8>,
-    metadata: &Object<Metadata>,
-    amount: u64,
-);
-
- - - -
- - - -## Function `fund_community_pool_internal` - - - -
fun fund_community_pool_internal(sender: address, metadata: &object::Object<fungible_asset::Metadata>, amount: u64)
-
- - - -
-Implementation - - -
native fun fund_community_pool_internal (
-    sender: address,
-    metadata: &Object<Metadata>,
-    amount: u64,
-);
-
- - - -
- - - -## Function `transfer_internal` - - - -
fun transfer_internal(sender: address, receiver: vector<u8>, metadata: &object::Object<fungible_asset::Metadata>, token_amount: u64, source_port: vector<u8>, source_channel: vector<u8>, revision_number: u64, revision_height: u64, timeout_timestamp: u64, memo: vector<u8>)
-
- - - -
-Implementation - - -
native fun transfer_internal (
-    sender: address,
-    receiver: vector<u8>,
-    metadata: &Object<Metadata>,
-    token_amount: u64,
-    source_port: vector<u8>,
-    source_channel: vector<u8>,
-    revision_number: u64,
-    revision_height: u64,
-    timeout_timestamp: u64,
-    memo: vector<u8>,
-);
-
- - - -
- - - -## Function `nft_transfer_internal` - - - -
fun nft_transfer_internal(sender: address, receiver: vector<u8>, collection: &object::Object<collection::Collection>, token_ids: vector<vector<u8>>, source_port: vector<u8>, source_channel: vector<u8>, revision_number: u64, revision_height: u64, timeout_timestamp: u64, memo: vector<u8>)
-
- - - -
-Implementation - - -
native fun nft_transfer_internal (
-    sender: address,
-    receiver: vector<u8>,
-    collection: &Object<Collection>,
-    token_ids: vector<vector<u8>>,
-    source_port: vector<u8>,
-    source_channel: vector<u8>,
-    revision_number: u64,
-    revision_height: u64,
-    timeout_timestamp: u64,
-    memo: vector<u8>,
-);
-
- - - -
- - - -## Function `pay_fee_internal` - - - -
fun pay_fee_internal(sender: address, source_port: vector<u8>, source_channel: vector<u8>, recv_fee_metadata: &object::Object<fungible_asset::Metadata>, recv_fee_amount: u64, ack_fee_metadata: &object::Object<fungible_asset::Metadata>, ack_fee_amount: u64, timeout_fee_metadata: &object::Object<fungible_asset::Metadata>, timeout_fee_amount: u64)
-
- - - -
-Implementation - - -
native fun pay_fee_internal (
-    sender: address,
-    source_port: vector<u8>,
-    source_channel: vector<u8>,
-    recv_fee_metadata: &Object<Metadata>,
-    recv_fee_amount: u64,
-    ack_fee_metadata: &Object<Metadata>,
-    ack_fee_amount: u64,
-    timeout_fee_metadata: &Object<Metadata>,
-    timeout_fee_amount: u64,
-);
-
- - - -
diff --git a/initia_stdlib/doc/debug.md b/initia_stdlib/doc/debug.md index 029ff17..9be477b 100644 --- a/initia_stdlib/doc/debug.md +++ b/initia_stdlib/doc/debug.md @@ -9,9 +9,6 @@ Module providing debug functionality. - [Constants](#@Constants_0) - [Function `print`](#0x1_debug_print) - [Function `print_stack_trace`](#0x1_debug_print_stack_trace) -- [Function `format`](#0x1_debug_format) -- [Function `native_print`](#0x1_debug_native_print) -- [Function `native_stack_trace`](#0x1_debug_native_stack_trace)
use 0x1::string;
@@ -54,8 +51,7 @@ Module providing debug functionality.
 
 
 
-
-Implementation +##### Implementation
public fun print<T>(x: &T) {
@@ -65,8 +61,6 @@ Module providing debug functionality.
 
 
 
-
- ## Function `print_stack_trace` @@ -78,83 +72,10 @@ Module providing debug functionality. -
-Implementation +##### Implementation
public fun print_stack_trace() {
     native_print(native_stack_trace());
 }
 
- - - -
- - - -## Function `format` - - - -
fun format<T>(x: &T): string::String
-
- - - -
-Implementation - - -
inline fun format<T>(x: &T): String {
-    debug_string(x)
-}
-
- - - -
- - - -## Function `native_print` - - - -
fun native_print(x: string::String)
-
- - - -
-Implementation - - -
native fun native_print(x: String);
-
- - - -
- - - -## Function `native_stack_trace` - - - -
fun native_stack_trace(): string::String
-
- - - -
-Implementation - - -
native fun native_stack_trace(): String;
-
- - - -
diff --git a/initia_stdlib/doc/decimal128.md b/initia_stdlib/doc/decimal128.md deleted file mode 100644 index 2d20494..0000000 --- a/initia_stdlib/doc/decimal128.md +++ /dev/null @@ -1,579 +0,0 @@ - - - -# Module `0x1::decimal128` - - - -- [Struct `Decimal128`](#0x1_decimal128_Decimal128) -- [Constants](#@Constants_0) -- [Function `new`](#0x1_decimal128_new) -- [Function `new_u64`](#0x1_decimal128_new_u64) -- [Function `one`](#0x1_decimal128_one) -- [Function `zero`](#0x1_decimal128_zero) -- [Function `from_ratio_u64`](#0x1_decimal128_from_ratio_u64) -- [Function `from_ratio`](#0x1_decimal128_from_ratio) -- [Function `add`](#0x1_decimal128_add) -- [Function `sub`](#0x1_decimal128_sub) -- [Function `mul_u64`](#0x1_decimal128_mul_u64) -- [Function `mul_u128`](#0x1_decimal128_mul_u128) -- [Function `mul`](#0x1_decimal128_mul) -- [Function `div_u64`](#0x1_decimal128_div_u64) -- [Function `div`](#0x1_decimal128_div) -- [Function `val`](#0x1_decimal128_val) -- [Function `is_same`](#0x1_decimal128_is_same) -- [Function `from_string`](#0x1_decimal128_from_string) -- [Function `pow`](#0x1_decimal128_pow) - - -
use 0x1::error;
-use 0x1::string;
-
- - - - - -## Struct `Decimal128` - -A fixed-point decimal value with 18 fractional digits, i.e. Decimal128{ val: 1_000_000_000_000_000_000 } == 1.0 - - -
struct Decimal128 has copy, drop, store
-
- - - -
-Fields - - -
-
-val: u128 -
-
- -
-
- - -
- - - -## Constants - - - - - - -
const DECIMAL_FRACTIONAL: u128 = 1000000000000000000;
-
- - - - - - - -
const EDIV_WITH_ZERO: u64 = 0;
-
- - - - - - - -
const EFAILED_TO_DESERIALIZE: u64 = 1;
-
- - - - - - - -
const EOUT_OF_RANGE: u64 = 2;
-
- - - - - - - -
const FRACTIONAL_LENGTH: u64 = 18;
-
- - - - - - - -
const MAX_INTEGER_PART: u128 = 340282366920938463463;
-
- - - - - -## Function `new` - - - -
public fun new(val: u128): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun new(val: u128): Decimal128 {
-    Decimal128 { val }
-}
-
- - - -
- - - -## Function `new_u64` - - - -
public fun new_u64(val: u64): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun new_u64(val: u64): Decimal128 {
-    Decimal128 { val: (val as u128) }
-}
-
- - - -
- - - -## Function `one` - - - -
public fun one(): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun one(): Decimal128 {
-    Decimal128 { val: DECIMAL_FRACTIONAL }
-}
-
- - - -
- - - -## Function `zero` - - - -
public fun zero(): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun zero(): Decimal128 {
-    Decimal128 { val: 0 }
-}
-
- - - -
- - - -## Function `from_ratio_u64` - - - -
public fun from_ratio_u64(numerator: u64, denominator: u64): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun from_ratio_u64(numerator: u64, denominator: u64): Decimal128 {
-    assert!(denominator != 0, EDIV_WITH_ZERO);
-
-    new((numerator as u128) * DECIMAL_FRACTIONAL / (denominator as u128))
-}
-
- - - -
- - - -## Function `from_ratio` - - - -
public fun from_ratio(numerator: u128, denominator: u128): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun from_ratio(numerator: u128, denominator: u128): Decimal128 {
-    assert!(denominator != 0, EDIV_WITH_ZERO);
-
-    new(numerator * DECIMAL_FRACTIONAL / denominator)
-}
-
- - - -
- - - -## Function `add` - - - -
public fun add(left: &decimal128::Decimal128, right: &decimal128::Decimal128): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun add(left: &Decimal128, right: &Decimal128): Decimal128 {
-    new(left.val + right.val)
-}
-
- - - -
- - - -## Function `sub` - - - -
public fun sub(left: &decimal128::Decimal128, right: &decimal128::Decimal128): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun sub(left: &Decimal128, right: &Decimal128): Decimal128 {
-    new(left.val - right.val)
-}
-
- - - -
- - - -## Function `mul_u64` - - - -
public fun mul_u64(decimal: &decimal128::Decimal128, val: u64): u64
-
- - - -
-Implementation - - -
public fun mul_u64(decimal: &Decimal128, val: u64): u64 {
-    (decimal.val * (val as u128) / DECIMAL_FRACTIONAL as u64)
-}
-
- - - -
- - - -## Function `mul_u128` - - - -
public fun mul_u128(decimal: &decimal128::Decimal128, val: u128): u128
-
- - - -
-Implementation - - -
public fun mul_u128(decimal: &Decimal128, val: u128): u128 {
-    decimal.val * val / DECIMAL_FRACTIONAL
-}
-
- - - -
- - - -## Function `mul` - - - -
public fun mul(a: &decimal128::Decimal128, b: &decimal128::Decimal128): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun mul(a: &Decimal128, b: &Decimal128): Decimal128 {
-    new(a.val * b.val / DECIMAL_FRACTIONAL)
-}
-
- - - -
- - - -## Function `div_u64` - - - -
public fun div_u64(decimal: &decimal128::Decimal128, val: u64): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun div_u64(decimal: &Decimal128, val: u64): Decimal128 {
-    new(decimal.val / (val as u128))
-}
-
- - - -
- - - -## Function `div` - - - -
public fun div(decimal: &decimal128::Decimal128, val: u128): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun div(decimal: &Decimal128, val: u128): Decimal128 {
-    new(decimal.val / val)
-}
-
- - - -
- - - -## Function `val` - - - -
public fun val(decimal: &decimal128::Decimal128): u128
-
- - - -
-Implementation - - -
public fun val(decimal: &Decimal128): u128 {
-    decimal.val
-}
-
- - - -
- - - -## Function `is_same` - - - -
public fun is_same(left: &decimal128::Decimal128, right: &decimal128::Decimal128): bool
-
- - - -
-Implementation - - -
public fun is_same(left: &Decimal128, right: &Decimal128): bool {
-    left.val == right.val
-}
-
- - - -
- - - -## Function `from_string` - - - -
public fun from_string(num: &string::String): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun from_string(num: &String): Decimal128 {
-    let vec = string::bytes(num);
-    let len = vector::length(vec);
-
-    let cursor = 0;
-    let dot_index = 0;
-    let val: u128 = 0;
-    while (cursor < len) {
-        let s = *vector::borrow(vec, cursor);
-        cursor = cursor + 1;
-
-        // find `.` position
-        if (s == 46) continue;
-
-        val = val * 10;
-        assert!(s >= 48 && s <= 57, error::invalid_argument(EFAILED_TO_DESERIALIZE));
-
-        let n = (s - 48 as u128);
-        val = val + n;
-
-        if (cursor == dot_index + 1) {
-            // use `<` not `<=` to safely check "out of range"
-            // (i.e. to avoid fractional part checking)
-            assert!(val < MAX_INTEGER_PART, error::invalid_argument(EOUT_OF_RANGE));
-
-            dot_index = dot_index + 1;
-        };
-    };
-
-    // ignore fractional part longer than `FRACTIONAL_LENGTH`
-    let val = if (dot_index == len) {
-        val * pow(10, FRACTIONAL_LENGTH)
-    } else {
-        let fractional_length = len - dot_index - 1;
-        if (fractional_length > FRACTIONAL_LENGTH) {
-            val / pow(10, fractional_length - FRACTIONAL_LENGTH)
-        } else {
-            val * pow(10, FRACTIONAL_LENGTH - fractional_length)
-        }
-    };
-
-    new(val)
-}
-
- - - -
- - - -## Function `pow` - - - -
fun pow(num: u128, pow_amount: u64): u128
-
- - - -
-Implementation - - -
fun pow(num: u128, pow_amount: u64): u128 {
-    let index = 0;
-    let val = 1;
-    while (index < pow_amount) {
-        val = val * num;
-        index = index + 1;
-    };
-
-    val
-}
-
- - - -
diff --git a/initia_stdlib/doc/decimal256.md b/initia_stdlib/doc/decimal256.md deleted file mode 100644 index bb0add4..0000000 --- a/initia_stdlib/doc/decimal256.md +++ /dev/null @@ -1,681 +0,0 @@ - - - -# Module `0x1::decimal256` - - - -- [Struct `Decimal256`](#0x1_decimal256_Decimal256) -- [Constants](#@Constants_0) -- [Function `new`](#0x1_decimal256_new) -- [Function `new_u64`](#0x1_decimal256_new_u64) -- [Function `new_u128`](#0x1_decimal256_new_u128) -- [Function `one`](#0x1_decimal256_one) -- [Function `zero`](#0x1_decimal256_zero) -- [Function `from_ratio_u64`](#0x1_decimal256_from_ratio_u64) -- [Function `from_ratio_u128`](#0x1_decimal256_from_ratio_u128) -- [Function `from_ratio`](#0x1_decimal256_from_ratio) -- [Function `add`](#0x1_decimal256_add) -- [Function `sub`](#0x1_decimal256_sub) -- [Function `mul_u64`](#0x1_decimal256_mul_u64) -- [Function `mul_u128`](#0x1_decimal256_mul_u128) -- [Function `mul_u256`](#0x1_decimal256_mul_u256) -- [Function `mul`](#0x1_decimal256_mul) -- [Function `div_u64`](#0x1_decimal256_div_u64) -- [Function `div_u128`](#0x1_decimal256_div_u128) -- [Function `div`](#0x1_decimal256_div) -- [Function `val`](#0x1_decimal256_val) -- [Function `is_same`](#0x1_decimal256_is_same) -- [Function `from_string`](#0x1_decimal256_from_string) -- [Function `pow`](#0x1_decimal256_pow) - - -
use 0x1::error;
-use 0x1::string;
-
- - - - - -## Struct `Decimal256` - -A fixed-point decimal value with 18 fractional digits, i.e. Decimal256{ val: 1_000_000_000_000_000_000 } == 1.0 - - -
struct Decimal256 has copy, drop, store
-
- - - -
-Fields - - -
-
-val: u256 -
-
- -
-
- - -
- - - -## Constants - - - - - - -
const DECIMAL_FRACTIONAL: u256 = 1000000000000000000;
-
- - - - - - - -
const EDIV_WITH_ZERO: u64 = 0;
-
- - - - - - - -
const EFAILED_TO_DESERIALIZE: u64 = 1;
-
- - - - - - - -
const EOUT_OF_RANGE: u64 = 2;
-
- - - - - - - -
const FRACTIONAL_LENGTH: u64 = 18;
-
- - - - - - - -
const MAX_INTEGER_PART: u256 = 115792089237316195423570985008687907853269984665640564039457;
-
- - - - - -## Function `new` - - - -
public fun new(val: u256): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun new(val: u256): Decimal256 {
-    Decimal256 { val }
-}
-
- - - -
- - - -## Function `new_u64` - - - -
public fun new_u64(val: u64): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun new_u64(val: u64): Decimal256 {
-    Decimal256 { val: (val as u256) }
-}
-
- - - -
- - - -## Function `new_u128` - - - -
public fun new_u128(val: u128): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun new_u128(val: u128): Decimal256 {
-    Decimal256 { val: (val as u256) }
-}
-
- - - -
- - - -## Function `one` - - - -
public fun one(): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun one(): Decimal256 {
-    Decimal256 { val: DECIMAL_FRACTIONAL }
-}
-
- - - -
- - - -## Function `zero` - - - -
public fun zero(): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun zero(): Decimal256 {
-    Decimal256 { val: 0 }
-}
-
- - - -
- - - -## Function `from_ratio_u64` - - - -
public fun from_ratio_u64(numerator: u64, denominator: u64): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun from_ratio_u64(numerator: u64, denominator: u64): Decimal256 {
-    assert!(denominator != 0, EDIV_WITH_ZERO);
-
-    new((numerator as u256) * DECIMAL_FRACTIONAL / (denominator as u256))
-}
-
- - - -
- - - -## Function `from_ratio_u128` - - - -
public fun from_ratio_u128(numerator: u128, denominator: u128): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun from_ratio_u128(numerator: u128, denominator: u128): Decimal256 {
-    assert!(denominator != 0, EDIV_WITH_ZERO);
-
-    new((numerator as u256) * DECIMAL_FRACTIONAL / (denominator as u256))
-}
-
- - - -
- - - -## Function `from_ratio` - - - -
public fun from_ratio(numerator: u256, denominator: u256): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun from_ratio(numerator: u256, denominator: u256): Decimal256 {
-    assert!(denominator != 0, EDIV_WITH_ZERO);
-
-    new(numerator * DECIMAL_FRACTIONAL / denominator)
-}
-
- - - -
- - - -## Function `add` - - - -
public fun add(left: &decimal256::Decimal256, right: &decimal256::Decimal256): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun add(left: &Decimal256, right: &Decimal256): Decimal256 {
-    new(left.val + right.val)
-}
-
- - - -
- - - -## Function `sub` - - - -
public fun sub(left: &decimal256::Decimal256, right: &decimal256::Decimal256): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun sub(left: &Decimal256, right: &Decimal256): Decimal256 {
-    new(left.val - right.val)
-}
-
- - - -
- - - -## Function `mul_u64` - - - -
public fun mul_u64(decimal: &decimal256::Decimal256, val: u64): u64
-
- - - -
-Implementation - - -
public fun mul_u64(decimal: &Decimal256, val: u64): u64 {
-    (decimal.val * (val as u256) / DECIMAL_FRACTIONAL as u64)
-}
-
- - - -
- - - -## Function `mul_u128` - - - -
public fun mul_u128(decimal: &decimal256::Decimal256, val: u128): u128
-
- - - -
-Implementation - - -
public fun mul_u128(decimal: &Decimal256, val: u128): u128 {
-    (decimal.val * (val as u256) / DECIMAL_FRACTIONAL as u128)
-}
-
- - - -
- - - -## Function `mul_u256` - - - -
public fun mul_u256(decimal: &decimal256::Decimal256, val: u256): u256
-
- - - -
-Implementation - - -
public fun mul_u256(decimal: &Decimal256, val: u256): u256 {
-    decimal.val * val / DECIMAL_FRACTIONAL
-}
-
- - - -
- - - -## Function `mul` - - - -
public fun mul(a: &decimal256::Decimal256, b: &decimal256::Decimal256): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun mul(a: &Decimal256, b: &Decimal256): Decimal256 {
-    new(a.val * b.val / DECIMAL_FRACTIONAL)
-}
-
- - - -
- - - -## Function `div_u64` - - - -
public fun div_u64(decimal: &decimal256::Decimal256, val: u64): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun div_u64(decimal: &Decimal256, val: u64): Decimal256 {
-    new(decimal.val / (val as u256))
-}
-
- - - -
- - - -## Function `div_u128` - - - -
public fun div_u128(decimal: &decimal256::Decimal256, val: u128): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun div_u128(decimal: &Decimal256, val: u128): Decimal256 {
-    new(decimal.val / (val as u256))
-}
-
- - - -
- - - -## Function `div` - - - -
public fun div(decimal: &decimal256::Decimal256, val: u256): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun div(decimal: &Decimal256, val: u256): Decimal256 {
-    new(decimal.val / val)
-}
-
- - - -
- - - -## Function `val` - - - -
public fun val(decimal: &decimal256::Decimal256): u256
-
- - - -
-Implementation - - -
public fun val(decimal: &Decimal256): u256 {
-    decimal.val
-}
-
- - - -
- - - -## Function `is_same` - - - -
public fun is_same(left: &decimal256::Decimal256, right: &decimal256::Decimal256): bool
-
- - - -
-Implementation - - -
public fun is_same(left: &Decimal256, right: &Decimal256): bool {
-    left.val == right.val
-}
-
- - - -
- - - -## Function `from_string` - - - -
public fun from_string(num: &string::String): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun from_string(num: &String): Decimal256 {
-    let vec = string::bytes(num);
-    let len = vector::length(vec);
-
-    let cursor = 0;
-    let dot_index = 0;
-    let val: u256 = 0;
-    while (cursor < len) {
-        let s = *vector::borrow(vec, cursor);
-        cursor = cursor + 1;
-
-        // find `.` position
-        if (s == 46) continue;
-
-        val = val * 10;
-        assert!(s >= 48 && s <= 57, error::invalid_argument(EFAILED_TO_DESERIALIZE));
-
-        let n = (s - 48 as u256);
-        val = val + n;
-
-        if (cursor == dot_index + 1) {
-            // use `<` not `<=` to safely check "out of range"
-            // (i.e. to avoid fractional part checking)
-            assert!(val < MAX_INTEGER_PART, error::invalid_argument(EOUT_OF_RANGE));
-
-            dot_index = dot_index + 1;
-        };
-    };
-
-    // ignore fractional part longer than `FRACTIONAL_LENGTH`
-    let val = if (dot_index == len) {
-        val * pow(10, FRACTIONAL_LENGTH)
-    } else {
-        let fractional_length = len - dot_index - 1;
-        if (fractional_length > FRACTIONAL_LENGTH) {
-            val / pow(10, fractional_length - FRACTIONAL_LENGTH)
-        } else {
-            val * pow(10, FRACTIONAL_LENGTH - fractional_length)
-        }
-    };
-
-    new(val)
-}
-
- - - -
- - - -## Function `pow` - - - -
fun pow(num: u256, pow_amount: u64): u256
-
- - - -
-Implementation - - -
fun pow(num: u256, pow_amount: u64): u256 {
-    let index = 0;
-    let val = 1;
-    while (index < pow_amount) {
-        val = val * num;
-        index = index + 1;
-    };
-
-    val
-}
-
- - - -
diff --git a/initia_stdlib/doc/dex.md b/initia_stdlib/doc/dex.md index 04cf49c..f4b8c74 100644 --- a/initia_stdlib/doc/dex.md +++ b/initia_stdlib/doc/dex.md @@ -54,8 +54,6 @@ - [Function `get_timestamp_from_weight`](#0x1_dex_get_timestamp_from_weight) - [Function `unpack_pair_response`](#0x1_dex_unpack_pair_response) - [Function `unpack_current_weight_response`](#0x1_dex_unpack_current_weight_response) -- [Function `check_chain_permission`](#0x1_dex_check_chain_permission) -- [Function `init_module`](#0x1_dex_init_module) - [Function `create_pair_script`](#0x1_dex_create_pair_script) - [Function `create_lbp_pair_script`](#0x1_dex_create_lbp_pair_script) - [Function `update_swap_fee_rate`](#0x1_dex_update_swap_fee_rate) @@ -69,22 +67,16 @@ - [Function `swap`](#0x1_dex_swap) - [Function `create_pair`](#0x1_dex_create_pair) - [Function `provide_liquidity`](#0x1_dex_provide_liquidity) -- [Function `coin_address`](#0x1_dex_coin_address) -- [Function `check_lbp_ended`](#0x1_dex_check_lbp_ended) -- [Function `generate_pair_key`](#0x1_dex_generate_pair_key) -- [Function `get_weight`](#0x1_dex_get_weight) - [Function `pool_info`](#0x1_dex_pool_info) - [Function `swap_simulation`](#0x1_dex_swap_simulation) - [Function `swap_simulation_given_out`](#0x1_dex_swap_simulation_given_out) - [Function `pool_metadata`](#0x1_dex_pool_metadata) -- [Function `pow`](#0x1_dex_pow) -- [Function `ln`](#0x1_dex_ln) -- [Function `mul_decimal128s`](#0x1_dex_mul_decimal128s) -
use 0x1::block;
+
use 0x1::bigdecimal;
+use 0x1::biguint;
+use 0x1::block;
 use 0x1::coin;
-use 0x1::decimal128;
 use 0x1::error;
 use 0x1::event;
 use 0x1::fungible_asset;
@@ -110,8 +102,7 @@ Pool configuration
 
 
 
-
-Fields +##### Fields
@@ -128,7 +119,7 @@ Pool configuration
-swap_fee_rate: decimal128::Decimal128 +swap_fee_rate: bigdecimal::BigDecimal
@@ -136,8 +127,6 @@ Pool configuration
-
- ## Resource `Pool` @@ -149,8 +138,7 @@ Pool configuration -
-Fields +##### Fields
@@ -169,8 +157,6 @@ Pool configuration
-
- ## Struct `Weights` @@ -182,8 +168,7 @@ Pool configuration -
-Fields +##### Fields
@@ -202,8 +187,6 @@ Pool configuration
-
- ## Struct `Weight` @@ -215,25 +198,24 @@ Pool configuration -
-Fields +##### Fields
-coin_a_weight: decimal128::Decimal128 +coin_a_weight: bigdecimal::BigDecimal
-coin_b_weight: decimal128::Decimal128 +coin_b_weight: bigdecimal::BigDecimal
-timestamp: u64 +timestamp: u64
@@ -241,8 +223,6 @@ Pool configuration
-
- ## Struct `PairKey` @@ -255,8 +235,7 @@ Key for pair -
-Fields +##### Fields
@@ -281,8 +260,6 @@ Key for pair
-
- ## Struct `PairResponse` @@ -294,8 +271,7 @@ Key for pair -
-Fields +##### Fields
@@ -324,7 +300,7 @@ Key for pair
-swap_fee_rate: decimal128::Decimal128 +swap_fee_rate: bigdecimal::BigDecimal
@@ -332,8 +308,6 @@ Key for pair
-
- ## Struct `PairByDenomResponse` @@ -345,8 +319,7 @@ Key for pair -
-Fields +##### Fields
@@ -375,7 +348,7 @@ Key for pair
-swap_fee_rate: decimal128::Decimal128 +swap_fee_rate: bigdecimal::BigDecimal
@@ -383,8 +356,6 @@ Key for pair
-
- ## Resource `CoinCapabilities` @@ -397,8 +368,7 @@ Coin capabilities -
-Fields +##### Fields
@@ -423,8 +393,6 @@ Coin capabilities
-
- ## Struct `ProvideEvent` @@ -438,8 +406,7 @@ Event emitted when provide liquidity. -
-Fields +##### Fields
@@ -482,8 +449,6 @@ Event emitted when provide liquidity.
-
- ## Struct `WithdrawEvent` @@ -497,8 +462,7 @@ Event emitted when withdraw liquidity. -
-Fields +##### Fields
@@ -541,8 +505,6 @@ Event emitted when withdraw liquidity.
-
- ## Struct `SwapEvent` @@ -556,8 +518,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -600,8 +561,6 @@ Event emitted when swap token.
-
- ## Struct `SingleAssetProvideEvent` @@ -614,8 +573,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -664,8 +622,6 @@ Event emitted when swap token.
-
- ## Struct `PoolInfoResponse` @@ -677,8 +633,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -703,8 +658,6 @@ Event emitted when swap token.
-
- ## Struct `ConfigResponse` @@ -716,8 +669,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -728,7 +680,7 @@ Event emitted when swap token.
-swap_fee_rate: decimal128::Decimal128 +swap_fee_rate: bigdecimal::BigDecimal
@@ -736,8 +688,6 @@ Event emitted when swap token.
-
- ## Struct `CurrentWeightResponse` @@ -749,19 +699,18 @@ Event emitted when swap token. -
-Fields +##### Fields
-coin_a_weight: decimal128::Decimal128 +coin_a_weight: bigdecimal::BigDecimal
-coin_b_weight: decimal128::Decimal128 +coin_b_weight: bigdecimal::BigDecimal
@@ -769,8 +718,6 @@ Event emitted when swap token.
-
- ## Struct `PairMetadataResponse` @@ -782,8 +729,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -802,8 +748,6 @@ Event emitted when swap token.
-
- ## Struct `PairDenomResponse` @@ -815,8 +759,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -835,8 +778,6 @@ Event emitted when swap token.
-
- ## Struct `CreatePairEvent` @@ -849,8 +790,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -879,7 +819,7 @@ Event emitted when swap token.
-swap_fee_rate: decimal128::Decimal128 +swap_fee_rate: bigdecimal::BigDecimal
@@ -887,8 +827,6 @@ Event emitted when swap token.
-
- ## Struct `SwapFeeUpdateEvent` @@ -901,8 +839,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -925,7 +862,7 @@ Event emitted when swap token.
-swap_fee_rate: decimal128::Decimal128 +swap_fee_rate: bigdecimal::BigDecimal
@@ -933,8 +870,6 @@ Event emitted when swap token.
-
- ## Resource `ModuleStore` @@ -947,8 +882,7 @@ Module store for storing pair infos -
-Fields +##### Fields
@@ -967,13 +901,21 @@ Module store for storing pair infos
-
- ## Constants + + +Only chain can execute. + + +
const EUNAUTHORIZED: u64 = 7;
+
+ + + Wrong coin type given @@ -984,6 +926,16 @@ Wrong coin type given + + +Weights sum must be 1.0 + + +
const EINVALID_WEIGHTS: u64 = 21;
+
+ + + LBP is not ended, only swap allowed @@ -1093,16 +1045,6 @@ All start_after must be provided or not - - -Only chain can execute. - - -
const EUNAUTHORIZED: u64 = 7;
-
- - - end time must be larger than start time @@ -1113,21 +1055,22 @@ end time must be larger than start time - + -Can not withdraw zero liquidity +Zero amount in the swap simulation is not allowed -
const EZERO_LIQUIDITY: u64 = 2;
+
const EZERO_AMOUNT_IN: u64 = 20;
 
- + +Can not withdraw zero liquidity -
const MAX_FEE_RATE: u128 = 50000000000000000;
+
const EZERO_LIQUIDITY: u64 = 2;
 
@@ -1146,7 +1089,7 @@ Can not withdraw zero liquidity Result Precision of pow and ln function -
const PRECISION: u128 = 100000;
+
const PRECISION: u64 = 100000;
 
@@ -1163,28 +1106,20 @@ Result Precision of pow and ln function -
-Implementation +##### Implementation -
public fun get_pair_metadata(
-    pair: Object<Config>,
-): PairMetadataResponse acquires Pool {
-    let pool = borrow_global_mut<Pool>(object::object_address(pair));
+
public fun get_pair_metadata(pair: Object<Config>): PairMetadataResponse acquires Pool {
+    let pool = borrow_global_mut<Pool>(object::object_address(&pair));
     let coin_a_metadata = fungible_asset::store_metadata(pool.coin_a_store);
     let coin_b_metadata = fungible_asset::store_metadata(pool.coin_b_store);
 
-    PairMetadataResponse {
-        coin_a_metadata,
-        coin_b_metadata,
-    }
+    PairMetadataResponse { coin_a_metadata, coin_b_metadata }
 }
 
-
- ## Function `get_pair_denom` @@ -1197,26 +1132,21 @@ Result Precision of pow and ln function -
-Implementation +##### Implementation -
public fun get_pair_denom(
-    pair: Object<Config>,
-): PairDenomResponse acquires Pool {
+
public fun get_pair_denom(pair: Object<Config>): PairDenomResponse acquires Pool {
     let pair_metadata = get_pair_metadata(pair);
 
     PairDenomResponse {
         coin_a_denom: coin::metadata_to_denom(pair_metadata.coin_a_metadata),
-        coin_b_denom: coin::metadata_to_denom(pair_metadata.coin_b_metadata),
+        coin_b_denom: coin::metadata_to_denom(pair_metadata.coin_b_metadata)
     }
 }
 
-
- ## Function `get_spot_price` @@ -1226,45 +1156,43 @@ https://balancer.fi/whitepaper.pdf (2)
#[view]
-public fun get_spot_price(pair: object::Object<dex::Config>, base_coin: object::Object<fungible_asset::Metadata>): decimal128::Decimal128
+public fun get_spot_price(pair: object::Object<dex::Config>, base_coin: object::Object<fungible_asset::Metadata>): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation
public fun get_spot_price(
-    pair: Object<Config>,
-    base_coin: Object<Metadata>,
-): Decimal128 acquires Config, Pool {
-    let (coin_a_pool, coin_b_pool, coin_a_weight, coin_b_weight, _) = pool_info(pair, false);
+    pair: Object<Config>, base_coin: Object<Metadata>
+): BigDecimal acquires Config, Pool {
+    let (coin_a_pool, coin_b_pool, coin_a_weight, coin_b_weight, _) =
+        pool_info(pair, false);
 
     let pair_key = generate_pair_key(pair);
-    let base_addr = object::object_address(base_coin);
+    let base_addr = object::object_address(&base_coin);
     assert!(
         base_addr == pair_key.coin_a || base_addr == pair_key.coin_b,
-        error::invalid_argument(ECOIN_TYPE),
+        error::invalid_argument(ECOIN_TYPE)
     );
     let is_base_a = base_addr == pair_key.coin_a;
-    let (base_pool, quote_pool, base_weight, quote_weight) = if (is_base_a) {
-        (coin_a_pool, coin_b_pool, coin_a_weight, coin_b_weight)
-    } else {
-        (coin_b_pool, coin_a_pool, coin_b_weight, coin_a_weight)
-    };
+    let (base_pool, quote_pool, base_weight, quote_weight) =
+        if (is_base_a) {
+            (coin_a_pool, coin_b_pool, coin_a_weight, coin_b_weight)
+        } else {
+            (coin_b_pool, coin_a_pool, coin_b_weight, coin_a_weight)
+        };
 
-    decimal128::from_ratio_u64(
-        decimal128::mul_u64(&base_weight, quote_pool),
-        decimal128::mul_u64("e_weight, base_pool),
+    bigdecimal::div(
+        bigdecimal::mul_by_u64(base_weight, quote_pool),
+        bigdecimal::mul_by_u64(quote_weight, base_pool)
     )
 }
 
-
- ## Function `get_spot_price_by_denom` @@ -1272,19 +1200,17 @@ https://balancer.fi/whitepaper.pdf (2)
#[view]
-public fun get_spot_price_by_denom(pair_denom: string::String, base_coin: string::String): decimal128::Decimal128
+public fun get_spot_price_by_denom(pair_denom: string::String, base_coin: string::String): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation
public fun get_spot_price_by_denom(
-    pair_denom: String,
-    base_coin: String,
-): Decimal128 acquires Config, Pool {
+    pair_denom: String, base_coin: String
+): BigDecimal acquires Config, Pool {
     let pair_metadata = coin::denom_to_metadata(pair_denom);
     let base_metadata = coin::denom_to_metadata(base_coin);
     get_spot_price(object::convert(pair_metadata), base_metadata)
@@ -1293,8 +1219,6 @@ https://balancer.fi/whitepaper.pdf (2)
 
 
 
-
- ## Function `get_swap_simulation` @@ -1308,36 +1232,35 @@ Return swap simulation result -
-Implementation +##### Implementation
public fun get_swap_simulation(
-    pair: Object<Config>,
-    offer_metadata: Object<Metadata>,
-    offer_amount: u64,
+    pair: Object<Config>, offer_metadata: Object<Metadata>, offer_amount: u64
 ): u64 acquires Config, Pool {
     let pair_key = generate_pair_key(pair);
-    let offer_address = object::object_address(offer_metadata);
+    let offer_address = object::object_address(&offer_metadata);
     assert!(
         offer_address == pair_key.coin_a || offer_address == pair_key.coin_b,
-        error::invalid_argument(ECOIN_TYPE),
+        error::invalid_argument(ECOIN_TYPE)
     );
     let is_offer_a = offer_address == pair_key.coin_a;
     let (pool_a, pool_b, weight_a, weight_b, swap_fee_rate) = pool_info(pair, true);
-    let (offer_pool, return_pool, offer_weight, return_weight) = if (is_offer_a) {
-        (pool_a, pool_b, weight_a, weight_b)
-    } else {
-        (pool_b, pool_a, weight_b, weight_a)
-    };
-    let (return_amount, _fee_amount) = swap_simulation(
-        offer_pool,
-        return_pool,
-        offer_weight,
-        return_weight,
-        offer_amount,
-        swap_fee_rate,
-    );
+    let (offer_pool, return_pool, offer_weight, return_weight) =
+        if (is_offer_a) {
+            (pool_a, pool_b, weight_a, weight_b)
+        } else {
+            (pool_b, pool_a, weight_b, weight_a)
+        };
+    let (return_amount, _fee_amount) =
+        swap_simulation(
+            offer_pool,
+            return_pool,
+            offer_weight,
+            return_weight,
+            offer_amount,
+            swap_fee_rate
+        );
 
     return_amount
 }
@@ -1345,8 +1268,6 @@ Return swap simulation result
 
 
 
-
- ## Function `get_swap_simulation_by_denom` @@ -1359,25 +1280,24 @@ Return swap simulation result -
-Implementation +##### Implementation
public fun get_swap_simulation_by_denom(
-    pair_denom: String,
-    offer_denom: String,
-    offer_amount: u64,
+    pair_denom: String, offer_denom: String, offer_amount: u64
 ): u64 acquires Config, Pool {
     let pair_metadata = coin::denom_to_metadata(pair_denom);
     let offer_metadata = coin::denom_to_metadata(offer_denom);
-    get_swap_simulation(object::convert(pair_metadata), offer_metadata, offer_amount)
+    get_swap_simulation(
+        object::convert(pair_metadata),
+        offer_metadata,
+        offer_amount
+    )
 }
 
-
- ## Function `get_swap_simulation_given_out` @@ -1391,36 +1311,35 @@ Return swap simulation result -
-Implementation +##### Implementation
public fun get_swap_simulation_given_out(
-    pair: Object<Config>,
-    offer_metadata: Object<Metadata>,
-    return_amount: u64,
+    pair: Object<Config>, offer_metadata: Object<Metadata>, return_amount: u64
 ): u64 acquires Config, Pool {
     let pair_key = generate_pair_key(pair);
-    let offer_address = object::object_address(offer_metadata);
+    let offer_address = object::object_address(&offer_metadata);
     assert!(
         offer_address == pair_key.coin_a || offer_address == pair_key.coin_b,
-        error::invalid_argument(ECOIN_TYPE),
+        error::invalid_argument(ECOIN_TYPE)
     );
     let is_offer_a = offer_address == pair_key.coin_a;
     let (pool_a, pool_b, weight_a, weight_b, swap_fee_rate) = pool_info(pair, true);
-    let (offer_pool, return_pool, offer_weight, return_weight) = if (is_offer_a) {
-        (pool_a, pool_b, weight_a, weight_b)
-    } else {
-        (pool_b, pool_a, weight_b, weight_a)
-    };
-    let (offer_amount, _fee_amount) = swap_simulation_given_out(
-        offer_pool,
-        return_pool,
-        offer_weight,
-        return_weight,
-        return_amount,
-        swap_fee_rate,
-    );
+    let (offer_pool, return_pool, offer_weight, return_weight) =
+        if (is_offer_a) {
+            (pool_a, pool_b, weight_a, weight_b)
+        } else {
+            (pool_b, pool_a, weight_b, weight_a)
+        };
+    let (offer_amount, _fee_amount) =
+        swap_simulation_given_out(
+            offer_pool,
+            return_pool,
+            offer_weight,
+            return_weight,
+            return_amount,
+            swap_fee_rate
+        );
 
     offer_amount
 }
@@ -1428,8 +1347,6 @@ Return swap simulation result
 
 
 
-
- ## Function `get_swap_simulation_given_out_by_denom` @@ -1442,25 +1359,24 @@ Return swap simulation result -
-Implementation +##### Implementation
public fun get_swap_simulation_given_out_by_denom(
-    pair_denom: String,
-    offer_denom: String,
-    return_amount: u64,
+    pair_denom: String, offer_denom: String, return_amount: u64
 ): u64 acquires Config, Pool {
     let pair_metadata = coin::denom_to_metadata(pair_denom);
     let offer_metadata = coin::denom_to_metadata(offer_denom);
-    get_swap_simulation_given_out(object::convert(pair_metadata), offer_metadata, return_amount)
+    get_swap_simulation_given_out(
+        object::convert(pair_metadata),
+        offer_metadata,
+        return_amount
+    )
 }
 
-
- ## Function `get_pool_info` @@ -1474,25 +1390,22 @@ get pool info -
-Implementation +##### Implementation
public fun get_pool_info(pair: Object<Config>): PoolInfoResponse acquires Pool {
-    let pair_addr = object::object_address(pair);
+    let pair_addr = object::object_address(&pair);
     let pool = borrow_global<Pool>(pair_addr);
     PoolInfoResponse {
         coin_a_amount: fungible_asset::balance(pool.coin_a_store),
         coin_b_amount: fungible_asset::balance(pool.coin_b_store),
-        total_share: option::extract(&mut fungible_asset::supply(pair)),
+        total_share: option::extract(&mut fungible_asset::supply(pair))
     }
 }
 
-
- ## Function `get_pool_info_by_denom` @@ -1506,8 +1419,7 @@ get pool info -
-Implementation +##### Implementation
public fun get_pool_info_by_denom(pair_denom: String): PoolInfoResponse acquires Pool {
@@ -1518,8 +1430,6 @@ get pool info
 
 
 
-
- ## Function `get_config` @@ -1533,25 +1443,19 @@ get config -
-Implementation +##### Implementation
public fun get_config(pair: Object<Config>): ConfigResponse acquires Config {
-    let pair_addr = object::object_address(pair);
+    let pair_addr = object::object_address(&pair);
     let config = borrow_global<Config>(pair_addr);
 
-    ConfigResponse {
-        weights: config.weights,
-        swap_fee_rate: config.swap_fee_rate,
-    }
+    ConfigResponse { weights: config.weights, swap_fee_rate: config.swap_fee_rate }
 }
 
-
- ## Function `get_config_by_denom` @@ -1565,8 +1469,7 @@ get config -
-Implementation +##### Implementation
public fun get_config_by_denom(pair_denom: String): ConfigResponse acquires Config {
@@ -1577,8 +1480,6 @@ get config
 
 
 
-
- ## Function `get_current_weight` @@ -1591,25 +1492,19 @@ get config -
-Implementation +##### Implementation
public fun get_current_weight(pair: Object<Config>): CurrentWeightResponse acquires Config {
-    let pair_addr = object::object_address(pair);
+    let pair_addr = object::object_address(&pair);
     let config = borrow_global<Config>(pair_addr);
     let (coin_a_weight, coin_b_weight) = get_weight(&config.weights);
-    CurrentWeightResponse {
-        coin_a_weight,
-        coin_b_weight,
-    }
+    CurrentWeightResponse { coin_a_weight, coin_b_weight }
 }
 
-
- ## Function `get_current_weight_by_denom` @@ -1622,11 +1517,12 @@ get config -
-Implementation +##### Implementation -
public fun get_current_weight_by_denom(pair_denom: String): CurrentWeightResponse acquires Config {
+
public fun get_current_weight_by_denom(
+    pair_denom: String
+): CurrentWeightResponse acquires Config {
     let pair_metadata = coin::denom_to_metadata(pair_denom);
     get_current_weight(object::convert(pair_metadata))
 }
@@ -1634,8 +1530,6 @@ get config
 
 
 
-
- ## Function `get_all_pairs` @@ -1648,52 +1542,55 @@ get config -
-Implementation +##### Implementation
public fun get_all_pairs(
     coin_a_start_after: Option<address>,
     coin_b_start_after: Option<address>,
     liquidity_token_start_after: Option<address>,
-    limit: u8,
+    limit: u8
 ): vector<PairResponse> acquires ModuleStore {
     if (limit > MAX_LIMIT) {
         limit = MAX_LIMIT;
     };
 
     assert!(
-        option::is_some(&coin_a_start_after) == option::is_some(&coin_b_start_after)
-            && option::is_some(&coin_b_start_after) == option::is_some(&liquidity_token_start_after),
+        option::is_some(&coin_a_start_after)
+            == option::is_some(&coin_b_start_after)
+            && option::is_some(&coin_b_start_after)
+                == option::is_some(&liquidity_token_start_after),
         ESTART_AFTER
     );
 
     let module_store = borrow_global<ModuleStore>(@initia_std);
 
-    let start_after = if (option::is_some(&coin_a_start_after)) {
-        option::some(PairKey {
-            coin_a: option::extract(&mut coin_a_start_after),
-            coin_b: option::extract(&mut coin_b_start_after),
-            liquidity_token: option::extract(&mut liquidity_token_start_after),
-        })
-    } else {
-        option::some(PairKey {
-            coin_a: @0x0,
-            coin_b: @0x0,
-            liquidity_token: @0x0,
-        })
-    };
+    let start_after =
+        if (option::is_some(&coin_a_start_after)) {
+            option::some(
+                PairKey {
+                    coin_a: option::extract(&mut coin_a_start_after),
+                    coin_b: option::extract(&mut coin_b_start_after),
+                    liquidity_token: option::extract(&mut liquidity_token_start_after)
+                }
+            )
+        } else {
+            option::some(
+                PairKey { coin_a: @0x0, coin_b: @0x0, liquidity_token: @0x0 }
+            )
+        };
 
     let res = vector[];
     let pairs_iter = table::iter(
         &module_store.pairs,
         start_after,
         option::none(),
-        1,
+        1
     );
 
-    while (vector::length(&res) < (limit as u64) && table::prepare<PairKey, PairResponse>(&mut pairs_iter)) {
-        let (key, value) = table::next<PairKey, PairResponse>(&mut pairs_iter);
+    while (vector::length(&res) < (limit as u64)
+        && table::prepare<PairKey, PairResponse>(pairs_iter)) {
+        let (key, value) = table::next<PairKey, PairResponse>(pairs_iter);
         if (&key != option::borrow(&start_after)) {
             vector::push_back(&mut res, *value)
         }
@@ -1705,8 +1602,6 @@ get config
 
 
 
-
- ## Function `get_all_pairs_by_denom` @@ -1719,63 +1614,82 @@ get config -
-Implementation +##### Implementation
public fun get_all_pairs_by_denom(
     coin_a_start_after: Option<String>,
     coin_b_start_after: Option<String>,
     liquidity_token_start_after: Option<String>,
-    limit: u8,
+    limit: u8
 ): vector<PairByDenomResponse> acquires ModuleStore {
     if (limit > MAX_LIMIT) {
         limit = MAX_LIMIT;
     };
 
     assert!(
-        option::is_some(&coin_a_start_after) == option::is_some(&coin_b_start_after)
-            && option::is_some(&coin_b_start_after) == option::is_some(&liquidity_token_start_after),
+        option::is_some(&coin_a_start_after)
+            == option::is_some(&coin_b_start_after)
+            && option::is_some(&coin_b_start_after)
+                == option::is_some(&liquidity_token_start_after),
         ESTART_AFTER
     );
 
     let module_store = borrow_global<ModuleStore>(@initia_std);
 
-    let start_after = if (option::is_some(&coin_a_start_after)) {
-        let coin_a_start_after = coin::denom_to_metadata(option::extract(&mut coin_a_start_after));
-        let coin_b_start_after = coin::denom_to_metadata(option::extract(&mut coin_b_start_after));
-        let liquidity_token_start_after = coin::denom_to_metadata(option::extract(&mut liquidity_token_start_after));
-        option::some(PairKey {
-            coin_a: object::object_address(coin_a_start_after),
-            coin_b: object::object_address(coin_b_start_after),
-            liquidity_token: object::object_address(liquidity_token_start_after),
-        })
-    } else {
-        option::some(PairKey {
-            coin_a: @0x0,
-            coin_b: @0x0,
-            liquidity_token: @0x0,
-        })
-    };
+    let start_after =
+        if (option::is_some(&coin_a_start_after)) {
+            let coin_a_start_after =
+                coin::denom_to_metadata(option::extract(&mut coin_a_start_after));
+            let coin_b_start_after =
+                coin::denom_to_metadata(option::extract(&mut coin_b_start_after));
+            let liquidity_token_start_after =
+                coin::denom_to_metadata(
+                    option::extract(&mut liquidity_token_start_after)
+                );
+            option::some(
+                PairKey {
+                    coin_a: object::object_address(&coin_a_start_after),
+                    coin_b: object::object_address(&coin_b_start_after),
+                    liquidity_token: object::object_address(
+                        &liquidity_token_start_after
+                    )
+                }
+            )
+        } else {
+            option::some(
+                PairKey { coin_a: @0x0, coin_b: @0x0, liquidity_token: @0x0 }
+            )
+        };
 
     let res = vector[];
     let pairs_iter = table::iter(
         &module_store.pairs,
         start_after,
         option::none(),
-        1,
+        1
     );
 
-    while (vector::length(&res) < (limit as u64) && table::prepare<PairKey, PairResponse>(&mut pairs_iter)) {
-        let (key, value) = table::next<PairKey, PairResponse>(&mut pairs_iter);
+    while (vector::length(&res) < (limit as u64)
+        && table::prepare<PairKey, PairResponse>(pairs_iter)) {
+        let (key, value) = table::next<PairKey, PairResponse>(pairs_iter);
         if (&key != option::borrow(&start_after)) {
-            vector::push_back(&mut res, PairByDenomResponse {
-                coin_a: coin::metadata_to_denom(object::address_to_object(value.coin_a)),
-                coin_b: coin::metadata_to_denom(object::address_to_object(value.coin_b)),
-                liquidity_token: coin::metadata_to_denom(object::address_to_object(value.liquidity_token)),
-                weights: value.weights,
-                swap_fee_rate: value.swap_fee_rate,
-            })
+            vector::push_back(
+                &mut res,
+                PairByDenomResponse {
+                    coin_a: coin::metadata_to_denom(
+                        object::address_to_object(value.coin_a)
+                    ),
+                    coin_b: coin::metadata_to_denom(
+                        object::address_to_object(value.coin_b)
+                    ),
+                    liquidity_token: coin::metadata_to_denom(
+                        object::address_to_object(value.liquidity_token)
+                    ),
+                    weights: value.weights,
+                    swap_fee_rate: value.swap_fee_rate
+                }
+            )
         }
     };
 
@@ -1785,8 +1699,6 @@ get config
 
 
 
-
- ## Function `get_pairs` @@ -1799,15 +1711,14 @@ get config -
-Implementation +##### Implementation
public fun get_pairs(
     coin_a: address,
     coin_b: address,
     start_after: Option<address>,
-    limit: u8,
+    limit: u8
 ): vector<PairResponse> acquires ModuleStore {
     if (limit > MAX_LIMIT) {
         limit = MAX_LIMIT;
@@ -1815,31 +1726,32 @@ get config
 
     let module_store = borrow_global<ModuleStore>(@initia_std);
 
-    let start_after = if (option::is_some(&start_after)) {
-        option::some(PairKey {
-            coin_a,
-            coin_b,
-            liquidity_token: option::extract(&mut start_after),
-        })
-    } else {
-        option::some(PairKey {
-            coin_a,
-            coin_b,
-            liquidity_token: @0x0,
-        })
-    };
+    let start_after =
+        if (option::is_some(&start_after)) {
+            option::some(
+                PairKey {
+                    coin_a,
+                    coin_b,
+                    liquidity_token: option::extract(&mut start_after)
+                }
+            )
+        } else {
+            option::some(PairKey { coin_a, coin_b, liquidity_token: @0x0 })
+        };
 
     let res = vector[];
     let pairs_iter = table::iter(
         &module_store.pairs,
         start_after,
         option::none(),
-        1,
+        1
     );
 
-    while (vector::length(&res) < (limit as u64) && table::prepare<PairKey, PairResponse>(&mut pairs_iter)) {
-        let (key, value) = table::next<PairKey, PairResponse>(&mut pairs_iter);
-        if (coin_a != key.coin_a || coin_b != key.coin_b) break;
+    while (vector::length(&res) < (limit as u64)
+        && table::prepare<PairKey, PairResponse>(pairs_iter)) {
+        let (key, value) = table::next<PairKey, PairResponse>(pairs_iter);
+        if (coin_a != key.coin_a || coin_b != key.coin_b)
+            break;
         if (&key != option::borrow(&start_after)) {
             vector::push_back(&mut res, *value)
         }
@@ -1851,8 +1763,6 @@ get config
 
 
 
-
- ## Function `get_coin_a_amount_from_pool_info_response` @@ -1864,19 +1774,18 @@ get config -
-Implementation +##### Implementation -
public fun get_coin_a_amount_from_pool_info_response(res: &PoolInfoResponse): u64 {
+
public fun get_coin_a_amount_from_pool_info_response(
+    res: &PoolInfoResponse
+): u64 {
     res.coin_a_amount
 }
 
-
- ## Function `get_coin_b_amount_from_pool_info_response` @@ -1888,19 +1797,18 @@ get config -
-Implementation +##### Implementation -
public fun get_coin_b_amount_from_pool_info_response(res: &PoolInfoResponse): u64 {
+
public fun get_coin_b_amount_from_pool_info_response(
+    res: &PoolInfoResponse
+): u64 {
     res.coin_b_amount
 }
 
-
- ## Function `get_total_share_from_pool_info_response` @@ -1912,43 +1820,41 @@ get config -
-Implementation +##### Implementation -
public fun get_total_share_from_pool_info_response(res: &PoolInfoResponse): u128 {
+
public fun get_total_share_from_pool_info_response(
+    res: &PoolInfoResponse
+): u128 {
     res.total_share
 }
 
-
- ## Function `get_swap_fee_rate_from_config_response` -
public fun get_swap_fee_rate_from_config_response(res: &dex::ConfigResponse): decimal128::Decimal128
+
public fun get_swap_fee_rate_from_config_response(res: &dex::ConfigResponse): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation -
public fun get_swap_fee_rate_from_config_response(res: &ConfigResponse): Decimal128 {
+
public fun get_swap_fee_rate_from_config_response(
+    res: &ConfigResponse
+): BigDecimal {
     res.swap_fee_rate
 }
 
-
- ## Function `get_weight_before_from_config_response` @@ -1960,19 +1866,18 @@ get config -
-Implementation +##### Implementation -
public fun get_weight_before_from_config_response(res: &ConfigResponse): Weight {
+
public fun get_weight_before_from_config_response(
+    res: &ConfigResponse
+): Weight {
     res.weights.weights_before
 }
 
-
- ## Function `get_weight_after_from_config_response` @@ -1984,8 +1889,7 @@ get config -
-Implementation +##### Implementation
public fun get_weight_after_from_config_response(res: &ConfigResponse): Weight {
@@ -1995,56 +1899,48 @@ get config
 
 
 
-
- ## Function `get_coin_a_weight_from_weight` -
public fun get_coin_a_weight_from_weight(weight: &dex::Weight): decimal128::Decimal128
+
public fun get_coin_a_weight_from_weight(weight: &dex::Weight): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation -
public fun get_coin_a_weight_from_weight(weight: &Weight): Decimal128 {
+
public fun get_coin_a_weight_from_weight(weight: &Weight): BigDecimal {
     weight.coin_a_weight
 }
 
-
- ## Function `get_coin_b_weight_from_weight` -
public fun get_coin_b_weight_from_weight(weight: &dex::Weight): decimal128::Decimal128
+
public fun get_coin_b_weight_from_weight(weight: &dex::Weight): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation -
public fun get_coin_b_weight_from_weight(weight: &Weight): Decimal128 {
+
public fun get_coin_b_weight_from_weight(weight: &Weight): BigDecimal {
     weight.coin_b_weight
 }
 
-
- ## Function `get_timestamp_from_weight` @@ -2056,35 +1952,33 @@ get config -
-Implementation +##### Implementation
public fun get_timestamp_from_weight(weight: &Weight): u64 {
-    weight.timestamp
+    weight.timestamp
 }
 
-
- ## Function `unpack_pair_response` -
public fun unpack_pair_response(pair_response: &dex::PairResponse): (address, address, address, dex::Weights, decimal128::Decimal128)
+
public fun unpack_pair_response(pair_response: &dex::PairResponse): (address, address, address, dex::Weights, bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation -
public fun unpack_pair_response(pair_response: &PairResponse): (address, address, address, Weights, Decimal128) {
+
public fun unpack_pair_response(
+    pair_response: &PairResponse
+): (address, address, address, Weights, BigDecimal) {
     (
         pair_response.coin_a,
         pair_response.coin_b,
@@ -2097,140 +1991,88 @@ get config
 
 
 
-
- ## Function `unpack_current_weight_response` -
public fun unpack_current_weight_response(current_weight_response: &dex::CurrentWeightResponse): (decimal128::Decimal128, decimal128::Decimal128)
+
public fun unpack_current_weight_response(current_weight_response: &dex::CurrentWeightResponse): (bigdecimal::BigDecimal, bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation -
public fun unpack_current_weight_response(current_weight_response: &CurrentWeightResponse): (Decimal128, Decimal128) {
-    (
-        current_weight_response.coin_a_weight,
-        current_weight_response.coin_b_weight,
-    )
+
public fun unpack_current_weight_response(
+    current_weight_response: &CurrentWeightResponse
+): (BigDecimal, BigDecimal) {
+    (current_weight_response.coin_a_weight, current_weight_response.coin_b_weight)
 }
 
-
- - - -## Function `check_chain_permission` - -Check signer is chain - - -
fun check_chain_permission(chain: &signer)
-
- - - -
-Implementation - - -
fun check_chain_permission(chain: &signer) {
-    assert!(signer::address_of(chain) == @initia_std, error::permission_denied(EUNAUTHORIZED));
-}
-
- - - -
- - - -## Function `init_module` - - - -
fun init_module(chain: &signer)
-
- - - -
-Implementation - - -
fun init_module(chain: &signer) {
-    move_to(chain, ModuleStore {
-        pairs: table::new<PairKey, PairResponse>(),
-        pair_count: 0,
-    });
-}
-
- - - -
- ## Function `create_pair_script` -
public entry fun create_pair_script(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: decimal128::Decimal128, coin_a_weight: decimal128::Decimal128, coin_b_weight: decimal128::Decimal128, coin_a_metadata: object::Object<fungible_asset::Metadata>, coin_b_metadata: object::Object<fungible_asset::Metadata>, coin_a_amount: u64, coin_b_amount: u64)
+
public entry fun create_pair_script(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: bigdecimal::BigDecimal, coin_a_weight: bigdecimal::BigDecimal, coin_b_weight: bigdecimal::BigDecimal, coin_a_metadata: object::Object<fungible_asset::Metadata>, coin_b_metadata: object::Object<fungible_asset::Metadata>, coin_a_amount: u64, coin_b_amount: u64)
 
-
-Implementation +##### Implementation
public entry fun create_pair_script(
     creator: &signer,
     name: String,
     symbol: String,
-    swap_fee_rate: Decimal128,
-    coin_a_weight: Decimal128,
-    coin_b_weight: Decimal128,
+    swap_fee_rate: BigDecimal,
+    coin_a_weight: BigDecimal,
+    coin_b_weight: BigDecimal,
     coin_a_metadata: Object<Metadata>,
     coin_b_metadata: Object<Metadata>,
     coin_a_amount: u64,
-    coin_b_amount: u64,
+    coin_b_amount: u64
 ) acquires CoinCapabilities, Config, Pool, ModuleStore {
-    let (_, timestamp) = get_block_info();
+    let (_, timestamp) = get_block_info();
     let weights = Weights {
-        weights_before: Weight {
-            coin_a_weight,
-            coin_b_weight,
-            timestamp
-        },
-        weights_after: Weight {
-            coin_a_weight,
-            coin_b_weight,
-            timestamp
-        }
+        weights_before: Weight { coin_a_weight, coin_b_weight, timestamp },
+        weights_after: Weight { coin_a_weight, coin_b_weight, timestamp }
     };
 
-    let coin_a = coin::withdraw(creator, coin_a_metadata, coin_a_amount);
-    let coin_b = coin::withdraw(creator, coin_b_metadata, coin_b_amount);
+    let coin_a = coin::withdraw(
+        creator,
+        coin_a_metadata,
+        coin_a_amount
+    );
+    let coin_b = coin::withdraw(
+        creator,
+        coin_b_metadata,
+        coin_b_amount
+    );
 
-    let liquidity_token = create_pair(creator, name, symbol, swap_fee_rate, coin_a, coin_b, weights);
+    let liquidity_token =
+        create_pair(
+            creator,
+            name,
+            symbol,
+            swap_fee_rate,
+            coin_a,
+            coin_b,
+            weights
+        );
     coin::deposit(signer::address_of(creator), liquidity_token);
 }
 
-
- ## Function `create_lbp_pair_script` @@ -2240,59 +2082,79 @@ permission check will be done in LP coin initialize only LP struct owner can initialize -
public entry fun create_lbp_pair_script(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: decimal128::Decimal128, start_time: u64, coin_a_start_weight: decimal128::Decimal128, coin_b_start_weight: decimal128::Decimal128, end_time: u64, coin_a_end_weight: decimal128::Decimal128, coin_b_end_weight: decimal128::Decimal128, coin_a_metadata: object::Object<fungible_asset::Metadata>, coin_b_metadata: object::Object<fungible_asset::Metadata>, coin_a_amount: u64, coin_b_amount: u64)
+
public entry fun create_lbp_pair_script(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: bigdecimal::BigDecimal, start_time: u64, coin_a_start_weight: bigdecimal::BigDecimal, coin_b_start_weight: bigdecimal::BigDecimal, end_time: u64, coin_a_end_weight: bigdecimal::BigDecimal, coin_b_end_weight: bigdecimal::BigDecimal, coin_a_metadata: object::Object<fungible_asset::Metadata>, coin_b_metadata: object::Object<fungible_asset::Metadata>, coin_a_amount: u64, coin_b_amount: u64)
 
-
-Implementation +##### Implementation
public entry fun create_lbp_pair_script(
     creator: &signer,
     name: String,
     symbol: String,
-    swap_fee_rate: Decimal128,
+    swap_fee_rate: BigDecimal,
     start_time: u64,
-    coin_a_start_weight: Decimal128,
-    coin_b_start_weight: Decimal128,
+    coin_a_start_weight: BigDecimal,
+    coin_b_start_weight: BigDecimal,
     end_time: u64,
-    coin_a_end_weight: Decimal128,
-    coin_b_end_weight: Decimal128,
+    coin_a_end_weight: BigDecimal,
+    coin_b_end_weight: BigDecimal,
     coin_a_metadata: Object<Metadata>,
     coin_b_metadata: Object<Metadata>,
     coin_a_amount: u64,
-    coin_b_amount: u64,
+    coin_b_amount: u64
 ) acquires CoinCapabilities, Config, ModuleStore, Pool {
-    let (_, timestamp) = get_block_info();
-    assert!(start_time > timestamp, error::invalid_argument(ELBP_START_TIME));
-    assert!(end_time > start_time, error::invalid_argument(EWEIGHTS_TIMESTAMP));
+    let (_, timestamp) = get_block_info();
+    assert!(
+        start_time > timestamp,
+        error::invalid_argument(ELBP_START_TIME)
+    );
+    assert!(
+        end_time > start_time,
+        error::invalid_argument(EWEIGHTS_TIMESTAMP)
+    );
     let weights = Weights {
         weights_before: Weight {
             coin_a_weight: coin_a_start_weight,
             coin_b_weight: coin_b_start_weight,
-            timestamp: start_time,
+            timestamp: start_time
         },
         weights_after: Weight {
             coin_a_weight: coin_a_end_weight,
             coin_b_weight: coin_b_end_weight,
-            timestamp: end_time,
+            timestamp: end_time
         }
     };
 
-    let coin_a = coin::withdraw(creator, coin_a_metadata, coin_a_amount);
-    let coin_b = coin::withdraw(creator, coin_b_metadata, coin_b_amount);
+    let coin_a = coin::withdraw(
+        creator,
+        coin_a_metadata,
+        coin_a_amount
+    );
+    let coin_b = coin::withdraw(
+        creator,
+        coin_b_metadata,
+        coin_b_amount
+    );
 
-    let liquidity_token = create_pair(creator, name, symbol, swap_fee_rate, coin_a, coin_b, weights);
+    let liquidity_token =
+        create_pair(
+            creator,
+            name,
+            symbol,
+            swap_fee_rate,
+            coin_a,
+            coin_b,
+            weights
+        );
     coin::deposit(signer::address_of(creator), liquidity_token);
 }
 
-
- ## Function `update_swap_fee_rate` @@ -2300,25 +2162,22 @@ only LP struct owner can initialize update swap fee rate -
public entry fun update_swap_fee_rate(chain: &signer, pair: object::Object<dex::Config>, swap_fee_rate: decimal128::Decimal128)
+
public entry fun update_swap_fee_rate(chain: &signer, pair: object::Object<dex::Config>, swap_fee_rate: bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation
public entry fun update_swap_fee_rate(
-    chain: &signer,
-    pair: Object<Config>,
-    swap_fee_rate: Decimal128,
+    chain: &signer, pair: Object<Config>, swap_fee_rate: BigDecimal
 ) acquires Config, Pool, ModuleStore {
     check_chain_permission(chain);
 
-    let config = borrow_global_mut<Config>(object::object_address(pair));
+    let config = borrow_global_mut<Config>(object::object_address(&pair));
     assert!(
-        decimal128::val(&swap_fee_rate) <= MAX_FEE_RATE,
+        bigdecimal::le(swap_fee_rate, max_fee_rate()),
         error::invalid_argument(EOUT_OF_SWAP_FEE_RATE_RANGE)
     );
 
@@ -2327,10 +2186,7 @@ update swap fee rate
 
     // update PairResponse
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let pair_response = table::borrow_mut(
-        &mut module_store.pairs,
-        pair_key,
-    );
+    let pair_response = table::borrow_mut(&mut module_store.pairs, pair_key);
 
     pair_response.swap_fee_rate = swap_fee_rate;
 
@@ -2340,16 +2196,14 @@ update swap fee rate
             coin_a: pair_key.coin_a,
             coin_b: pair_key.coin_b,
             liquidity_token: pair_key.liquidity_token,
-            swap_fee_rate,
-        },
+            swap_fee_rate
+        }
     );
 }
 
-
- ## Function `provide_liquidity_script` @@ -2362,8 +2216,7 @@ script of provide_liquidity_from_coin_store -
-Implementation +##### Implementation
public entry fun provide_liquidity_script(
@@ -2378,15 +2231,13 @@ script of provide_liquidity_from_coin_store
         pair,
         coin_a_amount_in,
         coin_b_amount_in,
-        min_liquidity,
+        min_liquidity
     );
 }
 
-
- ## Function `provide_liquidity_from_coin_store` @@ -2399,8 +2250,7 @@ Provide liquidity with 0x1::coin::CoinStore coins -
-Implementation +##### Implementation
public fun provide_liquidity_from_coin_store(
@@ -2410,39 +2260,57 @@ Provide liquidity with 0x1::coin::CoinStore coins
     coin_b_amount_in: u64,
     min_liquidity: Option<u64>
 ): (u64, u64, u64) acquires CoinCapabilities, Config, Pool {
-    let pair_addr = object::object_address(pair);
+    let pair_addr = object::object_address(&pair);
     let pool = borrow_global_mut<Pool>(pair_addr);
     let coin_a_amount = fungible_asset::balance(pool.coin_a_store);
     let coin_b_amount = fungible_asset::balance(pool.coin_b_store);
     let total_share = option::extract(&mut fungible_asset::supply(pair));
 
     // calculate the best coin amount
-    let (coin_a, coin_b) = if (total_share == 0) {
-        (
-            coin::withdraw(account, fungible_asset::store_metadata(pool.coin_a_store), coin_a_amount_in),
-            coin::withdraw(account, fungible_asset::store_metadata(pool.coin_b_store), coin_b_amount_in),
-        )
-    } else {
-        let coin_a_share_ratio = decimal128::from_ratio_u64(coin_a_amount_in, coin_a_amount);
-        let coin_b_share_ratio = decimal128::from_ratio_u64(coin_b_amount_in, coin_b_amount);
-        if (decimal128::val(&coin_a_share_ratio) > decimal128::val(&coin_b_share_ratio)) {
-            coin_a_amount_in = decimal128::mul_u64(&coin_b_share_ratio, coin_a_amount);
+    let (coin_a, coin_b) =
+        if (total_share == 0) {
+            (
+                coin::withdraw(
+                    account,
+                    fungible_asset::store_metadata(pool.coin_a_store),
+                    coin_a_amount_in
+                ),
+                coin::withdraw(
+                    account,
+                    fungible_asset::store_metadata(pool.coin_b_store),
+                    coin_b_amount_in
+                )
+            )
         } else {
-            coin_b_amount_in = decimal128::mul_u64(&coin_a_share_ratio, coin_b_amount);
+            let coin_a_share_ratio =
+                bigdecimal::from_ratio_u64(coin_a_amount_in, coin_a_amount);
+            let coin_b_share_ratio =
+                bigdecimal::from_ratio_u64(coin_b_amount_in, coin_b_amount);
+            if (bigdecimal::gt(coin_a_share_ratio, coin_b_share_ratio)) {
+                coin_a_amount_in = bigdecimal::mul_by_u64_truncate(
+                    coin_b_share_ratio, coin_a_amount
+                );
+            } else {
+                coin_b_amount_in = bigdecimal::mul_by_u64_truncate(
+                    coin_a_share_ratio, coin_b_amount
+                );
+            };
+
+            (
+                coin::withdraw(
+                    account,
+                    fungible_asset::store_metadata(pool.coin_a_store),
+                    coin_a_amount_in
+                ),
+                coin::withdraw(
+                    account,
+                    fungible_asset::store_metadata(pool.coin_b_store),
+                    coin_b_amount_in
+                )
+            )
         };
 
-        (
-            coin::withdraw(account, fungible_asset::store_metadata(pool.coin_a_store), coin_a_amount_in),
-            coin::withdraw(account, fungible_asset::store_metadata(pool.coin_b_store), coin_b_amount_in),
-        )
-    };
-
-    let liquidity_token = provide_liquidity(
-        pair,
-        coin_a,
-        coin_b,
-        min_liquidity,
-    );
+    let liquidity_token = provide_liquidity(pair, coin_a, coin_b, min_liquidity);
 
     let liquidity_token_amount = fungible_asset::amount(&liquidity_token);
     coin::deposit(signer::address_of(account), liquidity_token);
@@ -2453,8 +2321,6 @@ Provide liquidity with 0x1::coin::CoinStore coins
 
 
 
-
- ## Function `withdraw_liquidity_script` @@ -2467,8 +2333,7 @@ Withdraw liquidity with liquidity token in the token store -
-Implementation +##### Implementation
public entry fun withdraw_liquidity_script(
@@ -2476,17 +2341,26 @@ Withdraw liquidity with liquidity token in the token store
     pair: Object<Config>,
     liquidity: u64,
     min_coin_a_amount: Option<u64>,
-    min_coin_b_amount: Option<u64>,
+    min_coin_b_amount: Option<u64>
 ) acquires CoinCapabilities, Config, Pool {
-    assert!(liquidity != 0, error::invalid_argument(EZERO_LIQUIDITY));
+    assert!(
+        liquidity != 0,
+        error::invalid_argument(EZERO_LIQUIDITY)
+    );
 
     let addr = signer::address_of(account);
-    let liquidity_token = coin::withdraw(account, object::convert<Config, Metadata>(pair), liquidity);
-    let (coin_a, coin_b) = withdraw_liquidity(
-        liquidity_token,
-        min_coin_a_amount,
-        min_coin_b_amount,
-    );
+    let liquidity_token =
+        coin::withdraw(
+            account,
+            object::convert<Config, Metadata>(pair),
+            liquidity
+        );
+    let (coin_a, coin_b) =
+        withdraw_liquidity(
+            liquidity_token,
+            min_coin_a_amount,
+            min_coin_b_amount
+        );
 
     coin::deposit(addr, coin_a);
     coin::deposit(addr, coin_b);
@@ -2495,8 +2369,6 @@ Withdraw liquidity with liquidity token in the token store
 
 
 
-
- ## Function `swap_script` @@ -2509,8 +2381,7 @@ Swap with the coin in the coin store -
-Implementation +##### Implementation
public entry fun swap_script(
@@ -2518,14 +2389,21 @@ Swap with the coin in the coin store
     pair: Object<Config>,
     offer_coin: Object<Metadata>,
     offer_coin_amount: u64,
-    min_return: Option<u64>,
+    min_return: Option<u64>
 ) acquires Config, Pool {
-    let offer_coin = coin::withdraw(account, offer_coin, offer_coin_amount);
+    let offer_coin = coin::withdraw(
+        account,
+        offer_coin,
+        offer_coin_amount
+    );
     let return_coin = swap(pair, offer_coin);
 
     assert!(
-        option::is_none(&min_return) || *option::borrow(&min_return) <= fungible_asset::amount(&return_coin),
-        error::invalid_state(EMIN_RETURN),
+        option::is_none(&min_return)
+            || *option::borrow(&min_return) <= fungible_asset::amount(
+                &return_coin
+            ),
+        error::invalid_state(EMIN_RETURN)
     );
 
     coin::deposit(signer::address_of(account), return_coin);
@@ -2534,8 +2412,6 @@ Swap with the coin in the coin store
 
 
 
-
- ## Function `single_asset_provide_liquidity_script` @@ -2548,8 +2424,7 @@ Single asset provide liquidity with token in the token store -
-Implementation +##### Implementation
public entry fun single_asset_provide_liquidity_script(
@@ -2561,11 +2436,8 @@ Single asset provide liquidity with token in the token store
 ) acquires Config, CoinCapabilities, Pool {
     let addr = signer::address_of(account);
     let provide_coin = coin::withdraw(account, provide_coin, amount_in);
-    let liquidity_token = single_asset_provide_liquidity(
-        pair,
-        provide_coin,
-        min_liquidity,
-    );
+    let liquidity_token =
+        single_asset_provide_liquidity(pair, provide_coin, min_liquidity);
 
     coin::deposit(addr, liquidity_token);
 }
@@ -2573,8 +2445,6 @@ Single asset provide liquidity with token in the token store
 
 
 
-
- ## Function `withdraw_liquidity` @@ -2588,41 +2458,51 @@ CONTRACT: not allow until LBP is ended -
-Implementation +##### Implementation
public fun withdraw_liquidity(
     lp_token: FungibleAsset,
     min_coin_a_amount: Option<u64>,
-    min_coin_b_amount: Option<u64>,
+    min_coin_b_amount: Option<u64>
 ): (FungibleAsset, FungibleAsset) acquires CoinCapabilities, Config, Pool {
     let pair_addr = coin_address(&lp_token);
     let pool = borrow_global_mut<Pool>(pair_addr);
     let config = borrow_global_mut<Config>(pair_addr);
-    let total_share = option::extract(
-        &mut fungible_asset::supply(fungible_asset::metadata_from_asset(&lp_token))
-    );
+    let total_share =
+        option::extract(
+            &mut fungible_asset::supply(
+                fungible_asset::metadata_from_asset(&lp_token)
+            )
+        );
     let coin_a_amount = fungible_asset::balance(pool.coin_a_store);
     let given_token_amount = fungible_asset::amount(&lp_token);
     let coin_b_amount = fungible_asset::balance(pool.coin_b_store);
-    let given_share_ratio = decimal128::from_ratio((given_token_amount as u128), total_share);
-    let coin_a_amount_out = decimal128::mul_u64(&given_share_ratio, coin_a_amount);
-    let coin_b_amount_out = decimal128::mul_u64(&given_share_ratio, coin_b_amount);
+    let given_share_ratio =
+        bigdecimal::from_ratio_u128((given_token_amount as u128), total_share);
+    let coin_a_amount_out =
+        bigdecimal::mul_by_u64_truncate(given_share_ratio, coin_a_amount);
+    let coin_b_amount_out =
+        bigdecimal::mul_by_u64_truncate(given_share_ratio, coin_b_amount);
     check_lbp_ended(&config.weights);
 
     assert!(
-        option::is_none(&min_coin_a_amount) || *option::borrow(&min_coin_a_amount) <= coin_a_amount_out,
-        error::invalid_state(EMIN_WITHDRAW),
+        option::is_none(&min_coin_a_amount)
+            || *option::borrow(&min_coin_a_amount) <= coin_a_amount_out,
+        error::invalid_state(EMIN_WITHDRAW)
     );
     assert!(
-        option::is_none(&min_coin_b_amount) || *option::borrow(&min_coin_b_amount) <= coin_b_amount_out,
-        error::invalid_state(EMIN_WITHDRAW),
+        option::is_none(&min_coin_b_amount)
+            || *option::borrow(&min_coin_b_amount) <= coin_b_amount_out,
+        error::invalid_state(EMIN_WITHDRAW)
     );
 
     // burn liquidity token
     let liquidity_token_capabilities = borrow_global<CoinCapabilities>(pair_addr);
-    coin::burn(&liquidity_token_capabilities.burn_cap, lp_token);
+    coin::burn(
+        &liquidity_token_capabilities.burn_cap,
+        lp_token
+    );
 
     // emit events
     let pair_key = generate_pair_key(object::address_to_object<Config>(pair_addr));
@@ -2633,24 +2513,30 @@ CONTRACT: not allow until LBP is ended
             liquidity_token: pair_addr,
             coin_a_amount: coin_a_amount_out,
             coin_b_amount: coin_b_amount_out,
-            liquidity: given_token_amount,
-        },
+            liquidity: given_token_amount
+        }
     );
     let pool = borrow_global_mut<Pool>(pair_addr);
 
     // withdraw and return the coins
     let pair_signer = &object::generate_signer_for_extending(&config.extend_ref);
     (
-        fungible_asset::withdraw(pair_signer, pool.coin_a_store, coin_a_amount_out),
-        fungible_asset::withdraw(pair_signer, pool.coin_b_store, coin_b_amount_out),
+        fungible_asset::withdraw(
+            pair_signer,
+            pool.coin_a_store,
+            coin_a_amount_out
+        ),
+        fungible_asset::withdraw(
+            pair_signer,
+            pool.coin_b_store,
+            coin_b_amount_out
+        )
     )
 }
 
-
- ## Function `single_asset_provide_liquidity` @@ -2665,82 +2551,101 @@ CONTRACT: not allow until LBP is ended -
-Implementation +##### Implementation
public fun single_asset_provide_liquidity(
     pair: Object<Config>,
     provide_coin: FungibleAsset,
-    min_liquidity_amount: Option<u64>,
+    min_liquidity_amount: Option<u64>
 ): FungibleAsset acquires Config, CoinCapabilities, Pool {
-    let pair_addr = object::object_address(pair);
+    let pair_addr = object::object_address(&pair);
     let config = borrow_global<Config>(pair_addr);
     check_lbp_ended(&config.weights);
 
     // provide coin type must be one of coin a or coin b coin type
     let provide_metadata = fungible_asset::metadata_from_asset(&provide_coin);
-    let provide_address = object::object_address(provide_metadata);
+    let provide_address = object::object_address(&provide_metadata);
     let pair_key = generate_pair_key(pair);
     assert!(
         provide_address == pair_key.coin_a || provide_address == pair_key.coin_b,
-        error::invalid_argument(ECOIN_TYPE),
+        error::invalid_argument(ECOIN_TYPE)
     );
     let is_provide_a = provide_address == pair_key.coin_a;
 
     let total_share = option::extract(&mut fungible_asset::supply(pair));
-    assert!(total_share != 0, error::invalid_state(EZERO_LIQUIDITY));
+    assert!(
+        total_share != 0,
+        error::invalid_state(EZERO_LIQUIDITY)
+    );
 
     // load values for fee and increased liquidity amount calculation
     let amount_in = fungible_asset::amount(&provide_coin);
     let (coin_a_weight, coin_b_weight) = get_weight(&config.weights);
     let pool = borrow_global_mut<Pool>(pair_addr);
-    let (normalized_weight, pool_amount_in, provide_coin_addr) = if (is_provide_a) {
-        let normalized_weight = decimal128::from_ratio(
-            decimal128::val(&coin_a_weight),
-            decimal128::val(&coin_a_weight) + decimal128::val(&coin_b_weight)
-        );
-
-        let pool_amount_in = fungible_asset::balance(pool.coin_a_store);
-        fungible_asset::deposit(pool.coin_a_store, provide_coin);
-
-        (normalized_weight, pool_amount_in, pair_key.coin_a)
-    } else {
-        let normalized_weight = decimal128::from_ratio(
-            decimal128::val(&coin_b_weight),
-            decimal128::val(&coin_a_weight) + decimal128::val(&coin_b_weight)
-        );
+    let (normalized_weight, pool_amount_in, provide_coin_addr) =
+        if (is_provide_a) {
+            let normalized_weight =
+                bigdecimal::div(
+                    coin_a_weight,
+                    bigdecimal::add(coin_a_weight, coin_b_weight)
+                );
+            let pool_amount_in = fungible_asset::balance(pool.coin_a_store);
+            fungible_asset::deposit(pool.coin_a_store, provide_coin);
+
+            (normalized_weight, pool_amount_in, pair_key.coin_a)
+        } else {
+            let normalized_weight =
+                bigdecimal::div(
+                    coin_b_weight,
+                    bigdecimal::add(coin_a_weight, coin_b_weight)
+                );
 
-        let pool_amount_in = fungible_asset::balance(pool.coin_b_store);
-        fungible_asset::deposit(pool.coin_b_store, provide_coin);
+            let pool_amount_in = fungible_asset::balance(pool.coin_b_store);
+            fungible_asset::deposit(pool.coin_b_store, provide_coin);
 
-        (normalized_weight, pool_amount_in, pair_key.coin_b)
-    };
+            (normalized_weight, pool_amount_in, pair_key.coin_b)
+        };
 
     // CONTRACT: cannot provide more than the pool amount to prevent huge price impact
-    assert!(pool_amount_in > amount_in, error::invalid_argument(EPRICE_IMPACT));
+    assert!(
+        pool_amount_in > amount_in,
+        error::invalid_argument(EPRICE_IMPACT)
+    );
 
     // compute fee amount with the assumption that we will swap (1 - normalized_weight) of amount_in
-    let adjusted_swap_amount = decimal128::mul_u64(
-        &decimal128::sub(&decimal128::one(), &normalized_weight),
-        amount_in
-    );
-    let fee_amount = decimal128::mul_u64(&config.swap_fee_rate, adjusted_swap_amount);
+    let adjusted_swap_amount =
+        bigdecimal::mul_by_u64_truncate(
+            bigdecimal::sub(
+                bigdecimal::one(),
+                normalized_weight
+            ),
+            amount_in
+        );
+    let fee_amount =
+        calculate_fee_with_minimum(
+            config.swap_fee_rate,
+            adjusted_swap_amount
+        );
 
     // actual amount in after deducting fee amount
     let adjusted_amount_in = amount_in - fee_amount;
 
     // calculate new total share and new liquidity
-    let base = decimal128::from_ratio_u64(adjusted_amount_in + pool_amount_in, pool_amount_in);
-    let pool_ratio = pow(&base, &normalized_weight);
-    let new_total_share = decimal128::mul_u128(&pool_ratio, total_share);
+    let base =
+        bigdecimal::from_ratio_u64(
+            adjusted_amount_in + pool_amount_in,
+            pool_amount_in
+        );
+    let pool_ratio = pow(base, normalized_weight);
+    let new_total_share = bigdecimal::mul_by_u128_truncate(pool_ratio, total_share);
     let liquidity = (new_total_share - total_share as u64);
 
     // check min liquidity assertion
     assert!(
-        option::is_none(&min_liquidity_amount) ||
-            *option::borrow(&min_liquidity_amount) <= liquidity,
-        error::invalid_state(EMIN_LIQUIDITY),
+        option::is_none(&min_liquidity_amount)
+            || *option::borrow(&min_liquidity_amount) <= liquidity,
+        error::invalid_state(EMIN_LIQUIDITY)
     );
 
     // emit events
@@ -2752,20 +2657,21 @@ CONTRACT: not allow until LBP is ended
             liquidity_token: pair_addr,
             provide_amount: amount_in,
             fee_amount,
-            liquidity,
-        },
+            liquidity
+        }
     );
 
     // mint liquidity tokens to provider
     let liquidity_token_capabilities = borrow_global<CoinCapabilities>(pair_addr);
-    coin::mint(&liquidity_token_capabilities.mint_cap, liquidity)
+    coin::mint(
+        &liquidity_token_capabilities.mint_cap,
+        liquidity
+    )
 }
 
-
- ## Function `swap` @@ -2778,51 +2684,67 @@ Swap directly -
-Implementation +##### Implementation
public fun swap(
-    pair: Object<Config>,
-    offer_coin: FungibleAsset,
+    pair: Object<Config>, offer_coin: FungibleAsset
 ): FungibleAsset acquires Config, Pool {
     let offer_amount = fungible_asset::amount(&offer_coin);
     let offer_metadata = fungible_asset::metadata_from_asset(&offer_coin);
-    let offer_address = object::object_address(offer_metadata);
+    let offer_address = object::object_address(&offer_metadata);
     let pair_key = generate_pair_key(pair);
     assert!(
         offer_address == pair_key.coin_a || offer_address == pair_key.coin_b,
-        error::invalid_argument(ECOIN_TYPE),
+        error::invalid_argument(ECOIN_TYPE)
     );
     let is_offer_a = offer_address == pair_key.coin_a;
 
-    let (pool_a, pool_b, weight_a, weight_b, swap_fee_rate) = pool_info(pair ,true);
-    let (offer_coin_addr, return_coin_addr, offer_pool, return_pool, offer_weight, return_weight) = if (is_offer_a) {
-        (pair_key.coin_a, pair_key.coin_b, pool_a, pool_b, weight_a, weight_b)
-    } else {
-        (pair_key.coin_b, pair_key.coin_a, pool_b, pool_a, weight_b, weight_a)
-    };
-    let (return_amount, fee_amount) = swap_simulation(
+    let (pool_a, pool_b, weight_a, weight_b, swap_fee_rate) = pool_info(pair, true);
+    let (
+        offer_coin_addr,
+        return_coin_addr,
         offer_pool,
         return_pool,
         offer_weight,
-        return_weight,
-        fungible_asset::amount(&offer_coin),
-        swap_fee_rate,
-    );
+        return_weight
+    ) =
+        if (is_offer_a) {
+            (pair_key.coin_a, pair_key.coin_b, pool_a, pool_b, weight_a, weight_b)
+        } else {
+            (pair_key.coin_b, pair_key.coin_a, pool_b, pool_a, weight_b, weight_a)
+        };
+    let (return_amount, fee_amount) =
+        swap_simulation(
+            offer_pool,
+            return_pool,
+            offer_weight,
+            return_weight,
+            fungible_asset::amount(&offer_coin),
+            swap_fee_rate
+        );
 
     // apply swap result to pool
-    let pair_addr = object::object_address(pair);
+    let pair_addr = object::object_address(&pair);
     let pool = borrow_global_mut<Pool>(pair_addr);
     let config = borrow_global<Config>(pair_addr);
     let pair_signer = &object::generate_signer_for_extending(&config.extend_ref);
-    let return_coin = if (is_offer_a) {
-        fungible_asset::deposit(pool.coin_a_store, offer_coin);
-        fungible_asset::withdraw(pair_signer, pool.coin_b_store, return_amount)
-    } else {
-        fungible_asset::deposit(pool.coin_b_store, offer_coin);
-        fungible_asset::withdraw(pair_signer, pool.coin_a_store, return_amount)
-    };
+    let return_coin =
+        if (is_offer_a) {
+            fungible_asset::deposit(pool.coin_a_store, offer_coin);
+            fungible_asset::withdraw(
+                pair_signer,
+                pool.coin_b_store,
+                return_amount
+            )
+        } else {
+            fungible_asset::deposit(pool.coin_b_store, offer_coin);
+            fungible_asset::withdraw(
+                pair_signer,
+                pool.coin_a_store,
+                return_amount
+            )
+        };
 
     // emit events
     event::emit<SwapEvent>(
@@ -2832,8 +2754,8 @@ Swap directly
             liquidity_token: pair_addr,
             fee_amount,
             offer_amount,
-            return_amount,
-        },
+            return_amount
+        }
     );
 
     return_coin
@@ -2842,56 +2764,67 @@ Swap directly
 
 
 
-
- ## Function `create_pair` -
public fun create_pair(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: decimal128::Decimal128, coin_a: fungible_asset::FungibleAsset, coin_b: fungible_asset::FungibleAsset, weights: dex::Weights): fungible_asset::FungibleAsset
+
public fun create_pair(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: bigdecimal::BigDecimal, coin_a: fungible_asset::FungibleAsset, coin_b: fungible_asset::FungibleAsset, weights: dex::Weights): fungible_asset::FungibleAsset
 
-
-Implementation +##### Implementation
public fun create_pair(
     creator: &signer,
     name: String,
     symbol: String,
-    swap_fee_rate: Decimal128,
+    swap_fee_rate: BigDecimal,
     coin_a: FungibleAsset,
     coin_b: FungibleAsset,
-    weights: Weights,
+    weights: Weights
 ): FungibleAsset acquires CoinCapabilities, Config, ModuleStore, Pool {
-    let (mint_cap, burn_cap, freeze_cap, extend_ref) = coin::initialize_and_generate_extend_ref (
-        creator,
-        option::none(),
-        name,
-        symbol,
-        6,
-        string::utf8(b""),
-        string::utf8(b""),
-    );
+    let (mint_cap, burn_cap, freeze_cap, extend_ref) =
+        coin::initialize_and_generate_extend_ref(
+            creator,
+            option::none(),
+            name,
+            symbol,
+            6,
+            string::utf8(b""),
+            string::utf8(b"")
+        );
+
+    assert_weights(weights);
 
     assert!(
-        decimal128::val(&swap_fee_rate) <= MAX_FEE_RATE,
+        bigdecimal::le(swap_fee_rate, max_fee_rate()),
         error::invalid_argument(EOUT_OF_SWAP_FEE_RATE_RANGE)
     );
 
-    assert!(coin_address(&coin_a) != coin_address(&coin_b), error::invalid_argument(ESAME_COIN_TYPE));
+    assert!(
+        coin_address(&coin_a) != coin_address(&coin_b),
+        error::invalid_argument(ESAME_COIN_TYPE)
+    );
 
     let pair_signer = &object::generate_signer_for_extending(&extend_ref);
     let pair_address = signer::address_of(pair_signer);
     // transfer pair object's ownership to initia_std
     object::transfer_raw(creator, pair_address, @initia_std);
 
-    let coin_a_store = primary_fungible_store::create_primary_store(pair_address, fungible_asset::asset_metadata(&coin_a));
-    let coin_b_store = primary_fungible_store::create_primary_store(pair_address, fungible_asset::asset_metadata(&coin_b));
+    let coin_a_store =
+        primary_fungible_store::create_primary_store(
+            pair_address,
+            fungible_asset::asset_metadata(&coin_a)
+        );
+    let coin_b_store =
+        primary_fungible_store::create_primary_store(
+            pair_address,
+            fungible_asset::asset_metadata(&coin_b)
+        );
     let coin_a_addr = coin_address(&coin_a);
     let coin_b_addr = coin_address(&coin_b);
 
@@ -2902,7 +2835,7 @@ Swap directly
 
     move_to(
         pair_signer,
-        CoinCapabilities { mint_cap, freeze_cap, burn_cap },
+        CoinCapabilities { mint_cap, freeze_cap, burn_cap }
     );
 
     move_to(
@@ -2912,26 +2845,27 @@ Swap directly
             // temp weights for initial provide
             weights: Weights {
                 weights_before: Weight {
-                    coin_a_weight: decimal128::one(),
-                    coin_b_weight: decimal128::one(),
-                    timestamp: 0,
+                    coin_a_weight: bigdecimal::one(),
+                    coin_b_weight: bigdecimal::one(),
+                    timestamp: 0
                 },
                 weights_after: Weight {
-                    coin_a_weight: decimal128::one(),
-                    coin_b_weight: decimal128::one(),
-                    timestamp: 0,
+                    coin_a_weight: bigdecimal::one(),
+                    coin_b_weight: bigdecimal::one(),
+                    timestamp: 0
                 }
             },
-            swap_fee_rate,
+            swap_fee_rate
         }
     );
 
-    let liquidity_token = provide_liquidity(
-        object::address_to_object<Config>(pair_address),
-        coin_a,
-        coin_b,
-        option::none(),
-    );
+    let liquidity_token =
+        provide_liquidity(
+            object::address_to_object<Config>(pair_address),
+            coin_a,
+            coin_b,
+            option::none()
+        );
 
     // update weights
     let config = borrow_global_mut<Config>(pair_address);
@@ -2944,7 +2878,11 @@ Swap directly
     // let coin_a_type = type_info::type_name<CoinA>();
     // let coin_b_type = type_info::type_name<CoinB>();
     // let liquidity_token_type = type_info::type_name<LiquidityToken>();
-    let pair_key = PairKey { coin_a: coin_a_addr, coin_b: coin_b_addr, liquidity_token: pair_address};
+    let pair_key = PairKey {
+        coin_a: coin_a_addr,
+        coin_b: coin_b_addr,
+        liquidity_token: pair_address
+    };
 
     // add pair to table for queries
     table::add(
@@ -2955,8 +2893,8 @@ Swap directly
             coin_b: coin_b_addr,
             liquidity_token: pair_address,
             weights,
-            swap_fee_rate,
-        },
+            swap_fee_rate
+        }
     );
 
     // emit create pair event
@@ -2966,8 +2904,8 @@ Swap directly
             coin_b: coin_b_addr,
             liquidity_token: pair_address,
             weights,
-            swap_fee_rate,
-        },
+            swap_fee_rate
+        }
     );
 
     liquidity_token
@@ -2976,8 +2914,6 @@ Swap directly
 
 
 
-
- ## Function `provide_liquidity` @@ -2991,17 +2927,16 @@ CONTRACT: not allow until LBP is ended -
-Implementation +##### Implementation
public fun provide_liquidity(
     pair: Object<Config>,
     coin_a: FungibleAsset,
     coin_b: FungibleAsset,
-    min_liquidity_amount: Option<u64>,
+    min_liquidity_amount: Option<u64>
 ): FungibleAsset acquires Config, Pool, CoinCapabilities {
-    let pool_addr = object::object_address(pair);
+    let pool_addr = object::object_address(&pair);
     let config = borrow_global_mut<Config>(pool_addr);
     let pool = borrow_global_mut<Pool>(pool_addr);
     check_lbp_ended(&config.weights);
@@ -3012,25 +2947,33 @@ CONTRACT: not allow until LBP is ended
     let coin_b_amount = fungible_asset::balance(pool.coin_b_store);
 
     let total_share = option::extract(&mut fungible_asset::supply(pair));
-    let liquidity = if (total_share == 0) {
-        if (coin_a_amount_in > coin_b_amount_in) {
-            coin_a_amount_in
-        } else {
-            coin_b_amount_in
-        }
-    } else {
-        let coin_a_share_ratio = decimal128::from_ratio_u64(coin_a_amount_in, coin_a_amount);
-        let coin_b_share_ratio = decimal128::from_ratio_u64(coin_b_amount_in, coin_b_amount);
-        if (decimal128::val(&coin_a_share_ratio) > decimal128::val(&coin_b_share_ratio)) {
-            (decimal128::mul_u128(&coin_b_share_ratio, total_share) as u64)
+    let liquidity =
+        if (total_share == 0) {
+            if (coin_a_amount_in > coin_b_amount_in) {
+                coin_a_amount_in
+            } else {
+                coin_b_amount_in
+            }
         } else {
-            (decimal128::mul_u128(&coin_a_share_ratio, total_share) as u64)
-        }
-    };
+            let coin_a_share_ratio =
+                bigdecimal::from_ratio_u64(coin_a_amount_in, coin_a_amount);
+            let coin_b_share_ratio =
+                bigdecimal::from_ratio_u64(coin_b_amount_in, coin_b_amount);
+            if (bigdecimal::gt(coin_a_share_ratio, coin_b_share_ratio)) {
+                (
+                    bigdecimal::mul_by_u128_truncate(coin_b_share_ratio, total_share) as u64
+                )
+            } else {
+                (
+                    bigdecimal::mul_by_u128_truncate(coin_a_share_ratio, total_share) as u64
+                )
+            }
+        };
 
     assert!(
-        option::is_none(&min_liquidity_amount) || *option::borrow(&min_liquidity_amount) <= liquidity,
-        error::invalid_state(EMIN_LIQUIDITY),
+        option::is_none(&min_liquidity_amount)
+            || *option::borrow(&min_liquidity_amount) <= liquidity,
+        error::invalid_state(EMIN_LIQUIDITY)
     );
 
     event::emit<ProvideEvent>(
@@ -3040,156 +2983,23 @@ CONTRACT: not allow until LBP is ended
             liquidity_token: pool_addr,
             coin_a_amount: coin_a_amount_in,
             coin_b_amount: coin_b_amount_in,
-            liquidity,
-        },
+            liquidity
+        }
     );
 
     fungible_asset::deposit(pool.coin_a_store, coin_a);
     fungible_asset::deposit(pool.coin_b_store, coin_b);
 
     let liquidity_token_capabilities = borrow_global<CoinCapabilities>(pool_addr);
-    coin::mint(&liquidity_token_capabilities.mint_cap, liquidity)
-}
-
- - - -
- - - -## Function `coin_address` - - - -
fun coin_address(fa: &fungible_asset::FungibleAsset): address
-
- - - -
-Implementation - - -
fun coin_address(fa: &FungibleAsset): address {
-    let metadata = fungible_asset::asset_metadata(fa);
-    object::object_address(metadata)
-}
-
- - - -
- - - -## Function `check_lbp_ended` - - - -
fun check_lbp_ended(weights: &dex::Weights)
-
- - - -
-Implementation - - -
fun check_lbp_ended(weights: &Weights) {
-    let (_, timestamp) = get_block_info();
-
-    assert!(timestamp >= weights.weights_after.timestamp, error::invalid_state(ELBP_NOT_ENDED))
-}
-
- - - -
- - - -## Function `generate_pair_key` - - - -
fun generate_pair_key<T: key>(pair: object::Object<T>): dex::PairKey
-
- - - -
-Implementation - - -
fun generate_pair_key<T: key>(pair: Object<T>): PairKey acquires Pool {
-    let addr = object::object_address(pair);
-    let pool = borrow_global<Pool>(addr);
-    let coin_a_metadata = fungible_asset::store_metadata(pool.coin_a_store);
-    let coin_b_metadata = fungible_asset::store_metadata(pool.coin_b_store);
-    PairKey {
-        coin_a: object::object_address(coin_a_metadata),
-        coin_b: object::object_address(coin_b_metadata),
-        liquidity_token: addr
-    }
-}
-
- - - -
- - - -## Function `get_weight` - -return (coin_a_weight, coin_b_weight) - - -
fun get_weight(weights: &dex::Weights): (decimal128::Decimal128, decimal128::Decimal128)
-
- - - -
-Implementation - - -
fun get_weight(weights: &Weights): (Decimal128, Decimal128) {
-    let (_, timestamp) = get_block_info();
-    if (timestamp <= weights.weights_before.timestamp) {
-        (weights.weights_before.coin_a_weight, weights.weights_before.coin_b_weight)
-    } else if (timestamp < weights.weights_after.timestamp) {
-        let interval = (weights.weights_after.timestamp - weights.weights_before.timestamp as u128);
-        let time_diff_after = (weights.weights_after.timestamp - timestamp as u128);
-        let time_diff_before = (timestamp - weights.weights_before.timestamp as u128);
-
-        // when timestamp_before < timestamp < timestamp_after
-        // weight = a * timestamp + b
-        // m = (a * timestamp_before + b) * (timestamp_after - timestamp)
-        //   = a * t_b * t_a - a * t_b * t + b * t_a - b * t
-        // n = (a * timestamp_after + b) * (timestamp - timestamp_before)
-        //   = a * t_a * t - a * t_a * t_b + b * t - b * t_b
-        // l = m + n = a * t * (t_a - t_b) + b * (t_a - t_b)
-        // weight = l / (t_a - t_b)
-        let coin_a_m = decimal128::new(decimal128::val(&weights.weights_after.coin_a_weight) * time_diff_before);
-        let coin_a_n = decimal128::new(decimal128::val(&weights.weights_before.coin_a_weight) * time_diff_after);
-        let coin_a_l = decimal128::add(&coin_a_m, &coin_a_n);
-
-        let coin_b_m = decimal128::new(decimal128::val(&weights.weights_after.coin_b_weight) * time_diff_before);
-        let coin_b_n = decimal128::new(decimal128::val(&weights.weights_before.coin_b_weight) * time_diff_after);
-        let coin_b_l = decimal128::add(&coin_b_m, &coin_b_n);
-        (decimal128::div(&coin_a_l, interval), decimal128::div(&coin_b_l, interval))
-    } else {
-        (weights.weights_after.coin_a_weight, weights.weights_after.coin_b_weight)
-    }
+    coin::mint(
+        &liquidity_token_capabilities.mint_cap,
+        liquidity
+    )
 }
 
-
- ## Function `pool_info` @@ -3197,22 +3007,26 @@ return (coin_a_weight, coin_b_weight) get all pool info at once (a_amount, b_amount, a_weight, b_weight, fee_rate) -
public fun pool_info(pair: object::Object<dex::Config>, lbp_assertion: bool): (u64, u64, decimal128::Decimal128, decimal128::Decimal128, decimal128::Decimal128)
+
public fun pool_info(pair: object::Object<dex::Config>, lbp_assertion: bool): (u64, u64, bigdecimal::BigDecimal, bigdecimal::BigDecimal, bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation -
public fun pool_info(pair: Object<Config>, lbp_assertion: bool): (u64, u64, Decimal128, Decimal128, Decimal128) acquires Config, Pool {
-    let pair_addr = object::object_address(pair);
+
public fun pool_info(
+    pair: Object<Config>, lbp_assertion: bool
+): (u64, u64, BigDecimal, BigDecimal, BigDecimal) acquires Config, Pool {
+    let pair_addr = object::object_address(&pair);
     let config = borrow_global<Config>(pair_addr);
     if (lbp_assertion) {
         // assert LBP start time
-        let (_, timestamp) = get_block_info();
-        assert!(timestamp >= config.weights.weights_before.timestamp, error::invalid_state(ELBP_NOT_STARTED));
+        let (_, timestamp) = get_block_info();
+        assert!(
+            timestamp >= config.weights.weights_before.timestamp,
+            error::invalid_state(ELBP_NOT_STARTED)
+        );
     };
 
     let pool = borrow_global<Pool>(pair_addr);
@@ -3223,15 +3037,13 @@ get all pool info at once (a_amount, b_amount, a_weight, b_weight, fee_rate)
         fungible_asset::balance(pool.coin_b_store),
         coin_a_weight,
         coin_b_weight,
-        config.swap_fee_rate,
+        config.swap_fee_rate
     )
 }
 
-
- ## Function `swap_simulation` @@ -3241,69 +3053,84 @@ https://balancer.fi/whitepaper.pdf (15) return (return_amount, fee_amount) -
public fun swap_simulation(pool_amount_in: u64, pool_amount_out: u64, weight_in: decimal128::Decimal128, weight_out: decimal128::Decimal128, amount_in: u64, swap_fee_rate: decimal128::Decimal128): (u64, u64)
+
public fun swap_simulation(pool_amount_in: u64, pool_amount_out: u64, weight_in: bigdecimal::BigDecimal, weight_out: bigdecimal::BigDecimal, amount_in: u64, swap_fee_rate: bigdecimal::BigDecimal): (u64, u64)
 
-
-Implementation +##### Implementation
public fun swap_simulation(
     pool_amount_in: u64,
     pool_amount_out: u64,
-    weight_in: Decimal128,
-    weight_out: Decimal128,
+    weight_in: BigDecimal,
+    weight_out: BigDecimal,
     amount_in: u64,
-    swap_fee_rate: Decimal128,
+    swap_fee_rate: BigDecimal
 ): (u64, u64) {
-    let one = decimal128::one();
-    let exp = decimal128::from_ratio(decimal128::val(&weight_in), decimal128::val(&weight_out));
-    let fee_amount = decimal128::mul_u64(&swap_fee_rate, amount_in);
+    assert!(
+        amount_in > 0,
+        error::invalid_argument(EZERO_AMOUNT_IN)
+    );
+
+    let one = bigdecimal::one();
+    let exp = bigdecimal::div(weight_in, weight_out);
+
+    let fee_amount = calculate_fee_with_minimum(swap_fee_rate, amount_in);
     let adjusted_amount_in = amount_in - fee_amount;
-    let base = decimal128::from_ratio_u64(pool_amount_in, pool_amount_in + adjusted_amount_in);
-    let sub_amount = pow(&base, &exp);
-    (decimal128::mul_u64(&decimal128::sub(&one, &sub_amount), pool_amount_out), fee_amount)
+    let base =
+        bigdecimal::from_ratio_u64(
+            pool_amount_in,
+            pool_amount_in + adjusted_amount_in
+        );
+    let sub_amount = pow(base, exp);
+    (
+        bigdecimal::mul_by_u64_truncate(
+            bigdecimal::sub(one, sub_amount),
+            pool_amount_out
+        ),
+        fee_amount
+    )
 }
 
-
- ## Function `swap_simulation_given_out` -
public fun swap_simulation_given_out(pool_amount_in: u64, pool_amount_out: u64, weight_in: decimal128::Decimal128, weight_out: decimal128::Decimal128, amount_out: u64, swap_fee_rate: decimal128::Decimal128): (u64, u64)
+
public fun swap_simulation_given_out(pool_amount_in: u64, pool_amount_out: u64, weight_in: bigdecimal::BigDecimal, weight_out: bigdecimal::BigDecimal, amount_out: u64, swap_fee_rate: bigdecimal::BigDecimal): (u64, u64)
 
-
-Implementation +##### Implementation
public fun swap_simulation_given_out(
     pool_amount_in: u64,
     pool_amount_out: u64,
-    weight_in: Decimal128,
-    weight_out: Decimal128,
+    weight_in: BigDecimal,
+    weight_out: BigDecimal,
     amount_out: u64,
-    swap_fee_rate: Decimal128,
+    swap_fee_rate: BigDecimal
 ): (u64, u64) {
-    let one = decimal128::one();
-    let exp = decimal128::from_ratio(decimal128::val(&weight_out), decimal128::val(&weight_in));
-    let base = decimal128::from_ratio_u64(pool_amount_out, pool_amount_out - amount_out);
-    let base_exp = pow(&base, &exp);
-    let adjusted_amount_in = decimal128::val(&decimal128::sub(&base_exp, &one)) * (pool_amount_in as u128) ;
-    let sub_one_fee = decimal128::sub(&one, &swap_fee_rate);
-
-    let amount_in = ( adjusted_amount_in / decimal128::val(&sub_one_fee) as u64);
-    let fee_amount = decimal128::mul_u64(&swap_fee_rate, amount_in);
+    let one = bigdecimal::one();
+    let exp = bigdecimal::div(weight_out, weight_in);
+    let base = bigdecimal::from_ratio_u64(
+        pool_amount_out, pool_amount_out - amount_out
+    );
+    let base_exp = pow(base, exp);
+    let adjusted_amount_in =
+        bigdecimal::mul_by_u64(bigdecimal::sub(base_exp, one), pool_amount_in);
+    let sub_one_fee = bigdecimal::sub(one, swap_fee_rate);
+    let amount_in =
+        bigdecimal::truncate_u64(bigdecimal::div(adjusted_amount_in, sub_one_fee));
+    let fee_amount = calculate_fee_with_minimum(swap_fee_rate, amount_in);
 
     (amount_in, fee_amount)
 }
@@ -3311,8 +3138,6 @@ return (return_amount, fee_amount)
 
 
 
-
- ## Function `pool_metadata` @@ -3324,153 +3149,17 @@ return (return_amount, fee_amount) -
-Implementation +##### Implementation -
public fun pool_metadata(pair: Object<Config>): (Object<Metadata>, Object<Metadata>) acquires Pool {
-    let pair_addr = object::object_address(pair);
+
public fun pool_metadata(
+    pair: Object<Config>
+): (Object<Metadata>, Object<Metadata>) acquires Pool {
+    let pair_addr = object::object_address(&pair);
     let pool = borrow_global<Pool>(pair_addr);
-    (fungible_asset::store_metadata(pool.coin_a_store), fungible_asset::store_metadata(pool.coin_b_store))
-}
-
- - - -
- - - -## Function `pow` - -a^x = 1 + sigma[(k^n)/n!] -k = x * ln(a) - - -
fun pow(base: &decimal128::Decimal128, exp: &decimal128::Decimal128): decimal128::Decimal128
-
- - - -
-Implementation - - -
fun pow(base: &Decimal128, exp: &Decimal128): Decimal128 {
-    assert!(
-        decimal128::val(base) != 0 && decimal128::val(base) < 2000000000000000000,
-        error::invalid_argument(EOUT_OF_BASE_RANGE),
-    );
-
-    let res = decimal128::one();
-    let (ln_a, neg) = ln(base);
-    let k = mul_decimal128s(&ln_a, exp);
-    let comp = k;
-    let index = 1;
-    let subs: vector<Decimal128> = vector[];
-    while (decimal128::val(&comp) > PRECISION) {
-        if (index & 1 == 1 && neg) {
-            vector::push_back(&mut subs, comp)
-        } else {
-            res = decimal128::add(&res, &comp)
-        };
-
-        comp = decimal128::div(&mul_decimal128s(&comp, &k), index + 1);
-        index = index + 1;
-    };
-
-    let index = 0;
-    while (index < vector::length(&subs)) {
-        let comp = vector::borrow(&subs, index);
-        res = decimal128::sub(&res, comp);
-        index = index + 1;
-    };
-
-    res
-}
-
- - - -
- - - -## Function `ln` - -ln(1 + a) = sigma[(-1) ^ (n + 1) * (a ^ n / n)] -https://en.wikipedia.org/wiki/Taylor_series#Natural_logarithm - - -
fun ln(num: &decimal128::Decimal128): (decimal128::Decimal128, bool)
-
- - - -
-Implementation - - -
fun ln(num: &Decimal128): (Decimal128, bool) {
-    let one = decimal128::val(&decimal128::one());
-    let num_val = decimal128::val(num);
-    let (a, a_neg) = if (num_val >= one) {
-        (decimal128::sub(num, &decimal128::one()), false)
-    } else {
-        (decimal128::sub(&decimal128::one(), num), true)
-    };
-
-    let res = decimal128::zero();
-    let comp = a;
-    let index = 1;
-
-    while (decimal128::val(&comp) > PRECISION) {
-        if (index & 1 == 0 && !a_neg) {
-            res = decimal128::sub(&res, &comp);
-        } else {
-            res = decimal128::add(&res, &comp);
-        };
-
-        // comp(old) = a ^ n / n
-        // comp(new) = comp(old) * a * n / (n + 1) = a ^ (n + 1) / (n + 1)
-        comp = decimal128::div(
-            &decimal128::new(decimal128::val(&mul_decimal128s(&comp, &a)) * index), // comp * a * index
-            index + 1,
-        );
-
-        index = index + 1;
-    };
-
-    (res, a_neg)
-}
-
- - - -
- - - -## Function `mul_decimal128s` - - - -
fun mul_decimal128s(decimal128_0: &decimal128::Decimal128, decimal128_1: &decimal128::Decimal128): decimal128::Decimal128
-
- - - -
-Implementation - - -
fun mul_decimal128s(decimal128_0: &Decimal128, decimal128_1: &Decimal128): Decimal128 {
-    let one = (decimal128::val(&decimal128::one()) as u256);
-    let val_mul = (decimal128::val(decimal128_0) as u256) * (decimal128::val(decimal128_1) as u256);
-    decimal128::new((val_mul / one as u128))
+    (
+        fungible_asset::store_metadata(pool.coin_a_store),
+        fungible_asset::store_metadata(pool.coin_b_store)
+    )
 }
 
- - - -
diff --git a/initia_stdlib/doc/dispatchable_fungible_asset.md b/initia_stdlib/doc/dispatchable_fungible_asset.md new file mode 100644 index 0000000..d5d9ac2 --- /dev/null +++ b/initia_stdlib/doc/dispatchable_fungible_asset.md @@ -0,0 +1,382 @@ + + + +# Module `0x1::dispatchable_fungible_asset` + +This defines the fungible asset module that can issue fungible asset of any Metadata object. The +metadata object can be any object that equipped with Metadata resource. + +The dispatchable_fungible_asset wraps the existing fungible_asset module and adds the ability for token issuer +to customize the logic for withdraw and deposit operations. For example: + +- Deflation token: a fixed percentage of token will be destructed upon transfer. +- Transfer allowlist: token can only be transfered to addresses in the allow list. +- Predicated transfer: transfer can only happen when some certain predicate has been met. +- Loyalty token: a fixed loyalty will be paid to a designated address when a fungible asset transfer happens + +The api listed here intended to be an in-place replacement for defi applications that uses fungible_asset api directly +and is safe for non-dispatchable (aka vanilla) fungible assets as well. + +See AIP-73 for further discussion + + +- [Resource `TransferRefStore`](#0x1_dispatchable_fungible_asset_TransferRefStore) +- [Constants](#@Constants_0) +- [Function `register_dispatch_functions`](#0x1_dispatchable_fungible_asset_register_dispatch_functions) +- [Function `register_derive_supply_dispatch_function`](#0x1_dispatchable_fungible_asset_register_derive_supply_dispatch_function) +- [Function `withdraw`](#0x1_dispatchable_fungible_asset_withdraw) +- [Function `deposit`](#0x1_dispatchable_fungible_asset_deposit) +- [Function `transfer`](#0x1_dispatchable_fungible_asset_transfer) +- [Function `transfer_assert_minimum_deposit`](#0x1_dispatchable_fungible_asset_transfer_assert_minimum_deposit) +- [Function `derived_balance`](#0x1_dispatchable_fungible_asset_derived_balance) +- [Function `derived_supply`](#0x1_dispatchable_fungible_asset_derived_supply) + + +
use 0x1::error;
+use 0x1::function_info;
+use 0x1::fungible_asset;
+use 0x1::object;
+use 0x1::option;
+
+ + + + + +## Resource `TransferRefStore` + + + +
struct TransferRefStore has key
+
+ + + +##### Fields + + +
+
+transfer_ref: fungible_asset::TransferRef +
+
+ +
+
+ + + + +## Constants + + + + +Feature is not activated yet on the network. + + +
const ENOT_ACTIVATED: u64 = 3;
+
+ + + + + +Recipient is not getting the guaranteed value; + + +
const EAMOUNT_MISMATCH: u64 = 2;
+
+ + + + + +Dispatch target is not loaded. + + +
const ENOT_LOADED: u64 = 4;
+
+ + + + + +TransferRefStore doesn't exist on the fungible asset type. + + +
const ESTORE_NOT_FOUND: u64 = 1;
+
+ + + + + +## Function `register_dispatch_functions` + + + +
public fun register_dispatch_functions(constructor_ref: &object::ConstructorRef, withdraw_function: option::Option<function_info::FunctionInfo>, deposit_function: option::Option<function_info::FunctionInfo>, derived_balance_function: option::Option<function_info::FunctionInfo>)
+
+ + + +##### Implementation + + +
public fun register_dispatch_functions(
+    constructor_ref: &ConstructorRef,
+    withdraw_function: Option<FunctionInfo>,
+    deposit_function: Option<FunctionInfo>,
+    derived_balance_function: Option<FunctionInfo>
+) {
+    fungible_asset::register_dispatch_functions(
+        constructor_ref,
+        withdraw_function,
+        deposit_function,
+        derived_balance_function
+    );
+    let store_obj = &object::generate_signer(constructor_ref);
+    move_to<TransferRefStore>(
+        store_obj,
+        TransferRefStore {
+            transfer_ref: fungible_asset::generate_transfer_ref(constructor_ref)
+        }
+    );
+}
+
+ + + + + +## Function `register_derive_supply_dispatch_function` + + + +
public fun register_derive_supply_dispatch_function(constructor_ref: &object::ConstructorRef, dispatch_function: option::Option<function_info::FunctionInfo>)
+
+ + + +##### Implementation + + +
public fun register_derive_supply_dispatch_function(
+    constructor_ref: &ConstructorRef, dispatch_function: Option<FunctionInfo>
+) {
+    fungible_asset::register_derive_supply_dispatch_function(
+        constructor_ref, dispatch_function
+    );
+}
+
+ + + + + +## Function `withdraw` + +Withdraw amount of the fungible asset from store by the owner. + +The semantics of deposit will be governed by the function specified in DispatchFunctionStore. + + +
public fun withdraw<T: key>(owner: &signer, store: object::Object<T>, amount: u64): fungible_asset::FungibleAsset
+
+ + + +##### Implementation + + +
public fun withdraw<T: key>(
+    owner: &signer, store: Object<T>, amount: u64
+): FungibleAsset acquires TransferRefStore {
+    fungible_asset::withdraw_sanity_check(owner, store, false);
+    let func_opt = fungible_asset::withdraw_dispatch_function(store);
+    if (option::is_some(&func_opt)) {
+        let start_balance = fungible_asset::balance(store);
+        let func = option::borrow(&func_opt);
+        function_info::load_module_from_function(func);
+        let fa = dispatchable_withdraw(
+            store,
+            amount,
+            borrow_transfer_ref(store),
+            func
+        );
+        let end_balance = fungible_asset::balance(store);
+        assert!(
+            amount <= start_balance - end_balance,
+            error::aborted(EAMOUNT_MISMATCH)
+        );
+        fa
+    } else {
+        fungible_asset::withdraw_internal(object::object_address(&store), amount)
+    }
+}
+
+ + + + + +## Function `deposit` + +Deposit amount of the fungible asset to store. + +The semantics of deposit will be governed by the function specified in DispatchFunctionStore. + + +
public fun deposit<T: key>(store: object::Object<T>, fa: fungible_asset::FungibleAsset)
+
+ + + +##### Implementation + + +
public fun deposit<T: key>(store: Object<T>, fa: FungibleAsset) acquires TransferRefStore {
+    fungible_asset::deposit_sanity_check(store, false);
+    let func_opt = fungible_asset::deposit_dispatch_function(store);
+    if (option::is_some(&func_opt)) {
+        let func = option::borrow(&func_opt);
+        function_info::load_module_from_function(func);
+        dispatchable_deposit(
+            store,
+            fa,
+            borrow_transfer_ref(store),
+            func
+        )
+    } else {
+        fungible_asset::deposit_internal(object::object_address(&store), fa)
+    }
+}
+
+ + + + + +## Function `transfer` + +Transfer an amount of fungible asset from from_store, which should be owned by sender, to receiver. +Note: it does not move the underlying object. + + +
public entry fun transfer<T: key>(sender: &signer, from: object::Object<T>, to: object::Object<T>, amount: u64)
+
+ + + +##### Implementation + + +
public entry fun transfer<T: key>(
+    sender: &signer,
+    from: Object<T>,
+    to: Object<T>,
+    amount: u64
+) acquires TransferRefStore {
+    let fa = withdraw(sender, from, amount);
+    deposit(to, fa);
+}
+
+ + + + + +## Function `transfer_assert_minimum_deposit` + +Transfer an amount of fungible asset from from_store, which should be owned by sender, to receiver. +The recipient is guranteed to receive asset greater than the expected amount. +Note: it does not move the underlying object. + + +
public entry fun transfer_assert_minimum_deposit<T: key>(sender: &signer, from: object::Object<T>, to: object::Object<T>, amount: u64, expected: u64)
+
+ + + +##### Implementation + + +
public entry fun transfer_assert_minimum_deposit<T: key>(
+    sender: &signer,
+    from: Object<T>,
+    to: Object<T>,
+    amount: u64,
+    expected: u64
+) acquires TransferRefStore {
+    let start = fungible_asset::balance(to);
+    let fa = withdraw(sender, from, amount);
+    deposit(to, fa);
+    let end = fungible_asset::balance(to);
+    assert!(end - start >= expected, error::aborted(EAMOUNT_MISMATCH));
+}
+
+ + + + + +## Function `derived_balance` + +Get the derived value of store using the overloaded hook. + +The semantics of value will be governed by the function specified in DispatchFunctionStore. + + +
#[view]
+public fun derived_balance<T: key>(store: object::Object<T>): u64
+
+ + + +##### Implementation + + +
public fun derived_balance<T: key>(store: Object<T>): u64 {
+    let func_opt = fungible_asset::derived_balance_dispatch_function(store);
+    if (option::is_some(&func_opt)) {
+        let func = option::borrow(&func_opt);
+        function_info::load_module_from_function(func);
+        dispatchable_derived_balance(store, func)
+    } else {
+        fungible_asset::balance(store)
+    }
+}
+
+ + + + + +## Function `derived_supply` + +Get the derived supply of the fungible asset using the overloaded hook. + +The semantics of supply will be governed by the function specified in DeriveSupplyDispatch. + + +
#[view]
+public fun derived_supply<T: key>(metadata: object::Object<T>): option::Option<u128>
+
+ + + +##### Implementation + + +
public fun derived_supply<T: key>(metadata: Object<T>): Option<u128> {
+    let func_opt = fungible_asset::derived_supply_dispatch_function(metadata);
+    if (option::is_some(&func_opt)) {
+        let func = option::borrow(&func_opt);
+        function_info::load_module_from_function(func);
+        dispatchable_derived_supply(metadata, func)
+    } else {
+        fungible_asset::supply(metadata)
+    }
+}
+
diff --git a/initia_stdlib/doc/ed25519.md b/initia_stdlib/doc/ed25519.md index 4f8891a..21787aa 100644 --- a/initia_stdlib/doc/ed25519.md +++ b/initia_stdlib/doc/ed25519.md @@ -17,8 +17,6 @@ Contains functions for: - [Function `signature_to_bytes`](#0x1_ed25519_signature_to_bytes) - [Function `verify`](#0x1_ed25519_verify) - [Function `batch_verify`](#0x1_ed25519_batch_verify) -- [Function `verify_internal`](#0x1_ed25519_verify_internal) -- [Function `batch_verify_internal`](#0x1_ed25519_batch_verify_internal)
use 0x1::error;
@@ -38,8 +36,7 @@ A Ed25519 public key
 
 
 
-
-Fields +##### Fields
@@ -52,8 +49,6 @@ A Ed25519 public key
-
- ## Struct `Signature` @@ -66,8 +61,7 @@ A Ed25519 signature that can be verified via verify_internal or -Fields +##### Fields
@@ -80,13 +74,21 @@ A Ed25519 signature that can be verified via verify_internal or - - ## Constants + + +The number of messages, public keys, and signatures do not match. + + +
const E_UNMATCHED_ARGS_LENGTH: u64 = 3;
+
+ + + Wrong number of bytes were given as input when deserializing an Ed25519 public key. @@ -139,14 +141,13 @@ Contructs an PublicKey struct, given 32-byte representation. -
-Implementation +##### Implementation
public fun public_key_from_bytes(bytes: vector<u8>): PublicKey {
     assert!(
         std::vector::length(&bytes) == PUBLIC_KEY_SIZE,
-        std::error::invalid_argument(PUBLIC_KEY_SIZE),
+        std::error::invalid_argument(PUBLIC_KEY_SIZE)
     );
     PublicKey { bytes }
 }
@@ -154,8 +155,6 @@ Contructs an PublicKey struct, given 32-byte representation.
 
 
 
-
- ## Function `signature_from_bytes` @@ -168,20 +167,20 @@ Constructs an Signature struct from the given 64 bytes. -
-Implementation +##### Implementation
public fun signature_from_bytes(bytes: vector<u8>): Signature {
-    assert!(std::vector::length(&bytes) == SIGNATURE_SIZE, std::error::invalid_argument(E_WRONG_SIGNATURE_SIZE));
+    assert!(
+        std::vector::length(&bytes) == SIGNATURE_SIZE,
+        std::error::invalid_argument(E_WRONG_SIGNATURE_SIZE)
+    );
     Signature { bytes }
 }
 
-
- ## Function `public_key_to_bytes` @@ -194,8 +193,7 @@ Serializes an PublicKey struct to bytes. -
-Implementation +##### Implementation
public fun public_key_to_bytes(pk: &PublicKey): vector<u8> {
@@ -205,8 +203,6 @@ Serializes an PublicKey struct to bytes.
 
 
 
-
- ## Function `signature_to_bytes` @@ -219,8 +215,7 @@ Serializes an Signature struct to bytes. -
-Implementation +##### Implementation
public fun signature_to_bytes(sig: &Signature): vector<u8> {
@@ -230,8 +225,6 @@ Serializes an Signature struct to bytes.
 
 
 
-
- ## Function `verify` @@ -244,23 +237,22 @@ Verifies a Ed25519 signature under an public_key on th -
-Implementation +##### Implementation
public fun verify(
-    message: vector<u8>,
-    public_key: &PublicKey,
-    signature: &Signature,
+    message: vector<u8>, public_key: &PublicKey, signature: &Signature
 ): bool {
-    verify_internal(message, public_key.bytes, signature.bytes)
+    verify_internal(
+        message,
+        public_key.bytes,
+        signature.bytes
+    )
 }
 
-
- ## Function `batch_verify` @@ -288,67 +280,39 @@ case. -
-Implementation +##### Implementation
public fun batch_verify(
     messages: vector<vector<u8>>,
     public_keys: vector<PublicKey>,
-    signatures: vector<Signature>,
+    signatures: vector<Signature>
 ): bool {
+    let message_length = std::vector::length(&messages);
+    let public_key_length = std::vector::length(&public_keys);
+    let signature_length = std::vector::length(&signatures);
+
+    if (message_length == 1) {
+        assert!(
+            public_key_length == signature_length,
+            std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH)
+        );
+        if (public_key_length == 0) return true;
+    } else if (public_key_length == 1) {
+        assert!(
+            message_length == signature_length,
+            std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH)
+        );
+        if (message_length == 0) return true;
+    } else {
+        assert!(
+            message_length == public_key_length
+                && public_key_length == signature_length,
+            std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH)
+        );
+        if (message_length == 0) return true;
+    };
+
     batch_verify_internal(messages, public_keys, signatures)
 }
 
- - - -
- - - -## Function `verify_internal` - - - -
fun verify_internal(message: vector<u8>, public_key: vector<u8>, signature: vector<u8>): bool
-
- - - -
-Implementation - - -
native fun verify_internal(message: vector<u8>, public_key: vector<u8>, signature: vector<u8>): bool;
-
- - - -
- - - -## Function `batch_verify_internal` - - - -
fun batch_verify_internal(messages: vector<vector<u8>>, public_keys: vector<ed25519::PublicKey>, signatures: vector<ed25519::Signature>): bool
-
- - - -
-Implementation - - -
native fun batch_verify_internal(
-    messages: vector<vector<u8>>,
-    public_keys: vector<PublicKey>,
-    signatures: vector<Signature>
-): bool;
-
- - - -
diff --git a/initia_stdlib/doc/event.md b/initia_stdlib/doc/event.md index b46a429..caafc44 100644 --- a/initia_stdlib/doc/event.md +++ b/initia_stdlib/doc/event.md @@ -6,7 +6,6 @@ - [Function `emit`](#0x1_event_emit) -- [Function `write_module_event_to_store`](#0x1_event_write_module_event_to_store)
@@ -20,43 +19,15 @@ Emit an event with payload msg by using handle_ref's key and counter. -
public fun emit<T: drop, store>(msg: T)
+
public fun emit<T: drop>(msg: T)
 
-
-Implementation +##### Implementation -
public fun emit<T: store + drop>(msg: T) {
-    write_module_event_to_store<T>(msg);
+
public fun emit<T: drop>(msg: T) {
+    emit_event<T>(&msg);
 }
 
- - - -
- - - -## Function `write_module_event_to_store` - -Log msg with the event stream identified by T - - -
fun write_module_event_to_store<T: drop, store>(msg: T)
-
- - - -
-Implementation - - -
native fun write_module_event_to_store<T: drop + store>(msg: T);
-
- - - -
diff --git a/initia_stdlib/doc/fixed_point64.md b/initia_stdlib/doc/fixed_point64.md index b355b2e..9da9a36 100644 --- a/initia_stdlib/doc/fixed_point64.md +++ b/initia_stdlib/doc/fixed_point64.md @@ -9,19 +9,39 @@ a 64-bit fractional part. - [Struct `FixedPoint64`](#0x1_fixed_point64_FixedPoint64) - [Constants](#@Constants_0) +- [Function `one`](#0x1_fixed_point64_one) +- [Function `zero`](#0x1_fixed_point64_zero) +- [Function `rev`](#0x1_fixed_point64_rev) +- [Function `sub`](#0x1_fixed_point64_sub) +- [Function `sub_u64`](#0x1_fixed_point64_sub_u64) +- [Function `sub_u128`](#0x1_fixed_point64_sub_u128) +- [Function `add`](#0x1_fixed_point64_add) +- [Function `add_u64`](#0x1_fixed_point64_add_u64) +- [Function `add_u128`](#0x1_fixed_point64_add_u128) +- [Function `multiply`](#0x1_fixed_point64_multiply) +- [Function `multiply_u64`](#0x1_fixed_point64_multiply_u64) - [Function `multiply_u128`](#0x1_fixed_point64_multiply_u128) +- [Function `divide`](#0x1_fixed_point64_divide) +- [Function `divide_u64`](#0x1_fixed_point64_divide_u64) +- [Function `divide_by_u64`](#0x1_fixed_point64_divide_by_u64) - [Function `divide_u128`](#0x1_fixed_point64_divide_u128) +- [Function `divide_by_u128`](#0x1_fixed_point64_divide_by_u128) - [Function `create_from_rational`](#0x1_fixed_point64_create_from_rational) - [Function `create_from_raw_value`](#0x1_fixed_point64_create_from_raw_value) - [Function `get_raw_value`](#0x1_fixed_point64_get_raw_value) - [Function `is_zero`](#0x1_fixed_point64_is_zero) - [Function `min`](#0x1_fixed_point64_min) - [Function `max`](#0x1_fixed_point64_max) +- [Function `less_or_equal`](#0x1_fixed_point64_less_or_equal) +- [Function `less`](#0x1_fixed_point64_less) +- [Function `greater_or_equal`](#0x1_fixed_point64_greater_or_equal) +- [Function `greater`](#0x1_fixed_point64_greater) +- [Function `equal`](#0x1_fixed_point64_equal) +- [Function `almost_equal`](#0x1_fixed_point64_almost_equal) - [Function `create_from_u128`](#0x1_fixed_point64_create_from_u128) - [Function `floor`](#0x1_fixed_point64_floor) - [Function `ceil`](#0x1_fixed_point64_ceil) - [Function `round`](#0x1_fixed_point64_round) -- [Module Specification](#@Module_Specification_1)
@@ -48,8 +68,7 @@ decimal. -
-Fields +##### Fields
@@ -62,13 +81,20 @@ decimal.
-
- ## Constants + + + + +
const MAX_U64: u128 = 18446744073709551615;
+
+ + + @@ -78,6 +104,16 @@ decimal. + + +A division by zero was encountered + + +
const EDIVISION_BY_ZERO: u64 = 65540;
+
+ + + The denominator provided was zero @@ -98,22 +134,22 @@ The quotient value would be too large to be held in a u128 - + -A division by zero was encountered +The multiplied value would be too large to be held in a u128 -
const EDIVISION_BY_ZERO: u64 = 65540;
+
const EMULTIPLICATION: u64 = 131075;
 
- + -The multiplied value would be too large to be held in a u128 +Abort code on calculation result is negative. -
const EMULTIPLICATION: u64 = 131075;
+
const ENEGATIVE_RESULT: u64 = 65542;
 
@@ -128,6 +164,259 @@ The computed ratio when converting to a + +## Function `one` + + + +
public fun one(): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun one(): FixedPoint64 {
+    create_from_raw_value(1 << 64)
+}
+
+ + + + + +## Function `zero` + + + +
public fun zero(): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun zero(): FixedPoint64 {
+    create_from_raw_value(0)
+}
+
+ + + + + +## Function `rev` + + + +
public fun rev(self: fixed_point64::FixedPoint64): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun rev(self: FixedPoint64): FixedPoint64 {
+    create_from_raw_value(((1u256 << 128) / (get_raw_value(self) as u256) as u128))
+}
+
+ + + + + +## Function `sub` + +Returns self - y. self must be not less than y. + + +
public fun sub(self: fixed_point64::FixedPoint64, y: fixed_point64::FixedPoint64): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun sub(self: FixedPoint64, y: FixedPoint64): FixedPoint64 {
+    let x_raw = get_raw_value(self);
+    let y_raw = get_raw_value(y);
+    assert!(x_raw >= y_raw, ENEGATIVE_RESULT);
+    create_from_raw_value(x_raw - y_raw)
+}
+
+ + + + + +## Function `sub_u64` + + + +
public fun sub_u64(self: fixed_point64::FixedPoint64, y: u64): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun sub_u64(self: FixedPoint64, y: u64): FixedPoint64 {
+    sub_u128(self, (y as u128))
+}
+
+ + + + + +## Function `sub_u128` + + + +
public fun sub_u128(self: fixed_point64::FixedPoint64, y: u128): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun sub_u128(self: FixedPoint64, y: u128): FixedPoint64 {
+    let x_raw = (get_raw_value(self) as u256);
+    let y_raw = (y as u256) << 64;
+    assert!(x_raw >= y_raw, ENEGATIVE_RESULT);
+    create_from_raw_value(((x_raw - y_raw) as u128))
+}
+
+ + + + + +## Function `add` + +Returns self + y. The result cannot be greater than MAX_U128. + + +
public fun add(self: fixed_point64::FixedPoint64, y: fixed_point64::FixedPoint64): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun add(self: FixedPoint64, y: FixedPoint64): FixedPoint64 {
+    let x_raw = get_raw_value(self);
+    let y_raw = get_raw_value(y);
+    let result = (x_raw as u256) + (y_raw as u256);
+    assert!(result <= MAX_U128, ERATIO_OUT_OF_RANGE);
+    create_from_raw_value((result as u128))
+}
+
+ + + + + +## Function `add_u64` + + + +
public fun add_u64(self: fixed_point64::FixedPoint64, y: u64): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun add_u64(self: FixedPoint64, y: u64): FixedPoint64 {
+    add_u128(self, (y as u128))
+}
+
+ + + + + +## Function `add_u128` + + + +
public fun add_u128(self: fixed_point64::FixedPoint64, y: u128): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun add_u128(self: FixedPoint64, y: u128): FixedPoint64 {
+    let x_raw = (get_raw_value(self) as u256);
+    let y_raw = (y as u256) << 64;
+    let result = x_raw + y_raw;
+    assert!(result <= MAX_U128, ERATIO_OUT_OF_RANGE);
+    create_from_raw_value((result as u128))
+}
+
+ + + + + +## Function `multiply` + + + +
public fun multiply(self: fixed_point64::FixedPoint64, y: fixed_point64::FixedPoint64): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun multiply(self: FixedPoint64, y: FixedPoint64): FixedPoint64 {
+    let x_raw = get_raw_value(self);
+    let y_raw = get_raw_value(y);
+    let result = ((x_raw as u256) * (y_raw as u256)) >> 64;
+    assert!(result <= MAX_U128, EMULTIPLICATION);
+    create_from_raw_value((result as u128))
+}
+
+ + + + + +## Function `multiply_u64` + + + +
public fun multiply_u64(val: u64, multiplier: fixed_point64::FixedPoint64): u64
+
+ + + +##### Implementation + + +
public fun multiply_u64(val: u64, multiplier: FixedPoint64): u64 {
+    let res = multiply_u128((val as u128), multiplier);
+    assert!(res <= MAX_U64, EMULTIPLICATION);
+    (res as u64)
+}
+
+ + + ## Function `multiply_u128` @@ -142,8 +431,7 @@ overflows. -
-Implementation +##### Implementation
public fun multiply_u128(val: u128, multiplier: FixedPoint64): u128 {
@@ -162,45 +450,79 @@ overflows.
 
 
 
-
+ -
-Specification +## Function `divide` -
pragma opaque;
-include MultiplyAbortsIf;
-ensures result == spec_multiply_u128(val, multiplier);
+
public fun divide(self: fixed_point64::FixedPoint64, divisor: fixed_point64::FixedPoint64): fixed_point64::FixedPoint64
 
+##### Implementation - - -
schema MultiplyAbortsIf {
-    val: num;
-    multiplier: FixedPoint64;
-    aborts_if spec_multiply_u128(val, multiplier) > MAX_U128 with EMULTIPLICATION;
+
public fun divide(self: FixedPoint64, divisor: FixedPoint64): FixedPoint64 {
+    // Check for division by zero.
+    assert!(divisor.value != 0, EDIVISION_BY_ZERO);
+    // Perform the division with 256 bits to avoid losing accuracy.
+    let result = ((self.value as u256) << 64) / (divisor.value as u256);
+    assert!(result <= MAX_U128, EDIVISION);
+    create_from_raw_value((result as u128))
 }
 
+ + +## Function `divide_u64` + +Divide a u64 integer by a fixed-point number, truncating any +fractional part of the quotient. This will abort if the divisor +is zero or if the quotient overflows. + + +
public fun divide_u64(val: u64, divisor: fixed_point64::FixedPoint64): u64
+
+ - +##### Implementation -
fun spec_multiply_u128(val: num, multiplier: FixedPoint64): num {
-   (val * multiplier.value) >> 64
+
+
public fun divide_u64(val: u64, divisor: FixedPoint64): u64 {
+    let res = divide_u128((val as u128), divisor);
+    assert!(res <= MAX_U64, EDIVISION);
+    (res as u64)
 }
 
-
+ + +## Function `divide_by_u64` + +Divide a fixed-point number by a u64 integer. + + +
public fun divide_by_u64(val: fixed_point64::FixedPoint64, divisor: u64): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun divide_by_u64(val: FixedPoint64, divisor: u64): FixedPoint64 {
+    divide_by_u128(val, (divisor as u128))
+}
+
+ + @@ -216,8 +538,7 @@ is zero or if the quotient overflows. -
-Implementation +##### Implementation
public fun divide_u128(val: u128, divisor: FixedPoint64): u128 {
@@ -237,47 +558,30 @@ is zero or if the quotient overflows.
 
 
 
-
- -
-Specification - - - -
pragma opaque;
-include DivideAbortsIf;
-ensures result == spec_divide_u128(val, divisor);
-
- - + +## Function `divide_by_u128` - +Divide a fixed-point number by a u128 integer. -
schema DivideAbortsIf {
-    val: num;
-    divisor: FixedPoint64;
-    aborts_if divisor.value == 0 with EDIVISION_BY_ZERO;
-    aborts_if spec_divide_u128(val, divisor) > MAX_U128 with EDIVISION;
-}
+
public fun divide_by_u128(val: fixed_point64::FixedPoint64, divisor: u128): fixed_point64::FixedPoint64
 
- - +##### Implementation -
fun spec_divide_u128(val: num, divisor: FixedPoint64): num {
-   (val << 64) / divisor.value
+
public fun divide_by_u128(val: FixedPoint64, divisor: u128): FixedPoint64 {
+    // Check for division by zero.
+    assert!(divisor != 0, EDIVISION_BY_ZERO);
+    create_from_raw_value(get_raw_value(val) / divisor)
 }
 
-
- ## Function `create_from_rational` @@ -299,8 +603,7 @@ rounding, e.g., 0.0125 will round down to 0.012 instead of up to 0.013. -
-Implementation +##### Implementation
public fun create_from_rational(numerator: u128, denominator: u128): FixedPoint64 {
@@ -320,52 +623,6 @@ rounding, e.g., 0.0125 will round down to 0.012 instead of up to 0.013.
 
 
 
-
- -
-Specification - - - -
pragma opaque;
-pragma verify = false;
-include CreateFromRationalAbortsIf;
-ensures result == spec_create_from_rational(numerator, denominator);
-
- - - - - - - -
schema CreateFromRationalAbortsIf {
-    numerator: u128;
-    denominator: u128;
-    let scaled_numerator = (numerator as u256)<< 64;
-    let scaled_denominator = (denominator as u256);
-    let quotient = scaled_numerator / scaled_denominator;
-    aborts_if scaled_denominator == 0 with EDENOMINATOR;
-    aborts_if quotient == 0 && scaled_numerator != 0 with ERATIO_OUT_OF_RANGE;
-    aborts_if quotient > MAX_U128 with ERATIO_OUT_OF_RANGE;
-}
-
- - - - - - - -
fun spec_create_from_rational(numerator: num, denominator: num): FixedPoint64 {
-   FixedPoint64{value: (numerator << 128) / (denominator << 64)}
-}
-
- - - -
- ## Function `create_from_raw_value` @@ -378,8 +635,7 @@ Create a fixedpoint value from a raw value. -
-Implementation +##### Implementation
public fun create_from_raw_value(value: u128): FixedPoint64 {
@@ -389,22 +645,6 @@ Create a fixedpoint value from a raw value.
 
 
 
-
- -
-Specification - - - -
pragma opaque;
-aborts_if false;
-ensures result.value == value;
-
- - - -
- ## Function `get_raw_value` @@ -414,24 +654,21 @@ adding or subtracting FixedPoint64 values, can be done using the raw values directly. -
public fun get_raw_value(num: fixed_point64::FixedPoint64): u128
+
public fun get_raw_value(self: fixed_point64::FixedPoint64): u128
 
-
-Implementation +##### Implementation -
public fun get_raw_value(num: FixedPoint64): u128 {
-    num.value
+
public fun get_raw_value(self: FixedPoint64): u128 {
+    self.value
 }
 
-
- ## Function `is_zero` @@ -439,24 +676,21 @@ values directly. Returns true if the ratio is zero. -
public fun is_zero(num: fixed_point64::FixedPoint64): bool
+
public fun is_zero(self: fixed_point64::FixedPoint64): bool
 
-
-Implementation +##### Implementation -
public fun is_zero(num: FixedPoint64): bool {
-    num.value == 0
+
public fun is_zero(self: FixedPoint64): bool {
+    self.value == 0
 }
 
-
- ## Function `min` @@ -469,52 +703,17 @@ Returns the smaller of the two FixedPoint64 numbers. -
-Implementation +##### Implementation
public fun min(num1: FixedPoint64, num2: FixedPoint64): FixedPoint64 {
-    if (num1.value < num2.value) {
-        num1
-    } else {
-        num2
-    }
-}
-
- - - -
- -
-Specification - - - -
pragma opaque;
-aborts_if false;
-ensures result == spec_min(num1, num2);
-
- - - - - - - -
fun spec_min(num1: FixedPoint64, num2: FixedPoint64): FixedPoint64 {
-   if (num1.value < num2.value) {
-       num1
-   } else {
-       num2
-   }
+    if (num1.value < num2.value) { num1 }
+    else { num2 }
 }
 
-
- ## Function `max` @@ -527,305 +726,250 @@ Returns the larger of the two FixedPoint64 numbers. -
-Implementation +##### Implementation
public fun max(num1: FixedPoint64, num2: FixedPoint64): FixedPoint64 {
-    if (num1.value > num2.value) {
-        num1
-    } else {
-        num2
-    }
+    if (num1.value > num2.value) { num1 }
+    else { num2 }
 }
 
-
+ -
-Specification +## Function `less_or_equal` +Returns true if self <= num2 -
pragma opaque;
-aborts_if false;
-ensures result == spec_max(num1, num2);
+
public fun less_or_equal(self: fixed_point64::FixedPoint64, num2: fixed_point64::FixedPoint64): bool
 
- - +##### Implementation -
fun spec_max(num1: FixedPoint64, num2: FixedPoint64): FixedPoint64 {
-   if (num1.value > num2.value) {
-       num1
-   } else {
-       num2
-   }
+
public fun less_or_equal(self: FixedPoint64, num2: FixedPoint64): bool {
+    self.value <= num2.value
 }
 
-
+ - +## Function `less` -## Function `create_from_u128` - -Create a fixedpoint value from a u128 value. +Returns true if self < num2 -
public fun create_from_u128(val: u128): fixed_point64::FixedPoint64
+
public fun less(self: fixed_point64::FixedPoint64, num2: fixed_point64::FixedPoint64): bool
 
-
-Implementation +##### Implementation -
public fun create_from_u128(val: u128): FixedPoint64 {
-    let value = (val as u256) << 64;
-    assert!(value <= MAX_U128, ERATIO_OUT_OF_RANGE);
-    FixedPoint64 {value: (value as u128)}
+
public fun less(self: FixedPoint64, num2: FixedPoint64): bool {
+    self.value < num2.value
 }
 
-
- -
-Specification + +## Function `greater_or_equal` - -
pragma opaque;
-include CreateFromU64AbortsIf;
-ensures result == spec_create_from_u128(val);
-
- +Returns true if self >= num2 - - - - -
schema CreateFromU64AbortsIf {
-    val: num;
-    let scaled_value = (val as u256) << 64;
-    aborts_if scaled_value > MAX_U128;
-}
+
public fun greater_or_equal(self: fixed_point64::FixedPoint64, num2: fixed_point64::FixedPoint64): bool
 
+##### Implementation - - -
fun spec_create_from_u128(val: num): FixedPoint64 {
-   FixedPoint64 {value: val << 64}
+
public fun greater_or_equal(self: FixedPoint64, num2: FixedPoint64): bool {
+    self.value >= num2.value
 }
 
-
- - + -## Function `floor` +## Function `greater` -Returns the largest integer less than or equal to a given number. +Returns true if self > num2 -
public fun floor(num: fixed_point64::FixedPoint64): u128
+
public fun greater(self: fixed_point64::FixedPoint64, num2: fixed_point64::FixedPoint64): bool
 
-
-Implementation +##### Implementation -
public fun floor(num: FixedPoint64): u128 {
-    num.value >> 64
+
public fun greater(self: FixedPoint64, num2: FixedPoint64): bool {
+    self.value > num2.value
 }
 
-
+ -
-Specification +## Function `equal` +Returns true if self = num2 -
pragma opaque;
-aborts_if false;
-ensures result == spec_floor(num);
+
public fun equal(self: fixed_point64::FixedPoint64, num2: fixed_point64::FixedPoint64): bool
 
- - +##### Implementation -
fun spec_floor(val: FixedPoint64): u128 {
-   let fractional = val.value % (1 << 64);
-   if (fractional == 0) {
-       val.value >> 64
-   } else {
-       (val.value - fractional) >> 64
-   }
+
public fun equal(self: FixedPoint64, num2: FixedPoint64): bool {
+    self.value == num2.value
 }
 
-
+ - +## Function `almost_equal` -## Function `ceil` +Returns true if self almost equals to num2, which means abs(num1-num2) <= precision -Rounds up the given FixedPoint64 to the next largest integer. - -
public fun ceil(num: fixed_point64::FixedPoint64): u128
+
public fun almost_equal(self: fixed_point64::FixedPoint64, num2: fixed_point64::FixedPoint64, precision: fixed_point64::FixedPoint64): bool
 
-
-Implementation +##### Implementation -
public fun ceil(num: FixedPoint64): u128 {
-    let floored_num = floor(num) << 64;
-    if (num.value == floored_num) {
-        return floored_num >> 64
-    };
-    let val = ((floored_num as u256) + (1 << 64));
-    (val >> 64 as u128)
+
public fun almost_equal(
+    self: FixedPoint64, num2: FixedPoint64, precision: FixedPoint64
+): bool {
+    if (self.value > num2.value) {
+        (self.value - num2.value <= precision.value)
+    } else {
+        (num2.value - self.value <= precision.value)
+    }
 }
 
-
- -
-Specification + +## Function `create_from_u128` -TODO: worked in the past but started to time out since last z3 update +Create a fixedpoint value from a u128 value. -
pragma verify = false;
-pragma opaque;
-aborts_if false;
-ensures result == spec_ceil(num);
+
public fun create_from_u128(val: u128): fixed_point64::FixedPoint64
 
- - +##### Implementation -
fun spec_ceil(val: FixedPoint64): u128 {
-   let fractional = val.value % (1 << 64);
-   let one = 1 << 64;
-   if (fractional == 0) {
-       val.value >> 64
-   } else {
-       (val.value - fractional + one) >> 64
-   }
+
public fun create_from_u128(val: u128): FixedPoint64 {
+    let value = (val as u256) << 64;
+    assert!(value <= MAX_U128, ERATIO_OUT_OF_RANGE);
+    FixedPoint64 { value: (value as u128) }
 }
 
-
- - + -## Function `round` +## Function `floor` -Returns the value of a FixedPoint64 to the nearest integer. +Returns the largest integer less than or equal to a given number. -
public fun round(num: fixed_point64::FixedPoint64): u128
+
public fun floor(self: fixed_point64::FixedPoint64): u128
 
-
-Implementation +##### Implementation -
public fun round(num: FixedPoint64): u128 {
-    let floored_num = floor(num) << 64;
-    let boundary = floored_num + ((1 << 64) / 2);
-    if (num.value < boundary) {
-        floored_num >> 64
-    } else {
-        ceil(num)
-    }
+
public fun floor(self: FixedPoint64): u128 {
+    self.value >> 64
 }
 
-
+ -
-Specification +## Function `ceil` +Rounds up the given FixedPoint64 to the next largest integer. -
pragma opaque;
-aborts_if false;
-ensures result == spec_round(num);
+
public fun ceil(self: fixed_point64::FixedPoint64): u128
 
- - +##### Implementation -
fun spec_round(val: FixedPoint64): u128 {
-   let fractional = val.value % (1 << 64);
-   let boundary = (1 << 64) / 2;
-   let one = 1 << 64;
-   if (fractional < boundary) {
-       (val.value - fractional) >> 64
-   } else {
-       (val.value - fractional + one) >> 64
-   }
+
public fun ceil(self: FixedPoint64): u128 {
+    let floored_num = floor(self) << 64;
+    if (self.value == floored_num) {
+        return floored_num >> 64
+    };
+    let val = ((floored_num as u256) + (1 << 64));
+    (val >> 64 as u128)
 }
 
-
+ + +## Function `round` + +Returns the value of a FixedPoint64 to the nearest integer. + - +
public fun round(self: fixed_point64::FixedPoint64): u128
+
-## Module Specification +##### Implementation -
pragma aborts_if_is_strict;
+
public fun round(self: FixedPoint64): u128 {
+    let floored_num = floor(self) << 64;
+    let boundary = floored_num + ((1 << 64) / 2);
+    if (self.value < boundary) {
+        floored_num >> 64
+    } else {
+        ceil(self)
+    }
+}
 
diff --git a/initia_stdlib/doc/from_bcs.md b/initia_stdlib/doc/from_bcs.md index 34e36ce..1cc6479 100644 --- a/initia_stdlib/doc/from_bcs.md +++ b/initia_stdlib/doc/from_bcs.md @@ -64,8 +64,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_bool(v: vector<u8>): bool {
@@ -75,8 +74,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_u8` @@ -88,8 +85,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_u8(v: vector<u8>): u8 {
@@ -99,8 +95,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_u16` @@ -112,8 +106,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_u16(v: vector<u8>): u16 {
@@ -123,8 +116,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_u32` @@ -136,8 +127,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_u32(v: vector<u8>): u32 {
@@ -147,8 +137,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_u64` @@ -160,8 +148,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_u64(v: vector<u8>): u64 {
@@ -171,8 +158,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_u128` @@ -184,8 +169,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_u128(v: vector<u8>): u128 {
@@ -195,8 +179,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_u256` @@ -208,8 +190,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_u256(v: vector<u8>): u256 {
@@ -219,8 +200,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_address` @@ -232,8 +211,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_address(v: vector<u8>): address {
@@ -243,8 +221,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_bytes` @@ -256,8 +232,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_bytes(v: vector<u8>): vector<u8> {
@@ -267,8 +242,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_vector_bytes` @@ -280,8 +253,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_vector_bytes(v: vector<u8>): vector<vector<u8>> {
@@ -291,8 +263,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_vector_string` @@ -304,19 +274,26 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_vector_string(v: vector<u8>): vector<String> {
-    from_bytes<vector<String>>(v)
+    let vec_string = from_bytes<vector<String>>(v);
+    vector::for_each_ref(
+        &vec_string,
+        |s| {
+            assert!(
+                string::internal_check_utf8(string::bytes(s)),
+                EINVALID_UTF8
+            );
+        }
+    );
+    vec_string
 }
 
-
- ## Function `to_string` @@ -328,22 +305,22 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_string(v: vector<u8>): String {
     // To make this safe, we need to evaluate the utf8 invariant.
     let s = from_bytes<String>(v);
-    assert!(string::internal_check_utf8(string::bytes(&s)), EINVALID_UTF8);
+    assert!(
+        string::internal_check_utf8(string::bytes(&s)),
+        EINVALID_UTF8
+    );
     s
 }
 
-
- ## Function `from_bytes` @@ -360,13 +337,8 @@ owned. -
-Implementation +##### Implementation
public(friend) native fun from_bytes<T>(bytes: vector<u8>): T;
 
- - - -
diff --git a/initia_stdlib/doc/function_info.md b/initia_stdlib/doc/function_info.md new file mode 100644 index 0000000..b3e16cc --- /dev/null +++ b/initia_stdlib/doc/function_info.md @@ -0,0 +1,214 @@ + + + +# Module `0x1::function_info` + +The function_info module defines the FunctionInfo type which simulates a function pointer. + + +- [Struct `FunctionInfo`](#0x1_function_info_FunctionInfo) +- [Constants](#@Constants_0) +- [Function `new_function_info`](#0x1_function_info_new_function_info) +- [Function `new_function_info_from_address`](#0x1_function_info_new_function_info_from_address) +- [Function `check_dispatch_type_compatibility`](#0x1_function_info_check_dispatch_type_compatibility) +- [Function `load_module_from_function`](#0x1_function_info_load_module_from_function) + + +
use 0x1::signer;
+use 0x1::string;
+
+ + + + + +## Struct `FunctionInfo` + +A String holds a sequence of bytes which is guaranteed to be in utf8 format. + + +
struct FunctionInfo has copy, drop, store
+
+ + + +##### Fields + + +
+
+module_address: address +
+
+ +
+
+module_name: string::String +
+
+ +
+
+function_name: string::String +
+
+ +
+
+ + + + +## Constants + + + + +Function specified in the FunctionInfo doesn't exist on chain. + + +
const EINVALID_FUNCTION: u64 = 2;
+
+ + + + + +String is not a valid Move identifier + + +
const EINVALID_IDENTIFIER: u64 = 1;
+
+ + + + + +Feature hasn't been activated yet. + + +
const ENOT_ACTIVATED: u64 = 3;
+
+ + + + + +## Function `new_function_info` + +Creates a new function info from names. + + +
public fun new_function_info(module_signer: &signer, module_name: string::String, function_name: string::String): function_info::FunctionInfo
+
+ + + +##### Implementation + + +
public fun new_function_info(
+    module_signer: &signer, module_name: String, function_name: String
+): FunctionInfo {
+    new_function_info_from_address(
+        signer::address_of(module_signer),
+        module_name,
+        function_name
+    )
+}
+
+ + + + + +## Function `new_function_info_from_address` + + + +
public(friend) fun new_function_info_from_address(module_address: address, module_name: string::String, function_name: string::String): function_info::FunctionInfo
+
+ + + +##### Implementation + + +
public(friend) fun new_function_info_from_address(
+    module_address: address, module_name: String, function_name: String
+): FunctionInfo {
+    assert!(
+        is_identifier(string::bytes(&module_name)),
+        EINVALID_IDENTIFIER
+    );
+    assert!(
+        is_identifier(string::bytes(&function_name)),
+        EINVALID_IDENTIFIER
+    );
+    FunctionInfo { module_address, module_name, function_name }
+}
+
+ + + + + +## Function `check_dispatch_type_compatibility` + +Check if the dispatch target function meets the type requirements of the disptach entry point. + +framework_function is the dispatch native function defined in the initia_std. +dispatch_target is the function passed in by the user. + +dispatch_target should have the same signature (same argument type, same generics constraint) except +that the framework_function will have a &FunctionInfo in the last argument that will instruct the VM which +function to jump to. + +dispatch_target also needs to be public so the type signature will remain unchanged. + + +
public(friend) fun check_dispatch_type_compatibility(framework_function: &function_info::FunctionInfo, dispatch_target: &function_info::FunctionInfo): bool
+
+ + + +##### Implementation + + +
public(friend) fun check_dispatch_type_compatibility(
+    framework_function: &FunctionInfo, dispatch_target: &FunctionInfo
+): bool {
+    load_function_impl(dispatch_target);
+    check_dispatch_type_compatibility_impl(framework_function, dispatch_target)
+}
+
+ + + + + +## Function `load_module_from_function` + +Load up a function into VM's loader and charge for its dependencies + +It is **critical** to make sure that this function is invoked before check_dispatch_type_compatibility +or performing any other dispatching logic to ensure: +1. We properly charge gas for the function to dispatch. +2. The function is loaded in the cache so that we can perform further type checking/dispatching logic. + +Calling check_dispatch_type_compatibility_impl or dispatch without loading up the module would yield an error +if such module isn't accessed previously in the transaction. + + +
public(friend) fun load_module_from_function(f: &function_info::FunctionInfo)
+
+ + + +##### Implementation + + +
public(friend) fun load_module_from_function(f: &FunctionInfo) {
+    load_function_impl(f)
+}
+
diff --git a/initia_stdlib/doc/fungible_asset.md b/initia_stdlib/doc/fungible_asset.md index 13bc6e2..3b9f93e 100644 --- a/initia_stdlib/doc/fungible_asset.md +++ b/initia_stdlib/doc/fungible_asset.md @@ -11,9 +11,12 @@ metadata object can be any object that equipped with use 0x1::error; +
use 0x1::account;
+use 0x1::error;
 use 0x1::event;
+use 0x1::function_info;
 use 0x1::object;
 use 0x1::option;
 use 0x1::signer;
@@ -88,8 +105,7 @@ metadata object can be any object that equipped with 
 
 
-
-
 
 
 ## Resource `Metadata`
@@ -117,13 +131,12 @@ metadata object can be any object that equipped with Metadata has key
+
struct Metadata has copy, drop, key
 
-
-Fields +##### Fields
@@ -164,8 +177,6 @@ Metadata of a Fungible asset
-
- ## Resource `FungibleStore` @@ -178,8 +189,7 @@ The store object that holds fungible assets of a specific type associated with a -
-Fields +##### Fields
@@ -204,8 +214,6 @@ The store object that holds fungible assets of a specific type associated with a
-
- ## Struct `FungibleAsset` @@ -219,8 +227,7 @@ FungibleAsset is ephemeral and cannot be stored directly. It must be deposited b -
-Fields +##### Fields
@@ -239,7 +246,65 @@ FungibleAsset is ephemeral and cannot be stored directly. It must be deposited b
-
+ + +## Resource `DispatchFunctionStore` + + + +
struct DispatchFunctionStore has key
+
+ + + +##### Fields + + +
+
+withdraw_function: option::Option<function_info::FunctionInfo> +
+
+ +
+
+deposit_function: option::Option<function_info::FunctionInfo> +
+
+ +
+
+derived_balance_function: option::Option<function_info::FunctionInfo> +
+
+ +
+
+ + + + +## Resource `DeriveSupply` + + + +
struct DeriveSupply has key
+
+ + + +##### Fields + + +
+
+dispatch_function: option::Option<function_info::FunctionInfo> +
+
+ +
+
+ @@ -253,8 +318,7 @@ MintRef can be used to mint the fungible asset into an account's store. -
-Fields +##### Fields
@@ -267,8 +331,6 @@ MintRef can be used to mint the fungible asset into an account's store.
-
- ## Struct `TransferRef` @@ -282,8 +344,7 @@ and allow the holder of TransferRef to transfer fungible assets from any account -
-Fields +##### Fields
@@ -296,8 +357,6 @@ and allow the holder of TransferRef to transfer fungible assets from any account
-
- ## Struct `BurnRef` @@ -310,8 +369,7 @@ BurnRef can be used to burn fungible assets from a given holder account. -
-Fields +##### Fields
@@ -324,7 +382,30 @@ BurnRef can be used to burn fungible assets from a given holder account.
-
+ + +## Struct `MutateMetadataRef` + +MutateMetadataRef can be used to directly modify the fungible asset's Metadata. + + +
struct MutateMetadataRef has drop, store
+
+ + + +##### Fields + + +
+
+metadata: object::Object<fungible_asset::Metadata> +
+
+ +
+
+ @@ -339,8 +420,7 @@ Emitted when fungible assets are deposited into a store. -
-Fields +##### Fields
@@ -365,8 +445,6 @@ Emitted when fungible assets are deposited into a store.
-
- ## Struct `WithdrawEvent` @@ -380,8 +458,7 @@ Emitted when fungible assets are withdrawn from a store. -
-Fields +##### Fields
@@ -406,8 +483,6 @@ Emitted when fungible assets are withdrawn from a store.
-
- ## Struct `FrozenEvent` @@ -421,8 +496,7 @@ Emitted when a store's frozen status is updated. -
-Fields +##### Fields
@@ -447,8 +521,6 @@ Emitted when a store's frozen status is updated.
-
- ## Struct `BurnEvent` @@ -462,8 +534,7 @@ Emitted when fungible assets are burnt. -
-Fields +##### Fields
@@ -482,8 +553,6 @@ Emitted when fungible assets are burnt.
-
- ## Struct `MintEvent` @@ -497,8 +566,7 @@ Emitted when fungible assets are minted. -
-Fields +##### Fields
@@ -517,8 +585,6 @@ Emitted when fungible assets are minted.
-
- ## Constants @@ -534,6 +600,16 @@ Maximum possible coin supply. + + +Trying to re-register dispatch hook on a fungible asset. + + +
const EALREADY_REGISTERED: u64 = 29;
+
+ + + Cannot destroy non-empty fungible assets. @@ -544,6 +620,16 @@ Cannot destroy non-empty fungible assets. + + +Cannot register dispatch hook for APT. + + +
const EAPT_NOT_DISPATCHABLE: u64 = 31;
+
+ + + Cannot destroy fungible stores with a non-zero balance. @@ -574,6 +660,26 @@ Burn ref and store do not match. + + +Deposit to a blocked account is not allowed._ + + +
const ECANNOT_DEPOSIT_TO_BLOCKED_ACCOUNT: u64 = 92;
+
+ + + + + +Module account store cannot be manipulated. + + +
const ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE: u64 = 91;
+
+ + + Decimals is over the maximum of 32 @@ -584,6 +690,36 @@ Decimals is over the maximum of 32 + + +Provided deposit function type doesn't meet the signature requirement. + + +
const EDEPOSIT_FUNCTION_SIGNATURE_MISMATCH: u64 = 26;
+
+ + + + + +Provided derived_balance function type doesn't meet the signature requirement. + + +
const EDERIVED_BALANCE_FUNCTION_SIGNATURE_MISMATCH: u64 = 27;
+
+ + + + + +Provided derived_supply function type doesn't meet the signature requirement. + + +
const EDERIVED_SUPPLY_FUNCTION_SIGNATURE_MISMATCH: u64 = 33;
+
+ + + Fungible asset and store do not match. @@ -604,6 +740,26 @@ Fungible asset do not match when merging. + + +Fungible metadata does not exist on this account. + + +
const EFUNGIBLE_METADATA_EXISTENCE: u64 = 30;
+
+ + + + + +Flag for the existence of fungible store. + + +
const EFUNGIBLE_STORE_EXISTENCE: u64 = 23;
+
+ + + Insufficient balance to withdraw or transfer. @@ -614,6 +770,17 @@ Insufficient balance to withdraw or transfer. + + +Invalid withdraw/deposit on dispatchable token. The specified token has a dispatchable function hook. +Need to invoke dispatchable_fungible_asset::withdraw/deposit to perform transfer. + + +
const EINVALID_DISPATCHABLE_OPERATIONS: u64 = 28;
+
+ + + The fungible asset's supply has exceeded maximum. @@ -644,6 +811,16 @@ Name of the fungible asset metadata is too long + + +Account is not the owner of metadata object. + + +
const ENOT_METADATA_OWNER: u64 = 24;
+
+ + + Account is not the store's owner. @@ -734,6 +911,16 @@ URI for the icon of the fungible asset metadata is too long + + +Provided withdraw function type doesn't meet the signature requirement. + + +
const EWITHDRAW_FUNCTION_SIGNATURE_MISMATCH: u64 = 25;
+
+ + + @@ -788,8 +975,7 @@ maximum_supply defines the behavior of maximum supply when monitoring: -
-Implementation +##### Implementation
public fun add_fungibility(
@@ -799,34 +985,47 @@ maximum_supply defines the behavior of maximum supply when monitoring:
     symbol: String,
     decimals: u8,
     icon_uri: String,
-    project_uri: String,
+    project_uri: String
 ): Object<Metadata> {
-    assert!(!object::can_generate_delete_ref(constructor_ref), error::invalid_argument(EOBJECT_IS_DELETABLE));
+    assert!(
+        !object::can_generate_delete_ref(constructor_ref),
+        error::invalid_argument(EOBJECT_IS_DELETABLE)
+    );
     let metadata_object_signer = &object::generate_signer(constructor_ref);
 
     // metadata validations
-    assert!(string::length(&name) <= MAX_NAME_LENGTH, error::out_of_range(ENAME_TOO_LONG));
-    assert!(string::length(&symbol) <= MAX_SYMBOL_LENGTH, error::out_of_range(ESYMBOL_TOO_LONG));
-    assert!(decimals <= MAX_DECIMALS, error::out_of_range(EDECIMALS_TOO_LARGE));
-    assert!(string::length(&icon_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
-    assert!(string::length(&project_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
+    assert!(
+        string::length(&name) <= MAX_NAME_LENGTH,
+        error::out_of_range(ENAME_TOO_LONG)
+    );
+    assert!(
+        string::length(&symbol) <= MAX_SYMBOL_LENGTH,
+        error::out_of_range(ESYMBOL_TOO_LONG)
+    );
+    assert!(
+        decimals <= MAX_DECIMALS,
+        error::out_of_range(EDECIMALS_TOO_LARGE)
+    );
+    assert!(
+        string::length(&icon_uri) <= MAX_URI_LENGTH,
+        error::out_of_range(EURI_TOO_LONG)
+    );
+    assert!(
+        string::length(&project_uri) <= MAX_URI_LENGTH,
+        error::out_of_range(EURI_TOO_LONG)
+    );
 
     // store metadata
-    move_to(metadata_object_signer,
-        Metadata {
-            name,
-            symbol,
-            decimals,
-            icon_uri,
-            project_uri,
-        }
+    move_to(
+        metadata_object_signer,
+        Metadata { name, symbol, decimals, icon_uri, project_uri }
     );
 
     // store supply
-    move_to(metadata_object_signer, Supply {
-        current: 0,
-        maximum: maximum_supply
-    });
+    move_to(
+        metadata_object_signer,
+        Supply { current: 0, maximum: maximum_supply }
+    );
 
     // return metadata object
     object::object_from_constructor_ref<Metadata>(constructor_ref)
@@ -835,7 +1034,169 @@ maximum_supply defines the behavior of maximum supply when monitoring:
 
 
 
-
+ + +## Function `register_dispatch_functions` + +Create a fungible asset store whose transfer rule would be overloaded by the provided function. + + +
public(friend) fun register_dispatch_functions(constructor_ref: &object::ConstructorRef, withdraw_function: option::Option<function_info::FunctionInfo>, deposit_function: option::Option<function_info::FunctionInfo>, derived_balance_function: option::Option<function_info::FunctionInfo>)
+
+ + + +##### Implementation + + +
public(friend) fun register_dispatch_functions(
+    constructor_ref: &ConstructorRef,
+    withdraw_function: Option<FunctionInfo>,
+    deposit_function: Option<FunctionInfo>,
+    derived_balance_function: Option<FunctionInfo>
+) {
+    // Verify that caller type matches callee type so wrongly typed function cannot be registered.
+    option::for_each_ref(
+        &withdraw_function,
+        |withdraw_function| {
+            let dispatcher_withdraw_function_info =
+                function_info::new_function_info_from_address(
+                    @initia_std,
+                    string::utf8(b"dispatchable_fungible_asset"),
+                    string::utf8(b"dispatchable_withdraw")
+                );
+
+            assert!(
+                function_info::check_dispatch_type_compatibility(
+                    &dispatcher_withdraw_function_info,
+                    withdraw_function
+                ),
+                error::invalid_argument(EWITHDRAW_FUNCTION_SIGNATURE_MISMATCH)
+            );
+        }
+    );
+
+    option::for_each_ref(
+        &deposit_function,
+        |deposit_function| {
+            let dispatcher_deposit_function_info =
+                function_info::new_function_info_from_address(
+                    @initia_std,
+                    string::utf8(b"dispatchable_fungible_asset"),
+                    string::utf8(b"dispatchable_deposit")
+                );
+            // Verify that caller type matches callee type so wrongly typed function cannot be registered.
+            assert!(
+                function_info::check_dispatch_type_compatibility(
+                    &dispatcher_deposit_function_info,
+                    deposit_function
+                ),
+                error::invalid_argument(EDEPOSIT_FUNCTION_SIGNATURE_MISMATCH)
+            );
+        }
+    );
+
+    option::for_each_ref(
+        &derived_balance_function,
+        |balance_function| {
+            let dispatcher_derived_balance_function_info =
+                function_info::new_function_info_from_address(
+                    @initia_std,
+                    string::utf8(b"dispatchable_fungible_asset"),
+                    string::utf8(b"dispatchable_derived_balance")
+                );
+            // Verify that caller type matches callee type so wrongly typed function cannot be registered.
+            assert!(
+                function_info::check_dispatch_type_compatibility(
+                    &dispatcher_derived_balance_function_info,
+                    balance_function
+                ),
+                error::invalid_argument(
+                    EDERIVED_BALANCE_FUNCTION_SIGNATURE_MISMATCH
+                )
+            );
+        }
+    );
+    register_dispatch_function_sanity_check(constructor_ref);
+    assert!(
+        !exists<DispatchFunctionStore>(
+            object::address_from_constructor_ref(constructor_ref)
+        ),
+        error::already_exists(EALREADY_REGISTERED)
+    );
+
+    let store_obj = &object::generate_signer(constructor_ref);
+
+    // Store the overload function hook.
+    move_to<DispatchFunctionStore>(
+        store_obj,
+        DispatchFunctionStore {
+            withdraw_function,
+            deposit_function,
+            derived_balance_function
+        }
+    );
+}
+
+ + + + + +## Function `register_derive_supply_dispatch_function` + +Define the derived supply dispatch with the provided function. + + +
public(friend) fun register_derive_supply_dispatch_function(constructor_ref: &object::ConstructorRef, dispatch_function: option::Option<function_info::FunctionInfo>)
+
+ + + +##### Implementation + + +
public(friend) fun register_derive_supply_dispatch_function(
+    constructor_ref: &ConstructorRef, dispatch_function: Option<FunctionInfo>
+) {
+    // Verify that caller type matches callee type so wrongly typed function cannot be registered.
+    option::for_each_ref(
+        &dispatch_function,
+        |supply_function| {
+            let function_info =
+                function_info::new_function_info_from_address(
+                    @initia_std,
+                    string::utf8(b"dispatchable_fungible_asset"),
+                    string::utf8(b"dispatchable_derived_supply")
+                );
+            // Verify that caller type matches callee type so wrongly typed function cannot be registered.
+            assert!(
+                function_info::check_dispatch_type_compatibility(
+                    &function_info,
+                    supply_function
+                ),
+                error::invalid_argument(
+                    EDERIVED_SUPPLY_FUNCTION_SIGNATURE_MISMATCH
+                )
+            );
+        }
+    );
+    register_dispatch_function_sanity_check(constructor_ref);
+    assert!(
+        !exists<DeriveSupply>(
+            object::address_from_constructor_ref(constructor_ref)
+        ),
+        error::already_exists(EALREADY_REGISTERED)
+    );
+
+    let store_obj = &object::generate_signer(constructor_ref);
+
+    // Store the overload function hook.
+    move_to<DeriveSupply>(store_obj, DeriveSupply { dispatch_function });
+}
+
+ + @@ -850,8 +1211,7 @@ This can only be called at object creation time as constructor_ref is only avail -
-Implementation +##### Implementation
public fun generate_mint_ref(constructor_ref: &ConstructorRef): MintRef {
@@ -862,8 +1222,6 @@ This can only be called at object creation time as constructor_ref is only avail
 
 
 
-
- ## Function `generate_burn_ref` @@ -877,8 +1235,7 @@ This can only be called at object creation time as constructor_ref is only avail -
-Implementation +##### Implementation
public fun generate_burn_ref(constructor_ref: &ConstructorRef): BurnRef {
@@ -889,8 +1246,6 @@ This can only be called at object creation time as constructor_ref is only avail
 
 
 
-
- ## Function `generate_transfer_ref` @@ -905,8 +1260,7 @@ This can only be called at object creation time as constructor_ref is only avail -
-Implementation +##### Implementation
public fun generate_transfer_ref(constructor_ref: &ConstructorRef): TransferRef {
@@ -917,7 +1271,32 @@ This can only be called at object creation time as constructor_ref is only avail
 
 
 
-
+ + +## Function `generate_mutate_metadata_ref` + +Creates a mutate metadata ref that can be used to change the metadata information of fungible assets from the +given fungible object's constructor ref. +This can only be called at object creation time as constructor_ref is only available then. + + +
public fun generate_mutate_metadata_ref(constructor_ref: &object::ConstructorRef): fungible_asset::MutateMetadataRef
+
+ + + +##### Implementation + + +
public fun generate_mutate_metadata_ref(
+    constructor_ref: &ConstructorRef
+): MutateMetadataRef {
+    let metadata = object::object_from_constructor_ref<Metadata>(constructor_ref);
+    MutateMetadataRef { metadata }
+}
+
+ + @@ -932,8 +1311,7 @@ Retrun true if given address has Metadata else return false -
-Implementation +##### Implementation
public fun is_fungible_asset(metadata_addr: address): bool {
@@ -943,8 +1321,6 @@ Retrun true if given address has Metadata else return false
 
 
 
-
- ## Function `supply` @@ -958,12 +1334,11 @@ Get the current supply from the metadata object. -
-Implementation +##### Implementation
public fun supply<T: key>(metadata: Object<T>): Option<u128> acquires Supply {
-    let metadata_address = object::object_address(metadata);
+    let metadata_address = object::object_address(&metadata);
     if (exists<Supply>(metadata_address)) {
         let supply = borrow_global<Supply>(metadata_address);
         option::some(supply.current)
@@ -975,8 +1350,6 @@ Get the current supply from the metadata object.
 
 
 
-
- ## Function `maximum` @@ -990,12 +1363,11 @@ Get the maximum supply from the metadata object. -
-Implementation +##### Implementation
public fun maximum<T: key>(metadata: Object<T>): Option<u128> acquires Supply {
-    let metadata_address = object::object_address(metadata);
+    let metadata_address = object::object_address(&metadata);
     if (exists<Supply>(metadata_address)) {
         let supply = borrow_global<Supply>(metadata_address);
         supply.maximum
@@ -1007,8 +1379,6 @@ Get the maximum supply from the metadata object.
 
 
 
-
- ## Function `name` @@ -1022,19 +1392,16 @@ Get the name of the fungible asset from the metadata object. -
-Implementation +##### Implementation
public fun name<T: key>(metadata: Object<T>): String acquires Metadata {
-    borrow_fungible_metadata(metadata).name
+    borrow_fungible_metadata(&metadata).name
 }
 
-
- ## Function `symbol` @@ -1048,48 +1415,111 @@ Get the symbol of the fungible asset from the metadata object. -
-Implementation +##### Implementation
public fun symbol<T: key>(metadata: Object<T>): String acquires Metadata {
-    borrow_fungible_metadata(metadata).symbol
+    borrow_fungible_metadata(&metadata).symbol
 }
 
-
+ - - -## Function `decimals` +## Function `icon_uri` -Get the decimals from the metadata object. +Get the icon uri from the metadata object.
#[view]
-public fun decimals<T: key>(metadata: object::Object<T>): u8
+public fun icon_uri<T: key>(metadata: object::Object<T>): string::String
 
-
-Implementation +##### Implementation -
public fun decimals<T: key>(metadata: Object<T>): u8 acquires Metadata {
-    borrow_fungible_metadata(metadata).decimals
+
public fun icon_uri<T: key>(metadata: Object<T>): String acquires Metadata {
+    borrow_fungible_metadata(&metadata).icon_uri
 }
 
-
+ - +## Function `project_uri` -## Function `store_exists` +Get the project uri from the metadata object. + + +
#[view]
+public fun project_uri<T: key>(metadata: object::Object<T>): string::String
+
+ + + +##### Implementation + + +
public fun project_uri<T: key>(metadata: Object<T>): String acquires Metadata {
+    borrow_fungible_metadata(&metadata).project_uri
+}
+
+ + + + + +## Function `metadata` + +Get the metadata struct from the metadata object. + + +
#[view]
+public fun metadata<T: key>(metadata: object::Object<T>): fungible_asset::Metadata
+
+ + + +##### Implementation + + +
public fun metadata<T: key>(metadata: Object<T>): Metadata acquires Metadata {
+    *borrow_fungible_metadata(&metadata)
+}
+
+ + + + + +## Function `decimals` + +Get the decimals from the metadata object. + + +
#[view]
+public fun decimals<T: key>(metadata: object::Object<T>): u8
+
+ + + +##### Implementation + + +
public fun decimals<T: key>(metadata: Object<T>): u8 acquires Metadata {
+    borrow_fungible_metadata(&metadata).decimals
+}
+
+ + + + + +## Function `store_exists` Return whether the provided address has a store initialized. @@ -1100,8 +1530,7 @@ Return whether the provided address has a store initialized. -
-Implementation +##### Implementation
public fun store_exists(store: address): bool {
@@ -1111,8 +1540,6 @@ Return whether the provided address has a store initialized.
 
 
 
-
- ## Function `metadata_from_asset` @@ -1125,8 +1552,7 @@ Return the underlying metadata object -
-Implementation +##### Implementation
public fun metadata_from_asset(fa: &FungibleAsset): Object<Metadata> {
@@ -1136,8 +1562,6 @@ Return the underlying metadata object
 
 
 
-
- ## Function `store_metadata` @@ -1151,19 +1575,16 @@ Return the underlying metadata object. -
-Implementation +##### Implementation
public fun store_metadata<T: key>(store: Object<T>): Object<Metadata> acquires FungibleStore {
-    borrow_store_resource(store).metadata
+    borrow_store_resource(&store).metadata
 }
 
-
- ## Function `amount` @@ -1176,8 +1597,7 @@ Return the amount of a given fungible asset. -
-Implementation +##### Implementation
public fun amount(fa: &FungibleAsset): u64 {
@@ -1187,8 +1607,6 @@ Return the amount of a given fungible asset.
 
 
 
-
- ## Function `balance` @@ -1202,23 +1620,18 @@ Get the balance of a given store. -
-Implementation +##### Implementation
public fun balance<T: key>(store: Object<T>): u64 acquires FungibleStore {
-    if (store_exists(object::object_address(store))) {
-        borrow_store_resource(store).balance
-    } else {
-        0
-    }
+    if (store_exists(object::object_address(&store))) {
+        borrow_store_resource(&store).balance
+    } else { 0 }
 }
 
-
- ## Function `is_frozen` @@ -1234,18 +1647,156 @@ If the store has not been created, we default to returning false so deposits can -
-Implementation +##### Implementation
public fun is_frozen<T: key>(store: Object<T>): bool acquires FungibleStore {
-    store_exists(object::object_address(store)) && borrow_store_resource(store).frozen
+    store_exists(object::object_address(&store))
+        && borrow_store_resource(&store).frozen
+}
+
+ + + + + +## Function `is_store_dispatchable` + +Return whether a fungible asset type is dispatchable. + + +
#[view]
+public fun is_store_dispatchable<T: key>(store: object::Object<T>): bool
+
+ + + +##### Implementation + + +
public fun is_store_dispatchable<T: key>(store: Object<T>): bool acquires FungibleStore {
+    let fa_store = borrow_store_resource(&store);
+    let metadata_addr = object::object_address(&fa_store.metadata);
+    exists<DispatchFunctionStore>(metadata_addr)
+}
+
+ + + + + +## Function `deposit_dispatch_function` + + + +
public fun deposit_dispatch_function<T: key>(store: object::Object<T>): option::Option<function_info::FunctionInfo>
+
+ + + +##### Implementation + + +
public fun deposit_dispatch_function<T: key>(
+    store: Object<T>
+): Option<FunctionInfo> acquires FungibleStore, DispatchFunctionStore {
+    let fa_store = borrow_store_resource(&store);
+    let metadata_addr = object::object_address(&fa_store.metadata);
+    if (exists<DispatchFunctionStore>(metadata_addr)) {
+        borrow_global<DispatchFunctionStore>(metadata_addr).deposit_function
+    } else {
+        option::none()
+    }
+}
+
+ + + + + +## Function `withdraw_dispatch_function` + + + +
public fun withdraw_dispatch_function<T: key>(store: object::Object<T>): option::Option<function_info::FunctionInfo>
+
+ + + +##### Implementation + + +
public fun withdraw_dispatch_function<T: key>(
+    store: Object<T>
+): Option<FunctionInfo> acquires FungibleStore, DispatchFunctionStore {
+    let fa_store = borrow_store_resource(&store);
+    let metadata_addr = object::object_address(&fa_store.metadata);
+    if (exists<DispatchFunctionStore>(metadata_addr)) {
+        borrow_global<DispatchFunctionStore>(metadata_addr).withdraw_function
+    } else {
+        option::none()
+    }
 }
 
-
+ + +## Function `derived_balance_dispatch_function` + + + +
public(friend) fun derived_balance_dispatch_function<T: key>(store: object::Object<T>): option::Option<function_info::FunctionInfo>
+
+ + + +##### Implementation + + +
public(friend) fun derived_balance_dispatch_function<T: key>(
+    store: Object<T>
+): Option<FunctionInfo> acquires FungibleStore, DispatchFunctionStore {
+    let fa_store = borrow_store_resource(&store);
+    let metadata_addr = object::object_address(&fa_store.metadata);
+    if (exists<DispatchFunctionStore>(metadata_addr)) {
+        borrow_global<DispatchFunctionStore>(metadata_addr).derived_balance_function
+    } else {
+        option::none()
+    }
+}
+
+ + + + + +## Function `derived_supply_dispatch_function` + + + +
public(friend) fun derived_supply_dispatch_function<T: key>(metadata: object::Object<T>): option::Option<function_info::FunctionInfo>
+
+ + + +##### Implementation + + +
public(friend) fun derived_supply_dispatch_function<T: key>(
+    metadata: Object<T>
+): Option<FunctionInfo> acquires DeriveSupply {
+    let metadata_addr = object::object_address(&metadata);
+    if (exists<DeriveSupply>(metadata_addr)) {
+        borrow_global<DeriveSupply>(metadata_addr).dispatch_function
+    } else {
+        option::none()
+    }
+}
+
+ + @@ -1258,8 +1809,7 @@ If the store has not been created, we default to returning false so deposits can -
-Implementation +##### Implementation
public fun asset_metadata(fa: &FungibleAsset): Object<Metadata> {
@@ -1269,8 +1819,6 @@ If the store has not been created, we default to returning false so deposits can
 
 
 
-
- ## Function `mint_ref_metadata` @@ -1283,8 +1831,7 @@ Get the underlying metadata object from the mint_ref_metadata(ref: &MintRef): Object<Metadata> { @@ -1294,8 +1841,6 @@ Get the underlying metadata object from the ## Function `transfer_ref_metadata` @@ -1308,8 +1853,7 @@ Get the underlying metadata object from the transfer_ref_metadata(ref: &TransferRef): Object<Metadata> { @@ -1319,8 +1863,6 @@ Get the underlying metadata object from the ## Function `burn_ref_metadata` @@ -1333,8 +1875,7 @@ Get the underlying metadata object from the burn_ref_metadata(ref: &BurnRef): Object<Metadata> { @@ -1344,7 +1885,27 @@ Get the underlying metadata object from the + +## Function `object_from_metadata_ref` + +Get the underlying metadata object from the MutateMetadataRef. + + +
public fun object_from_metadata_ref(ref: &fungible_asset::MutateMetadataRef): object::Object<fungible_asset::Metadata>
+
+ + + +##### Implementation + + +
public fun object_from_metadata_ref(ref: &MutateMetadataRef): Object<Metadata> {
+    ref.metadata
+}
+
+ + @@ -1359,16 +1920,15 @@ Note: it does not move the underlying object. -
-Implementation +##### Implementation
public entry fun transfer<T: key>(
     sender: &signer,
     from: Object<T>,
     to: Object<T>,
-    amount: u64,
-) acquires FungibleStore {
+    amount: u64
+) acquires FungibleStore, DispatchFunctionStore {
     let fa = withdraw(sender, from, amount);
     deposit(to, fa);
 }
@@ -1376,8 +1936,6 @@ Note: it does not move the underlying object.
 
 
 
-
- ## Function `create_store` @@ -1391,20 +1949,17 @@ Applications can use this to create multiple stores for isolating fungible asset -
-Implementation +##### Implementation
public fun create_store<T: key>(
-    constructor_ref: &ConstructorRef,
-    metadata: Object<T>,
+    constructor_ref: &ConstructorRef, metadata: Object<T>
 ): Object<FungibleStore> {
     let store_obj = &object::generate_signer(constructor_ref);
-    move_to(store_obj, FungibleStore {
-        metadata: object::convert(metadata),
-        balance: 0,
-        frozen: false,
-    });
+    move_to(
+        store_obj,
+        FungibleStore { metadata: object::convert(metadata), balance: 0, frozen: false }
+    );
 
     object::object_from_constructor_ref<FungibleStore>(constructor_ref)
 }
@@ -1412,8 +1967,6 @@ Applications can use this to create multiple stores for isolating fungible asset
 
 
 
-
- ## Function `create_store_with_extend_ref` @@ -1427,20 +1980,17 @@ Applications can use this to create multiple stores for isolating fungible asset -
-Implementation +##### Implementation
public fun create_store_with_extend_ref<T: key>(
-    extend_ref: &ExtendRef,
-    metadata: Object<T>,
+    extend_ref: &ExtendRef, metadata: Object<T>
 ): Object<FungibleStore> {
     let store_obj = &object::generate_signer_for_extending(extend_ref);
-    move_to(store_obj, FungibleStore {
-        metadata: object::convert(metadata),
-        balance: 0,
-        frozen: false,
-    });
+    move_to(
+        store_obj,
+        FungibleStore { metadata: object::convert(metadata), balance: 0, frozen: false }
+    );
 
     let obj_addr = object::address_from_extend_ref(extend_ref);
     object::address_to_object<FungibleStore>(obj_addr)
@@ -1449,8 +1999,6 @@ Applications can use this to create multiple stores for isolating fungible asset
 
 
 
-
- ## Function `remove_store` @@ -1463,22 +2011,92 @@ Used to delete a store. Requires the store to be completely empty prior to remo -
-Implementation +##### Implementation
public fun remove_store(delete_ref: &DeleteRef) acquires FungibleStore {
     let store = object::object_from_delete_ref<FungibleStore>(delete_ref);
-    let addr = object::object_address(store);
-    let FungibleStore { metadata: _, balance, frozen: _ }
-        = move_from<FungibleStore>(addr);
-    assert!(balance == 0, error::permission_denied(EBALANCE_IS_NOT_ZERO));
+    let addr = object::object_address(&store);
+    let FungibleStore { metadata: _, balance, frozen: _ } =
+        move_from<FungibleStore>(addr);
+    assert!(
+        balance == 0,
+        error::permission_denied(EBALANCE_IS_NOT_ZERO)
+    );
+}
+
+ + + + + +## Function `withdraw_sanity_check` + +Check the permission for withdraw operation. + + +
public(friend) fun withdraw_sanity_check<T: key>(owner: &signer, store: object::Object<T>, abort_on_dispatch: bool)
+
+ + + +##### Implementation + + +
public(friend) fun withdraw_sanity_check<T: key>(
+    owner: &signer, store: Object<T>, abort_on_dispatch: bool
+) acquires FungibleStore, DispatchFunctionStore {
+    assert!(
+        object::owns(store, signer::address_of(owner)),
+        error::permission_denied(ENOT_STORE_OWNER)
+    );
+    let fa_store = borrow_store_resource(&store);
+    assert!(
+        !abort_on_dispatch || !has_withdraw_dispatch_function(fa_store.metadata),
+        error::invalid_argument(EINVALID_DISPATCHABLE_OPERATIONS)
+    );
+    assert!(!fa_store.frozen, error::permission_denied(ESTORE_IS_FROZEN));
 }
 
-
+ + +## Function `deposit_sanity_check` + +Deposit amount of the fungible asset to store. + + +
public fun deposit_sanity_check<T: key>(store: object::Object<T>, abort_on_dispatch: bool)
+
+ + + +##### Implementation + + +
public fun deposit_sanity_check<T: key>(
+    store: Object<T>, abort_on_dispatch: bool
+) acquires FungibleStore, DispatchFunctionStore {
+    let fa_store = borrow_store_resource(&store);
+    assert!(
+        !abort_on_dispatch || !has_deposit_dispatch_function(fa_store.metadata),
+        error::invalid_argument(EINVALID_DISPATCHABLE_OPERATIONS)
+    );
+
+    assert!(!fa_store.frozen, error::permission_denied(ESTORE_IS_FROZEN));
+
+    // cannot deposit to blocked account
+    let store_addr = object::object_address(&store);
+    assert!(
+        !is_blocked_store_addr(store_addr),
+        error::invalid_argument(ECANNOT_DEPOSIT_TO_BLOCKED_ACCOUNT)
+    );
+}
+
+ + @@ -1492,25 +2110,19 @@ Withdraw amount of the fungible asset from store by th -
-Implementation +##### Implementation
public fun withdraw<T: key>(
-    owner: &signer,
-    store: Object<T>,
-    amount: u64,
-): FungibleAsset acquires FungibleStore {
-    assert!(object::owns(store, signer::address_of(owner)), error::permission_denied(ENOT_STORE_OWNER));
-    assert!(!is_frozen(store), error::invalid_argument(ESTORE_IS_FROZEN));
-    withdraw_internal(object::object_address(store), amount)
+    owner: &signer, store: Object<T>, amount: u64
+): FungibleAsset acquires FungibleStore, DispatchFunctionStore {
+    withdraw_sanity_check(owner, store, true);
+    withdraw_internal(object::object_address(&store), amount)
 }
 
-
- ## Function `deposit` @@ -1523,20 +2135,19 @@ Deposit amount of the fungible asset to store. -
-Implementation +##### Implementation -
public fun deposit<T: key>(store: Object<T>, fa: FungibleAsset) acquires FungibleStore {
-    assert!(!is_frozen(store), error::invalid_argument(ESTORE_IS_FROZEN));
-    deposit_internal(store, fa);
+
public fun deposit<T: key>(
+    store: Object<T>, fa: FungibleAsset
+) acquires FungibleStore, DispatchFunctionStore {
+    deposit_sanity_check(store, true);
+    deposit_internal(object::object_address(&store), fa);
 }
 
-
- ## Function `mint` @@ -1549,8 +2160,7 @@ Mint the specified amount of the fungible asset. -
-Implementation +##### Implementation
public fun mint(ref: &MintRef, amount: u64): FungibleAsset acquires Supply {
@@ -1560,20 +2170,15 @@ Mint the specified amount of the fungible asset.
     increase_supply(metadata, amount);
 
     // emit event
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
     event::emit(MintEvent { metadata_addr, amount });
 
-    FungibleAsset {
-        metadata,
-        amount
-    }
+    FungibleAsset { metadata, amount }
 }
 
-
- ## Function `mint_to` @@ -1586,20 +2191,19 @@ Mint the specified amount of the fungible asset to a destination st -
-Implementation +##### Implementation -
public fun mint_to<T: key>(ref: &MintRef, store: Object<T>, amount: u64)
-acquires FungibleStore, Supply {
-    deposit(store, mint(ref, amount));
+
public fun mint_to<T: key>(
+    ref: &MintRef, store: Object<T>, amount: u64
+) acquires FungibleStore, Supply, DispatchFunctionStore {
+    deposit_sanity_check(store, false);
+    deposit_internal(object::object_address(&store), mint(ref, amount));
 }
 
-
- ## Function `set_frozen_flag` @@ -1612,22 +2216,26 @@ Enable/disable a store's ability to do direct transfers of the fungible asset. -
-Implementation +##### Implementation
public fun set_frozen_flag<T: key>(
-    ref: &TransferRef,
-    store: Object<T>,
-    frozen: bool,
+    ref: &TransferRef, store: Object<T>, frozen: bool
 ) acquires FungibleStore {
     assert!(
         ref.metadata == store_metadata(store),
-        error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH),
+        error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH)
+    );
+
+    let metadata_addr = object::object_address(&ref.metadata);
+    let store_addr = object::object_address(&store);
+
+    // cannot freeze module account store
+    assert!(
+        !is_module_account_store_addr(store_addr),
+        error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE)
     );
 
-    let metadata_addr = object::object_address(ref.metadata);
-    let store_addr = object::object_address(store);
     borrow_global_mut<FungibleStore>(store_addr).frozen = frozen;
 
     // emit event
@@ -1637,8 +2245,6 @@ Enable/disable a store's ability to do direct transfers of the fungible asset.
 
 
 
-
- ## Function `burn` @@ -1651,28 +2257,25 @@ Burns a fungible asset -
-Implementation +##### Implementation
public fun burn(ref: &BurnRef, fa: FungibleAsset) acquires Supply {
-    let FungibleAsset {
-        metadata,
-        amount,
-    } = fa;
-    assert!(ref.metadata == metadata, error::invalid_argument(EBURN_REF_AND_FUNGIBLE_ASSET_MISMATCH));
+    let FungibleAsset { metadata, amount } = fa;
+    assert!(
+        ref.metadata == metadata,
+        error::invalid_argument(EBURN_REF_AND_FUNGIBLE_ASSET_MISMATCH)
+    );
     decrease_supply(metadata, amount);
 
     // emit event
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
     event::emit(BurnEvent { metadata_addr, amount });
 }
 
-
- ## Function `burn_from` @@ -1685,27 +2288,32 @@ Burn the amount of the fungible asset from the given store. -
-Implementation +##### Implementation
public fun burn_from<T: key>(
-    ref: &BurnRef,
-    store: Object<T>,
-    amount: u64
+    ref: &BurnRef, store: Object<T>, amount: u64
 ) acquires FungibleStore, Supply {
     let metadata = ref.metadata;
-    assert!(metadata == store_metadata(store), error::invalid_argument(EBURN_REF_AND_STORE_MISMATCH));
+    assert!(
+        metadata == store_metadata(store),
+        error::invalid_argument(EBURN_REF_AND_STORE_MISMATCH)
+    );
+
+    let store_addr = object::object_address(&store);
+
+    // cannot burn module account funds
+    assert!(
+        !is_module_account_store_addr(store_addr),
+        error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE)
+    );
 
-    let store_addr = object::object_address(store);
     burn(ref, withdraw_internal(store_addr, amount));
 }
 
-
- ## Function `withdraw_with_ref` @@ -1718,28 +2326,30 @@ Withdraw amount of the fungible asset from the store i -
-Implementation +##### Implementation
public fun withdraw_with_ref<T: key>(
-    ref: &TransferRef,
-    store: Object<T>,
-    amount: u64
+    ref: &TransferRef, store: Object<T>, amount: u64
 ): FungibleAsset acquires FungibleStore {
     assert!(
         ref.metadata == store_metadata(store),
-        error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH),
+        error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH)
     );
 
-    withdraw_internal(object::object_address(store), amount)
+    // cannot withdraw module account funds
+    let store_addr = object::object_address(&store);
+    assert!(
+        !is_module_account_store_addr(store_addr),
+        error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE)
+    );
+
+    withdraw_internal(object::object_address(&store), amount)
 }
 
-
- ## Function `deposit_with_ref` @@ -1752,27 +2362,30 @@ Deposit the fungible asset into the store ignoring frozen -Implementation +##### Implementation
public fun deposit_with_ref<T: key>(
-    ref: &TransferRef,
-    store: Object<T>,
-    fa: FungibleAsset
+    ref: &TransferRef, store: Object<T>, fa: FungibleAsset
 ) acquires FungibleStore {
     assert!(
         ref.metadata == fa.metadata,
         error::invalid_argument(ETRANSFER_REF_AND_FUNGIBLE_ASSET_MISMATCH)
     );
-    deposit_internal(store, fa);
+
+    // cannot deposit to blocked account
+    let store_addr = object::object_address(&store);
+    assert!(
+        !is_blocked_store_addr(store_addr),
+        error::invalid_argument(ECANNOT_DEPOSIT_TO_BLOCKED_ACCOUNT)
+    );
+
+    deposit_internal(object::object_address(&store), fa);
 }
 
- - ## Function `transfer_with_ref` @@ -1785,15 +2398,14 @@ Transfer amount of the fungible asset with transfer_with_ref<T: key>( transfer_ref: &TransferRef, from: Object<T>, to: Object<T>, - amount: u64, + amount: u64 ) acquires FungibleStore { let fa = withdraw_with_ref(transfer_ref, from, amount); deposit_with_ref(transfer_ref, to, fa); @@ -1802,341 +2414,292 @@ Transfer amount of the fungible asset with - +## Function `mutate_metadata` -## Function `zero` - -Create a fungible asset with zero amount. -This can be useful when starting a series of computations where the initial value is 0. +Mutate specified fields of the fungible asset's Metadata. -
public fun zero<T: key>(metadata: object::Object<T>): fungible_asset::FungibleAsset
+
public fun mutate_metadata(metadata_ref: &fungible_asset::MutateMetadataRef, name: option::Option<string::String>, symbol: option::Option<string::String>, decimals: option::Option<u8>, icon_uri: option::Option<string::String>, project_uri: option::Option<string::String>)
 
-
-Implementation +##### Implementation -
public fun zero<T: key>(metadata: Object<T>): FungibleAsset {
-    FungibleAsset {
-        metadata: object::convert(metadata),
-        amount: 0,
-    }
+
public fun mutate_metadata(
+    metadata_ref: &MutateMetadataRef,
+    name: Option<String>,
+    symbol: Option<String>,
+    decimals: Option<u8>,
+    icon_uri: Option<String>,
+    project_uri: Option<String>
+) acquires Metadata {
+    let metadata_address = object::object_address(&metadata_ref.metadata);
+    let mutable_metadata = borrow_global_mut<Metadata>(metadata_address);
+
+    if (option::is_some(&name)) {
+        mutable_metadata.name = option::extract(&mut name);
+    };
+    if (option::is_some(&symbol)) {
+        mutable_metadata.symbol = option::extract(&mut symbol);
+    };
+    if (option::is_some(&decimals)) {
+        mutable_metadata.decimals = option::extract(&mut decimals);
+    };
+    if (option::is_some(&icon_uri)) {
+        mutable_metadata.icon_uri = option::extract(&mut icon_uri);
+    };
+    if (option::is_some(&project_uri)) {
+        mutable_metadata.project_uri = option::extract(&mut project_uri);
+    };
 }
 
-
+ - +## Function `sudo_transfer` -## Function `extract` +Transfer an amount of fungible asset from from_store, which should be owned by sender, to receiver. +Note: it does not move the underlying object. -Extract a given amount from the given fungible asset and return a new one. +This function is only callable by the chain. -
public fun extract(fungible_asset: &mut fungible_asset::FungibleAsset, amount: u64): fungible_asset::FungibleAsset
+
public(friend) fun sudo_transfer<T: key>(sender: &signer, from: object::Object<T>, to: object::Object<T>, amount: u64)
 
-
-Implementation +##### Implementation -
public fun extract(fungible_asset: &mut FungibleAsset, amount: u64): FungibleAsset {
-    assert!(fungible_asset.amount >= amount, error::invalid_argument(EINSUFFICIENT_BALANCE));
-    fungible_asset.amount = fungible_asset.amount - amount;
-    FungibleAsset {
-        metadata: fungible_asset.metadata,
-        amount,
-    }
+
public(friend) fun sudo_transfer<T: key>(
+    sender: &signer,
+    from: Object<T>,
+    to: Object<T>,
+    amount: u64
+) acquires FungibleStore, DispatchFunctionStore {
+    let fa = withdraw(sender, from, amount);
+    sudo_deposit(to, fa);
 }
 
-
+ - +## Function `sudo_deposit` -## Function `merge` +Deposit amount of the fungible asset to store. -"Merges" the two given fungible assets. The fungible asset passed in as dst_fungible_asset will have a value -equal to the sum of the two (dst_fungible_asset and src_fungible_asset). +This function is only callable by the chain. -
public fun merge(dst_fungible_asset: &mut fungible_asset::FungibleAsset, src_fungible_asset: fungible_asset::FungibleAsset)
+
public(friend) fun sudo_deposit<T: key>(store: object::Object<T>, fa: fungible_asset::FungibleAsset)
 
-
-Implementation +##### Implementation -
public fun merge(dst_fungible_asset: &mut FungibleAsset, src_fungible_asset: FungibleAsset) {
-    let FungibleAsset { metadata, amount } = src_fungible_asset;
-    assert!(metadata == dst_fungible_asset.metadata, error::invalid_argument(EFUNGIBLE_ASSET_MISMATCH));
-    dst_fungible_asset.amount = dst_fungible_asset.amount + amount;
+
public(friend) fun sudo_deposit<T: key>(
+    store: Object<T>, fa: FungibleAsset
+) acquires FungibleStore {
+    assert!(
+        !is_frozen(store),
+        error::invalid_argument(ESTORE_IS_FROZEN)
+    );
+
+    deposit_internal(object::object_address(&store), fa);
 }
 
-
- - + -## Function `destroy_zero` +## Function `zero` -Destroy an empty fungible asset. +Create a fungible asset with zero amount. +This can be useful when starting a series of computations where the initial value is 0. -
public fun destroy_zero(fungible_asset: fungible_asset::FungibleAsset)
+
public fun zero<T: key>(metadata: object::Object<T>): fungible_asset::FungibleAsset
 
-
-Implementation +##### Implementation -
public fun destroy_zero(fungible_asset: FungibleAsset) {
-    let FungibleAsset { amount, metadata: _ } = fungible_asset;
-    assert!(amount == 0, error::invalid_argument(EAMOUNT_IS_NOT_ZERO));
+
public fun zero<T: key>(metadata: Object<T>): FungibleAsset {
+    FungibleAsset { metadata: object::convert(metadata), amount: 0 }
 }
 
-
- - + -## Function `deposit_internal` +## Function `extract` +Extract a given amount from the given fungible asset and return a new one. -
fun deposit_internal<T: key>(store: object::Object<T>, fa: fungible_asset::FungibleAsset)
+
public fun extract(fungible_asset: &mut fungible_asset::FungibleAsset, amount: u64): fungible_asset::FungibleAsset
 
-
-Implementation - - -
fun deposit_internal<T: key>(store: Object<T>, fa: FungibleAsset) acquires FungibleStore {
-    let FungibleAsset { metadata, amount } = fa;
-    if (amount == 0) return;
-
-    let store_metadata = store_metadata(store);
-    assert!(metadata == store_metadata, error::invalid_argument(EFUNGIBLE_ASSET_AND_STORE_MISMATCH));
-    let metadata_addr = object::object_address(store_metadata);
-    let store_addr = object::object_address(store);
-    let store = borrow_global_mut<FungibleStore>(store_addr);
-    store.balance = store.balance + amount;
+##### Implementation
 
 
-    // emit event
-    event::emit(DepositEvent { store_addr, metadata_addr, amount });
+
public fun extract(fungible_asset: &mut FungibleAsset, amount: u64): FungibleAsset {
+    assert!(
+        fungible_asset.amount >= amount,
+        error::invalid_argument(EINSUFFICIENT_BALANCE)
+    );
+    fungible_asset.amount = fungible_asset.amount - amount;
+    FungibleAsset { metadata: fungible_asset.metadata, amount }
 }
 
-
- - + -## Function `withdraw_internal` +## Function `merge` -Extract amount of the fungible asset from store. +"Merges" the two given fungible assets. The fungible asset passed in as dst_fungible_asset will have a value +equal to the sum of the two (dst_fungible_asset and src_fungible_asset). -
fun withdraw_internal(store_addr: address, amount: u64): fungible_asset::FungibleAsset
+
public fun merge(dst_fungible_asset: &mut fungible_asset::FungibleAsset, src_fungible_asset: fungible_asset::FungibleAsset)
 
-
-Implementation +##### Implementation -
fun withdraw_internal(
-    store_addr: address,
-    amount: u64,
-): FungibleAsset acquires FungibleStore {
-    let store = borrow_global_mut<FungibleStore>(store_addr);
-    let metadata = store.metadata;
-    if (amount == 0) return zero(metadata);
-
-    assert!(store.balance >= amount, error::invalid_argument(EINSUFFICIENT_BALANCE));
-    store.balance = store.balance - amount;
-
-    // emit event
-    let metadata_addr = object::object_address(metadata);
-    event::emit(WithdrawEvent { store_addr, metadata_addr, amount });
-
-    FungibleAsset { metadata, amount }
+
public fun merge(
+    dst_fungible_asset: &mut FungibleAsset, src_fungible_asset: FungibleAsset
+) {
+    let FungibleAsset { metadata, amount } = src_fungible_asset;
+    assert!(
+        metadata == dst_fungible_asset.metadata,
+        error::invalid_argument(EFUNGIBLE_ASSET_MISMATCH)
+    );
+    dst_fungible_asset.amount = dst_fungible_asset.amount + amount;
 }
 
-
- - + -## Function `increase_supply` +## Function `destroy_zero` -Increase the supply of a fungible asset by minting. +Destroy an empty fungible asset. -
fun increase_supply<T: key>(metadata: object::Object<T>, amount: u64)
+
public fun destroy_zero(fungible_asset: fungible_asset::FungibleAsset)
 
-
-Implementation - +##### Implementation -
fun increase_supply<T: key>(metadata: Object<T>, amount: u64) acquires Supply {
-    if (amount == 0) return;
 
-    let metadata_address = object::object_address(metadata);
-    assert!(exists<Supply>(metadata_address), error::not_found(ESUPPLY_NOT_FOUND));
-    let supply = borrow_global_mut<Supply>(metadata_address);
-    if (option::is_some(&supply.maximum)) {
-        let max = *option::borrow_mut(&mut supply.maximum);
-        assert!(
-            max - supply.current >= (amount as u128),
-            error::out_of_range(EMAX_SUPPLY_EXCEEDED)
-        )
-    };
-    supply.current = supply.current + (amount as u128);
+
public fun destroy_zero(fungible_asset: FungibleAsset) {
+    let FungibleAsset { amount, metadata: _ } = fungible_asset;
+    assert!(
+        amount == 0,
+        error::invalid_argument(EAMOUNT_IS_NOT_ZERO)
+    );
 }
 
-
- - + -## Function `decrease_supply` +## Function `deposit_internal` -Decrease the supply of a fungible asset by burning. -
fun decrease_supply<T: key>(metadata: object::Object<T>, amount: u64)
+
public(friend) fun deposit_internal(store_addr: address, fa: fungible_asset::FungibleAsset)
 
-
-Implementation - +##### Implementation -
fun decrease_supply<T: key>(metadata: Object<T>, amount: u64) acquires Supply {
-    if (amount == 0) return;
 
-    let metadata_address = object::object_address(metadata);
-    assert!(exists<Supply>(metadata_address), error::not_found(ESUPPLY_NOT_FOUND));
-    let supply = borrow_global_mut<Supply>(metadata_address);
+
public(friend) fun deposit_internal(
+    store_addr: address, fa: FungibleAsset
+) acquires FungibleStore {
+    let FungibleAsset { metadata, amount } = fa;
     assert!(
-        supply.current >= (amount as u128),
-        error::invalid_state(ESUPPLY_UNDERFLOW)
+        exists<FungibleStore>(store_addr),
+        error::not_found(EFUNGIBLE_STORE_EXISTENCE)
+    );
+    let store = borrow_global_mut<FungibleStore>(store_addr);
+    assert!(
+        metadata == store.metadata,
+        error::invalid_argument(EFUNGIBLE_ASSET_AND_STORE_MISMATCH)
     );
-    supply.current = supply.current - (amount as u128);
-}
-
- - - -
- - - -## Function `borrow_fungible_metadata` - - - -
fun borrow_fungible_metadata<T: key>(metadata: object::Object<T>): &fungible_asset::Metadata
-
- - -
-Implementation + if (amount == 0) return; + store.balance = store.balance + amount; -
inline fun borrow_fungible_metadata<T: key>(
-    metadata: Object<T>
-): &Metadata acquires Metadata {
-    let addr = object::object_address(metadata);
-    borrow_global<Metadata>(addr)
+    // emit event
+    let metadata_addr = object::object_address(&metadata);
+    event::emit(DepositEvent { store_addr, metadata_addr, amount });
 }
 
-
- - - -## Function `borrow_fungible_metadata_mut` - - - -
fun borrow_fungible_metadata_mut<T: key>(metadata: object::Object<T>): &mut fungible_asset::Metadata
-
- + +## Function `withdraw_internal` -
-Implementation +Extract amount of the fungible asset from store. -
inline fun borrow_fungible_metadata_mut<T: key>(
-    metadata: Object<T>
-): &mut Metadata acquires Metadata {
-    let addr = object::object_address(metadata);
-    borrow_global_mut<Metadata>(addr)
-}
+
public(friend) fun withdraw_internal(store_addr: address, amount: u64): fungible_asset::FungibleAsset
 
-
- - - -## Function `borrow_store_resource` - - - -
fun borrow_store_resource<T: key>(store: object::Object<T>): &fungible_asset::FungibleStore
-
+##### Implementation +
public(friend) fun withdraw_internal(
+    store_addr: address, amount: u64
+): FungibleAsset acquires FungibleStore {
+    let store = borrow_global_mut<FungibleStore>(store_addr);
+    let metadata = store.metadata;
+    if (amount == 0) return zero(metadata);
 
-
-Implementation + assert!( + store.balance >= amount, + error::invalid_argument(EINSUFFICIENT_BALANCE) + ); + store.balance = store.balance - amount; + // emit event + let metadata_addr = object::object_address(&metadata); + event::emit(WithdrawEvent { store_addr, metadata_addr, amount }); -
inline fun borrow_store_resource<T: key>(store: Object<T>): &FungibleStore acquires FungibleStore {
-    borrow_global<FungibleStore>(object::object_address(store))
+    FungibleAsset { metadata, amount }
 }
 
- - - -
diff --git a/initia_stdlib/doc/hex.md b/initia_stdlib/doc/hex.md index a598eef..348ce33 100644 --- a/initia_stdlib/doc/hex.md +++ b/initia_stdlib/doc/hex.md @@ -5,13 +5,55 @@ +- [Constants](#@Constants_0) - [Function `encode_to_string`](#0x1_hex_encode_to_string) +- [Function `encode_to_string_with_option`](#0x1_hex_encode_to_string_with_option) - [Function `decode_string`](#0x1_hex_decode_string) -- [Function `encode_to_char`](#0x1_hex_encode_to_char) -- [Function `decode_char`](#0x1_hex_decode_char) -
use 0x1::string;
+
use 0x1::error;
+use 0x1::string;
+
+ + + + + +## Constants + + + + + + +
const ENOT_HEXSTRING: u64 = 1;
+
+ + + + + + + +
const LOWERA: u8 = 97;
+
+ + + + + + + +
const UPPERA: u8 = 65;
+
+ + + + + + + +
const ZERO: u8 = 48;
 
@@ -27,15 +69,14 @@ -
-Implementation +##### Implementation
public fun encode_to_string(bz: &vector<u8>): String {
     let vec: vector<u8> = vector[];
     let len = vector::length(bz);
     let index = 0;
-    while(index < len) {
+    while (index < len) {
         let val = *vector::borrow(bz, index);
         let h = val / 0x10;
         let l = val % 0x10;
@@ -50,110 +91,88 @@
 
 
 
-
+ - - -## Function `decode_string` +## Function `encode_to_string_with_option` -
public fun decode_string(str: &string::String): vector<u8>
+
public fun encode_to_string_with_option(bz: &vector<u8>, is_upper: bool): string::String
 
-
-Implementation +##### Implementation -
public fun decode_string(str: &String): vector<u8> {
+
public fun encode_to_string_with_option(
+    bz: &vector<u8>, is_upper: bool
+): String {
     let vec: vector<u8> = vector[];
-
-    let bz = string::bytes(str);
     let len = vector::length(bz);
-    if (len == 0) {
-        return vec
-    };
-
-    let index = if (len % 2 == 1) {
-        let l = decode_char(*vector::borrow(bz, 0));
-        vector::push_back(&mut vec, l);
-
-        1
-    } else {
-        0
-    };
-
-    while(index < len) {
-        let h = decode_char(*vector::borrow(bz, index));
-        let l = decode_char(*vector::borrow(bz, index+1));
-
-        vector::push_back(&mut vec, l + (h << 4));
-
-        index = index + 2
+    let index = 0;
+    while (index < len) {
+        let val = *vector::borrow(bz, index);
+        vector::push_back(
+            &mut vec,
+            encode_to_char_with_option(val / 0x10, is_upper)
+        );
+        vector::push_back(
+            &mut vec,
+            encode_to_char_with_option(val % 0x10, is_upper)
+        );
+        index = index + 1;
     };
 
-    vec
+    string::utf8(vec)
 }
 
-
- - - -## Function `encode_to_char` - - - -
fun encode_to_char(num: u8): u8
-
- + +## Function `decode_string` -
-Implementation -
fun encode_to_char(num: u8): u8 {
-    if (num < 10) {
-        0x30 + num
-    } else {
-        0x57 + num
-    }
-}
+
public fun decode_string(str: &string::String): vector<u8>
 
-
- - - -## Function `decode_char` +##### Implementation +
public fun decode_string(str: &String): vector<u8> {
+    assert!(
+        is_hex_string(str),
+        error::invalid_argument(ENOT_HEXSTRING)
+    );
 
-
fun decode_char(num: u8): u8
-
+ let vec: vector<u8> = vector[]; + let bz = string::bytes(str); + let len = vector::length(bz); + if (len == 0) { + return vec + }; + let index = + if (len % 2 == 1) { + let l = decode_char(*vector::borrow(bz, 0)); + vector::push_back(&mut vec, l); + 1 + } else { 0 }; -
-Implementation + while (index < len) { + let h = decode_char(*vector::borrow(bz, index)); + let l = decode_char(*vector::borrow(bz, index + 1)); + vector::push_back(&mut vec, (h << 4) + l); + index = index + 2 + }; -
fun decode_char(num: u8): u8 {
-    if (num < 0x3a) {
-        num - 0x30
-    } else {
-        num - 0x57
-    }
+    vec
 }
 
- - - -
diff --git a/initia_stdlib/doc/initia_nft.md b/initia_stdlib/doc/initia_nft.md index fcbe35d..ccac1b7 100644 --- a/initia_stdlib/doc/initia_nft.md +++ b/initia_stdlib/doc/initia_nft.md @@ -21,30 +21,24 @@ The key features are: - [Function `create_collection_object`](#0x1_initia_nft_create_collection_object) - [Function `mint`](#0x1_initia_nft_mint) - [Function `mint_nft_object`](#0x1_initia_nft_mint_nft_object) -- [Function `mint_internal`](#0x1_initia_nft_mint_internal) -- [Function `borrow`](#0x1_initia_nft_borrow) - [Function `is_mutable_description`](#0x1_initia_nft_is_mutable_description) - [Function `is_mutable_uri`](#0x1_initia_nft_is_mutable_uri) -- [Function `authorized_borrow`](#0x1_initia_nft_authorized_borrow) - [Function `burn`](#0x1_initia_nft_burn) - [Function `set_description`](#0x1_initia_nft_set_description) - [Function `set_uri`](#0x1_initia_nft_set_uri) -- [Function `collection_object`](#0x1_initia_nft_collection_object) -- [Function `borrow_collection`](#0x1_initia_nft_borrow_collection) - [Function `is_mutable_collection_description`](#0x1_initia_nft_is_mutable_collection_description) - [Function `is_mutable_collection_royalty`](#0x1_initia_nft_is_mutable_collection_royalty) - [Function `is_mutable_collection_uri`](#0x1_initia_nft_is_mutable_collection_uri) - [Function `is_mutable_collection_nft_description`](#0x1_initia_nft_is_mutable_collection_nft_description) - [Function `is_mutable_collection_nft_uri`](#0x1_initia_nft_is_mutable_collection_nft_uri) -- [Function `authorized_borrow_collection`](#0x1_initia_nft_authorized_borrow_collection) - [Function `set_collection_description`](#0x1_initia_nft_set_collection_description) - [Function `set_collection_royalties`](#0x1_initia_nft_set_collection_royalties) - [Function `set_collection_royalties_call`](#0x1_initia_nft_set_collection_royalties_call) - [Function `set_collection_uri`](#0x1_initia_nft_set_collection_uri) -
use 0x1::collection;
-use 0x1::decimal128;
+
use 0x1::bigdecimal;
+use 0x1::collection;
 use 0x1::error;
 use 0x1::nft;
 use 0x1::object;
@@ -68,8 +62,7 @@ Storage state for managing the no-code Collection.
 
 
 
-
-Fields +##### Fields
@@ -112,8 +105,6 @@ Storage state for managing the no-code Collection.
-
- ## Resource `InitiaNft` @@ -126,8 +117,7 @@ Storage state for managing the no-code Nft. -
-Fields +##### Fields
@@ -146,8 +136,6 @@ Storage state for managing the no-code Nft.
-
- ## Constants @@ -220,13 +208,12 @@ The provided signer is not the owner Create a new collection -
public entry fun create_collection(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_uri: bool, royalty: decimal128::Decimal128)
+
public entry fun create_collection(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_uri: bool, royalty: bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation
public entry fun create_collection(
@@ -240,7 +227,7 @@ Create a new collection
     mutable_uri: bool,
     mutable_nft_description: bool,
     mutable_nft_uri: bool,
-    royalty: Decimal128,
+    royalty: BigDecimal
 ) {
     create_collection_object(
         creator,
@@ -253,28 +240,25 @@ Create a new collection
         mutable_uri,
         mutable_nft_description,
         mutable_nft_uri,
-        royalty,
+        royalty
     );
 }
 
-
- ## Function `create_collection_object` -
public fun create_collection_object(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_uri: bool, royalty: decimal128::Decimal128): (object::Object<initia_nft::InitiaNftCollection>, object::ExtendRef)
+
public fun create_collection_object(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_uri: bool, royalty: bigdecimal::BigDecimal): (object::Object<initia_nft::InitiaNftCollection>, object::ExtendRef)
 
-
-Implementation +##### Implementation
public fun create_collection_object(
@@ -288,41 +272,48 @@ Create a new collection
     mutable_uri: bool,
     mutable_nft_description: bool,
     mutable_nft_uri: bool,
-    royalty: Decimal128,
+    royalty: BigDecimal
 ): (Object<InitiaNftCollection>, ExtendRef) {
     let creator_addr = signer::address_of(creator);
     let royalty = royalty::create(royalty, creator_addr);
-    let constructor_ref = if (option::is_some(&max_supply)) {
-        collection::create_fixed_collection(
-            creator,
-            description,
-            option::extract(&mut max_supply),
-            name,
-            option::some(royalty),
-            uri,
-        )
-    } else {
-        collection::create_unlimited_collection(
-            creator,
-            description,
-            name,
-            option::some(royalty),
-            uri,
-        )
-    };
+    let constructor_ref =
+        if (option::is_some(&max_supply)) {
+            collection::create_fixed_collection(
+                creator,
+                description,
+                option::extract(&mut max_supply),
+                name,
+                option::some(royalty),
+                uri
+            )
+        } else {
+            collection::create_unlimited_collection(
+                creator,
+                description,
+                name,
+                option::some(royalty),
+                uri
+            )
+        };
 
     let object_signer = object::generate_signer(&constructor_ref);
-    let mutator_ref = if (mutable_description || mutable_uri) {
-        option::some(collection::generate_mutator_ref(&constructor_ref))
-    } else {
-        option::none()
-    };
-
-    let royalty_mutator_ref = if (mutable_royalty) {
-        option::some(royalty::generate_mutator_ref(object::generate_extend_ref(&constructor_ref)))
-    } else {
-        option::none()
-    };
+    let mutator_ref =
+        if (mutable_description || mutable_uri) {
+            option::some(collection::generate_mutator_ref(&constructor_ref))
+        } else {
+            option::none()
+        };
+
+    let royalty_mutator_ref =
+        if (mutable_royalty) {
+            option::some(
+                royalty::generate_mutator_ref(
+                    object::generate_extend_ref(&constructor_ref)
+                )
+            )
+        } else {
+            option::none()
+        };
 
     let extend_ref = object::generate_extend_ref(&constructor_ref);
 
@@ -332,7 +323,7 @@ Create a new collection
         mutable_description,
         mutable_uri,
         mutable_nft_description,
-        mutable_nft_uri,
+        mutable_nft_uri
     };
     move_to(&object_signer, initia_nft_collection);
     (object::object_from_constructor_ref(&constructor_ref), extend_ref)
@@ -341,8 +332,6 @@ Create a new collection
 
 
 
-
- ## Function `mint` @@ -355,8 +344,7 @@ With an existing collection, directly mint a viable nft into the creators accoun -
-Implementation +##### Implementation
public entry fun mint(
@@ -366,19 +354,29 @@ With an existing collection, directly mint a viable nft into the creators accoun
     token_id: String,
     uri: String,
     can_burn: bool,
-    to: Option<address>,
+    to: Option<address>
 ) acquires InitiaNftCollection {
-    let (nft_object, _) = mint_nft_object(creator, collection, description, token_id, uri, can_burn);
+    let (nft_object, _) =
+        mint_nft_object(
+            creator,
+            collection,
+            description,
+            token_id,
+            uri,
+            can_burn
+        );
     if (option::is_some(&to)) {
-        object::transfer(creator, nft_object, option::extract(&mut to));
+        object::transfer(
+            creator,
+            nft_object,
+            option::extract(&mut to)
+        );
     }
 }
 
-
- ## Function `mint_nft_object` @@ -391,8 +389,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun mint_nft_object(
@@ -401,121 +398,25 @@ Mint a nft into an existing collection, and retrieve the object / address of the
     description: String,
     token_id: String,
     uri: String,
-    can_burn: bool,
+    can_burn: bool
 ): (Object<InitiaNft>, ExtendRef) acquires InitiaNftCollection {
-    let constructor_ref = mint_internal(
-        creator,
-        collection,
-        description,
-        token_id,
-        uri,
-        can_burn,
-    );
-    let extend_ref = object::generate_extend_ref(&constructor_ref);
-
-    (object::object_from_constructor_ref(&constructor_ref), extend_ref)
-}
-
- - - -
- - - -## Function `mint_internal` - - - -
fun mint_internal(creator: &signer, collection: string::String, description: string::String, token_id: string::String, uri: string::String, can_burn: bool): object::ConstructorRef
-
- - - -
-Implementation - - -
fun mint_internal(
-    creator: &signer,
-    collection: String,
-    description: String,
-    token_id: String,
-    uri: String,
-    can_burn: bool,
-): ConstructorRef acquires InitiaNftCollection {
-    let constructor_ref = nft::create(
+    let constructor_ref =
+        mint_internal(
             creator,
             collection,
             description,
             token_id,
-            option::none(),
             uri,
+            can_burn
         );
+    let extend_ref = object::generate_extend_ref(&constructor_ref);
 
-    let object_signer = object::generate_signer(&constructor_ref);
-
-    let collection_obj = collection_object(creator, &collection);
-    let collection = borrow_collection(collection_obj);
-
-    let mutator_ref = if (
-        collection.mutable_nft_description
-            || collection.mutable_nft_uri
-    ) {
-        option::some(nft::generate_mutator_ref(&constructor_ref))
-    } else {
-        option::none()
-    };
-
-    let burn_ref = if (can_burn) {
-        option::some(nft::generate_burn_ref(&constructor_ref))
-    } else {
-        option::none()
-    };
-
-    let initia_nft = InitiaNft {
-        burn_ref,
-        mutator_ref,
-    };
-    move_to(&object_signer, initia_nft);
-
-    constructor_ref
-}
-
- - - -
- - - -## Function `borrow` - - - -
fun borrow<T: key>(nft: object::Object<T>): &initia_nft::InitiaNft
-
- - - -
-Implementation - - -
inline fun borrow<T: key>(nft: Object<T>): &InitiaNft {
-    let nft_address = object::object_address(nft);
-    assert!(
-        exists<InitiaNft>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-    borrow_global<InitiaNft>(nft_address)
+    (object::object_from_constructor_ref(&constructor_ref), extend_ref)
 }
 
-
- ## Function `is_mutable_description` @@ -528,8 +429,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_description<T: key>(nft: Object<T>): bool acquires InitiaNftCollection {
@@ -539,8 +439,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_uri` @@ -553,8 +451,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_uri<T: key>(nft: Object<T>): bool acquires InitiaNftCollection {
@@ -564,42 +461,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- - - -## Function `authorized_borrow` - - - -
fun authorized_borrow<T: key>(nft: object::Object<T>, creator: &signer): &initia_nft::InitiaNft
-
- - - -
-Implementation - - -
inline fun authorized_borrow<T: key>(nft: Object<T>, creator: &signer): &InitiaNft {
-    let nft_address = object::object_address(nft);
-    assert!(
-        exists<InitiaNft>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-
-    assert!(
-        nft::creator(nft) == signer::address_of(creator),
-        error::permission_denied(ENOT_CREATOR),
-    );
-    borrow_global<InitiaNft>(nft_address)
-}
-
- - - -
- ## Function `burn` @@ -611,35 +472,32 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun burn<T: key>(owner: &signer, nft: Object<T>) acquires InitiaNft {
-    let nft_address = object::object_address(nft);
+    let nft_address = object::object_address(&nft);
     assert!(
         exists<InitiaNft>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
+        error::not_found(ENFT_DOES_NOT_EXIST)
     );
     assert!(
         object::owns(nft, signer::address_of(owner)),
-        error::permission_denied(ENOT_OWNER),
+        error::permission_denied(ENOT_OWNER)
     );
 
-    let initia_nft = move_from<InitiaNft>(object::object_address(nft));
-    assert!(option::is_some(&initia_nft.burn_ref), error::invalid_state(ECAN_NOT_BURN));
-    let InitiaNft {
-        burn_ref,
-        mutator_ref: _,
-    } = initia_nft;
+    let initia_nft = move_from<InitiaNft>(object::object_address(&nft));
+    assert!(
+        option::is_some(&initia_nft.burn_ref),
+        error::invalid_state(ECAN_NOT_BURN)
+    );
+    let InitiaNft { burn_ref, mutator_ref: _ } = initia_nft;
     nft::burn(option::extract(&mut burn_ref));
 }
 
-
- ## Function `set_description` @@ -651,28 +509,26 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_description<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    description: String,
+    creator: &signer, nft: Object<T>, description: String
 ) acquires InitiaNftCollection, InitiaNft {
     assert!(
         is_mutable_description(nft),
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
     );
     let initia_nft = authorized_borrow(nft, creator);
-    nft::set_description(option::borrow(&initia_nft.mutator_ref), description);
+    nft::set_description(
+        option::borrow(&initia_nft.mutator_ref),
+        description
+    );
 }
 
-
- ## Function `set_uri` @@ -684,18 +540,15 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_uri<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    uri: String,
+    creator: &signer, nft: Object<T>, uri: String
 ) acquires InitiaNftCollection, InitiaNft {
     assert!(
         is_mutable_uri(nft),
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
     );
     let initia_nft = authorized_borrow(nft, creator);
     nft::set_uri(option::borrow(&initia_nft.mutator_ref), uri);
@@ -704,62 +557,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- - - -## Function `collection_object` - - - -
fun collection_object(creator: &signer, name: &string::String): object::Object<initia_nft::InitiaNftCollection>
-
- - - -
-Implementation - - -
inline fun collection_object(creator: &signer, name: &String): Object<InitiaNftCollection> {
-    let collection_addr = collection::create_collection_address(signer::address_of(creator), name);
-    object::address_to_object<InitiaNftCollection>(collection_addr)
-}
-
- - - -
- - - -## Function `borrow_collection` - - - -
fun borrow_collection<T: key>(nft: object::Object<T>): &initia_nft::InitiaNftCollection
-
- - - -
-Implementation - - -
inline fun borrow_collection<T: key>(nft: Object<T>): &InitiaNftCollection {
-    let collection_address = object::object_address(nft);
-    assert!(
-        exists<InitiaNftCollection>(collection_address),
-        error::not_found(ECOLLECTION_DOES_NOT_EXIST),
-    );
-    borrow_global<InitiaNftCollection>(collection_address)
-}
-
- - - -
- ## Function `is_mutable_collection_description` @@ -771,12 +568,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_description<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires InitiaNftCollection {
     borrow_collection(collection).mutable_description
 }
@@ -784,8 +580,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_royalty` @@ -797,12 +591,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_royalty<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires InitiaNftCollection {
     option::is_some(&borrow_collection(collection).royalty_mutator_ref)
 }
@@ -810,8 +603,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_uri` @@ -823,12 +614,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_uri<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires InitiaNftCollection {
     borrow_collection(collection).mutable_uri
 }
@@ -836,8 +626,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_nft_description` @@ -849,12 +637,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_description<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires InitiaNftCollection {
     borrow_collection(collection).mutable_nft_description
 }
@@ -862,8 +649,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_nft_uri` @@ -875,12 +660,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_uri<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires InitiaNftCollection {
     borrow_collection(collection).mutable_nft_uri
 }
@@ -888,41 +672,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- - - -## Function `authorized_borrow_collection` - - - -
fun authorized_borrow_collection<T: key>(collection: object::Object<T>, creator: &signer): &initia_nft::InitiaNftCollection
-
- - - -
-Implementation - - -
inline fun authorized_borrow_collection<T: key>(collection: Object<T>, creator: &signer): &InitiaNftCollection {
-    let collection_address = object::object_address(collection);
-    assert!(
-        exists<InitiaNftCollection>(collection_address),
-        error::not_found(ECOLLECTION_DOES_NOT_EXIST),
-    );
-    assert!(
-        collection::creator(collection) == signer::address_of(creator),
-        error::permission_denied(ENOT_CREATOR),
-    );
-    borrow_global<InitiaNftCollection>(collection_address)
-}
-
- - - -
- ## Function `set_collection_description` @@ -934,28 +683,26 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_collection_description<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    description: String,
+    creator: &signer, collection: Object<T>, description: String
 ) acquires InitiaNftCollection {
     let initia_nft_collection = authorized_borrow_collection(collection, creator);
     assert!(
         initia_nft_collection.mutable_description,
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
+    );
+    collection::set_description(
+        option::borrow(&initia_nft_collection.mutator_ref),
+        description
     );
-    collection::set_description(option::borrow(&initia_nft_collection.mutator_ref), description);
 }
 
-
- ## Function `set_collection_royalties` @@ -967,48 +714,45 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun set_collection_royalties<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    royalty: royalty::Royalty,
+    creator: &signer, collection: Object<T>, royalty: royalty::Royalty
 ) acquires InitiaNftCollection {
     let initia_nft_collection = authorized_borrow_collection(collection, creator);
     assert!(
         option::is_some(&initia_nft_collection.royalty_mutator_ref),
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
+    );
+    royalty::update(
+        option::borrow(&initia_nft_collection.royalty_mutator_ref),
+        royalty
     );
-    royalty::update(option::borrow(&initia_nft_collection.royalty_mutator_ref), royalty);
 }
 
-
- ## Function `set_collection_royalties_call` -
public fun set_collection_royalties_call<T: key>(creator: &signer, collection: object::Object<T>, royalty: decimal128::Decimal128, payee_address: address)
+
public fun set_collection_royalties_call<T: key>(creator: &signer, collection: object::Object<T>, royalty: bigdecimal::BigDecimal, payee_address: address)
 
-
-Implementation +##### Implementation
public fun set_collection_royalties_call<T: key>(
     creator: &signer,
     collection: Object<T>,
-    royalty: Decimal128,
-    payee_address: address,
+    royalty: BigDecimal,
+    payee_address: address
 ) acquires InitiaNftCollection {
     let royalty = royalty::create(royalty, payee_address);
     set_collection_royalties(creator, collection, royalty);
@@ -1017,8 +761,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `set_collection_uri` @@ -1030,24 +772,20 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_collection_uri<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    uri: String,
+    creator: &signer, collection: Object<T>, uri: String
 ) acquires InitiaNftCollection {
     let initia_nft_collection = authorized_borrow_collection(collection, creator);
     assert!(
         initia_nft_collection.mutable_uri,
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
+    );
+    collection::set_uri(
+        option::borrow(&initia_nft_collection.mutator_ref),
+        uri
     );
-    collection::set_uri(option::borrow(&initia_nft_collection.mutator_ref), uri);
 }
 
- - - -
diff --git a/initia_stdlib/doc/json.md b/initia_stdlib/doc/json.md index 39789ce..9d4de2a 100644 --- a/initia_stdlib/doc/json.md +++ b/initia_stdlib/doc/json.md @@ -5,2027 +5,79 @@ -- [Struct `JsonIndex`](#0x1_json_JsonIndex) -- [Struct `JsonElem`](#0x1_json_JsonElem) -- [Struct `JsonObject`](#0x1_json_JsonObject) -- [Struct `Number`](#0x1_json_Number) -- [Struct `JsonValue`](#0x1_json_JsonValue) -- [Struct `NativeArrayValue`](#0x1_json_NativeArrayValue) -- [Struct `NativeObjectValue`](#0x1_json_NativeObjectValue) -- [Struct `KeyValue`](#0x1_json_KeyValue) -- [Constants](#@Constants_0) -- [Function `empty`](#0x1_json_empty) -- [Function `data`](#0x1_json_data) -- [Function `stringify`](#0x1_json_stringify) -- [Function `stringify_internal`](#0x1_json_stringify_internal) -- [Function `parse`](#0x1_json_parse) -- [Function `parse_internal`](#0x1_json_parse_internal) -- [Function `start_index`](#0x1_json_start_index) -- [Function `get_next_index`](#0x1_json_get_next_index) -- [Function `get_prev_index`](#0x1_json_get_prev_index) -- [Function `get_index_last`](#0x1_json_get_index_last) -- [Function `get_depth`](#0x1_json_get_depth) -- [Function `borrow`](#0x1_json_borrow) -- [Function `borrow_mut`](#0x1_json_borrow_mut) -- [Function `find`](#0x1_json_find) -- [Function `is_null_index`](#0x1_json_is_null_index) -- [Function `set_elem`](#0x1_json_set_elem) -- [Function `set_bool`](#0x1_json_set_bool) -- [Function `set_number`](#0x1_json_set_number) -- [Function `set_int_raw`](#0x1_json_set_int_raw) -- [Function `set_int_string`](#0x1_json_set_int_string) -- [Function `set_dec_string`](#0x1_json_set_dec_string) -- [Function `set_string`](#0x1_json_set_string) -- [Function `set_array`](#0x1_json_set_array) -- [Function `set_object`](#0x1_json_set_object) -- [Function `new_bool`](#0x1_json_new_bool) -- [Function `new_number`](#0x1_json_new_number) -- [Function `new_int`](#0x1_json_new_int) -- [Function `new_dec`](#0x1_json_new_dec) -- [Function `new_string`](#0x1_json_new_string) -- [Function `new_array`](#0x1_json_new_array) -- [Function `new_object`](#0x1_json_new_object) -- [Function `is_null`](#0x1_json_is_null) -- [Function `is_bool`](#0x1_json_is_bool) -- [Function `is_number`](#0x1_json_is_number) -- [Function `is_string`](#0x1_json_is_string) -- [Function `is_array`](#0x1_json_is_array) -- [Function `is_object`](#0x1_json_is_object) -- [Function `as_bool`](#0x1_json_as_bool) -- [Function `as_number`](#0x1_json_as_number) -- [Function `as_int`](#0x1_json_as_int) -- [Function `as_dec`](#0x1_json_as_dec) -- [Function `as_string`](#0x1_json_as_string) -- [Function `unpack_elem`](#0x1_json_unpack_elem) -- [Function `get_child_length`](#0x1_json_get_child_length) -- [Function `set_child_length`](#0x1_json_set_child_length) -- [Function `get_type`](#0x1_json_get_type) -- [Function `parse_bool`](#0x1_json_parse_bool) -- [Function `parse_number`](#0x1_json_parse_number) -- [Function `parse_string`](#0x1_json_parse_string) -- [Function `parse_array`](#0x1_json_parse_array) -- [Function `parse_object`](#0x1_json_parse_object) -- [Function `stringify_bool`](#0x1_json_stringify_bool) -- [Function `stringify_number`](#0x1_json_stringify_number) -- [Function `stringify_string`](#0x1_json_stringify_string) -- [Function `stringify_array`](#0x1_json_stringify_array) -- [Function `stringify_object`](#0x1_json_stringify_object) +- [Function `marshal`](#0x1_json_marshal) +- [Function `marshal_to_string`](#0x1_json_marshal_to_string) +- [Function `unmarshal`](#0x1_json_unmarshal) -
use 0x1::decimal256;
-use 0x1::error;
-use 0x1::option;
-use 0x1::simple_map;
-use 0x1::string;
-use 0x1::vector;
+
use 0x1::string;
 
- + -## Struct `JsonIndex` +## Function `marshal` +Marshal data to JSON bytes. +NOTE: key _type_ is converted to @type +NOTE: key _move_ is converted to move -
struct JsonIndex has copy, drop, store
-
- - - -
-Fields - - -
-
-data: vector<u64> -
-
- -
-
- - -
- - - -## Struct `JsonElem` - - - -
struct JsonElem has copy, drop, store
-
- - - -
-Fields - - -
-
-key: option::Option<string::String> -
-
- -
-
-value: json::JsonValue -
-
- -
-
- - -
- - - -## Struct `JsonObject` - - - -
struct JsonObject has copy, drop
-
- - - -
-Fields - - -
-
-data: simple_map::SimpleMap<json::JsonIndex, json::JsonElem> -
-
- -
-
- - -
- - - -## Struct `Number` - - - -
struct Number has copy, drop, store
-
- - - -
-Fields - - -
-
-type: u8 -
-
- -
-
-value: u256 -
-
- -
-
-is_positive: bool -
-
- -
-
- - -
- - - -## Struct `JsonValue` - - - -
struct JsonValue has copy, drop, store
-
- - - -
-Fields - - -
-
-type: u8 -
-
- -
-
-value_bool: option::Option<bool> -
-
- -
-
-value_number: option::Option<json::Number> -
-
- -
-
-value_string: option::Option<string::String> -
-
- -
-
-child_length: u64 -
-
- -
-
- - -
- - - -## Struct `NativeArrayValue` - - - -
struct NativeArrayValue has copy, drop, store
-
- - - -
-Fields - - -
-
-type: u8 -
-
- -
-
-value: string::String -
-
- -
-
- - -
- - - -## Struct `NativeObjectValue` - - - -
struct NativeObjectValue has copy, drop, store
-
- - - -
-Fields - - -
-
-type: u8 -
-
- -
-
-key: string::String -
-
- -
-
-value: string::String -
-
- -
-
- - -
- - - -## Struct `KeyValue` - - - -
struct KeyValue has copy, drop, store
-
- - - -
-Fields - - -
-
-key: string::String -
-
- -
-
-value: string::String -
-
- -
-
- - -
- - - -## Constants - - - - - - -
const EKEY_NOT_FOUND: u64 = 7;
-
- - - - - - - -
const EOUT_OF_RANGE: u64 = 3;
-
- - - - - - - -
const EDUPLICATED_INDEX: u64 = 5;
-
- - - - - - - -
const EINVALID_ARGS: u64 = 2;
-
- - - - - - - -
const ENOT_SUPPORTED_TYPE: u64 = 6;
-
- - - - - - - -
const ESERDE_DESERIALIZE: u64 = 1;
-
- - - - - - - -
const ETYPE_MISMATCH: u64 = 4;
-
- - - - - - - -
const JSON_VALUE_TYPE_ARRAY: u8 = 4;
-
- - - - - - - -
const JSON_VALUE_TYPE_BOOL: u8 = 1;
-
- - - - - - - -
const JSON_VALUE_TYPE_NULL: u8 = 0;
-
- - - - - - - -
const JSON_VALUE_TYPE_NUMBER: u8 = 2;
-
- - - - - - - -
const JSON_VALUE_TYPE_OBJECT: u8 = 5;
-
- - - - - - - -
const JSON_VALUE_TYPE_STRING: u8 = 3;
-
- - - - - - - -
const JSON_VALUE_TYPE_UNKNOWN: u8 = 255;
-
- - - - - - - -
const NUMBER_TYPE_DEC: u8 = 1;
-
- - - - - - - -
const NUMBER_TYPE_INT: u8 = 0;
-
- - - - - -## Function `empty` - - - -
public fun empty(): json::JsonObject
-
- - - -
-Implementation - - -
public fun empty(): JsonObject{
-    JsonObject {
-        data: simple_map::create<JsonIndex, JsonElem>(),
-    }
-}
-
- - - -
- - - -## Function `data` - - - -
public fun data(json_obj: &json::JsonObject): &simple_map::SimpleMap<json::JsonIndex, json::JsonElem>
-
- - - -
-Implementation - - -
public fun data(json_obj: &JsonObject): &SimpleMap<JsonIndex, JsonElem>{
-    &json_obj.data
-}
-
- - - -
- - - -## Function `stringify` - - - -
public fun stringify(json_obj: &json::JsonObject): string::String
-
- - - -
-Implementation - - -
public fun stringify(json_obj: &JsonObject): String {
-    let index = start_index();
-    let (_, json_string) = stringify_internal(json_obj, index);
-    json_string
-}
-
- - - -
- - - -## Function `stringify_internal` - - - -
fun stringify_internal(json_obj: &json::JsonObject, current_index: json::JsonIndex): (option::Option<string::String>, string::String)
-
- - - -
-Implementation - - -
fun stringify_internal(json_obj: &JsonObject, current_index: JsonIndex): (Option<String>, String) {
-    let json_elem = borrow(json_obj, ¤t_index);
-    let type = json_elem.value.type;
-
-    assert!(type != JSON_VALUE_TYPE_NULL, ENOT_SUPPORTED_TYPE);
-
-    if(type == JSON_VALUE_TYPE_BOOL) {
-        (json_elem.key, stringify_bool(as_bool(json_elem.value)))
-    } else if(type == JSON_VALUE_TYPE_NUMBER) {
-        (json_elem.key, stringify_number(as_number(json_elem.value)))
-    } else if(type == JSON_VALUE_TYPE_STRING) {
-        (json_elem.key, stringify_string(as_string(json_elem.value)))
-    } else if(type == JSON_VALUE_TYPE_ARRAY) {
-        let values = vector::empty<String>();
-        let i =0;
-        while(i < json_elem.value.child_length) {
-            let next_index = get_next_index(¤t_index, i);
-            let (_, value) = stringify_internal(json_obj, next_index);
-            vector::push_back(&mut values, value);
-            i = i + 1;
-        };
-        (json_elem.key, stringify_array(values))
-    } else if(type == JSON_VALUE_TYPE_OBJECT) {
-        let values = vector::empty<KeyValue>();
-        let i =0;
-        while(i < json_elem.value.child_length) {
-            let next_index = get_next_index(¤t_index, i);
-            let (key, value) = stringify_internal(json_obj, next_index);
-            vector::push_back(&mut values, KeyValue{
-                key: *option::borrow(&key),
-                value: value,
-            });
-            i = i + 1;
-        };
-        (json_elem.key, stringify_object(values))
-    } else {
-        abort(ENOT_SUPPORTED_TYPE)
-    }
-}
-
- - - -
- - - -## Function `parse` - - - -
public fun parse(json_string: string::String): json::JsonObject
-
- - - -
-Implementation - - -
public fun parse(json_string: String): JsonObject {
-    let json_obj = empty();
-    let index = start_index();
-    let type = get_type(&json_string);
-    parse_internal(&mut json_obj, type, option::none<String>(),json_string, index);
-
-    json_obj
-}
-
- - - -
- - - -## Function `parse_internal` - - - -
fun parse_internal(json_obj: &mut json::JsonObject, type: u8, key: option::Option<string::String>, json_string: string::String, current_index: json::JsonIndex)
-
- - - -
-Implementation - - -
fun parse_internal(json_obj: &mut JsonObject, type: u8, key: Option<String>, json_string: String, current_index: JsonIndex) {
-    assert!(type != JSON_VALUE_TYPE_NULL, ENOT_SUPPORTED_TYPE);
-
-    if(type == JSON_VALUE_TYPE_BOOL) {
-        set_bool(json_obj, current_index, key, parse_bool(json_string));
-    } else if(type == JSON_VALUE_TYPE_NUMBER) {
-        set_number(json_obj, current_index, key, parse_number(json_string));
-    } else if(type == JSON_VALUE_TYPE_STRING) {
-        let string_value = parse_string(json_string);
-        // number can be wrapped into string (e.g. "\"12.3456\"" -> "12.3456")
-        let type = get_type(&string_value);
-        if(type == JSON_VALUE_TYPE_NUMBER){
-            set_number(json_obj, current_index, key, parse_number(string_value));
-        } else {
-            set_string(json_obj, current_index, key, string_value);
-        }
-    } else if(type == JSON_VALUE_TYPE_ARRAY) {
-        let value = parse_array(json_string);
-        vector::reverse(&mut value);
-        let len = vector::length(&value);
-
-        set_array(json_obj, current_index, key, len);
-
-        let i = 0;
-        while( i < len) {
-            let array_value = vector::pop_back(&mut value);
-            let index = get_next_index(¤t_index, i);
-            parse_internal(json_obj, array_value.type, option::none<String>(), array_value.value, index);
-            i = i + 1;
-        };
-    } else if(type == JSON_VALUE_TYPE_OBJECT) {
-        let value = parse_object(json_string);
-        vector::reverse(&mut value);
-        let len = vector::length(&value);
-
-        set_object(json_obj, current_index, key, len);
-
-        let i = 0;
-        while( i < len) {
-            let object_value = vector::pop_back(&mut value);
-            let index = get_next_index(¤t_index, i);
-            parse_internal(json_obj, object_value.type, option::some(object_value.key), object_value.value, index);
-            i = i + 1;
-        };
-    } else {
-        abort(ENOT_SUPPORTED_TYPE)
-    };
-}
-
- - - -
- - - -## Function `start_index` - - - -
public fun start_index(): json::JsonIndex
-
- - - -
-Implementation - - -
public fun start_index(): JsonIndex  {
-    JsonIndex {
-        data: vector::singleton<u64>(0)
-    }
-}
-
- - - -
- - - -## Function `get_next_index` - - - -
public fun get_next_index(current: &json::JsonIndex, idx: u64): json::JsonIndex
-
- - - -
-Implementation - - -
public fun get_next_index(current: &JsonIndex, idx: u64): JsonIndex  {
-    let index = *current;
-    vector::push_back(&mut index.data, idx);
-    index
-}
-
- - - -
- - - -## Function `get_prev_index` - - - -
public fun get_prev_index(current: &json::JsonIndex): (json::JsonIndex, u64)
-
- - - -
-Implementation - - -
public fun get_prev_index(current: &JsonIndex): (JsonIndex, u64) {
-    let index = *current;
-    let last = vector::pop_back(&mut index.data);
-    (index, last)
-}
-
- - - -
- - - -## Function `get_index_last` - - - -
public fun get_index_last(index: &json::JsonIndex): u64
-
- - - -
-Implementation - - -
public fun get_index_last(index: &JsonIndex): u64 {
-    let length = vector::length(&index.data);
-    *vector::borrow(&index.data, length-1)
-}
-
- - - -
- - - -## Function `get_depth` - - - -
public fun get_depth(index: &json::JsonIndex): u64
-
- - - -
-Implementation - - -
public fun get_depth(index: &JsonIndex): u64 {
-    vector::length(&index.data)
-}
-
- - - -
- - - -## Function `borrow` - - - -
public fun borrow(obj: &json::JsonObject, index: &json::JsonIndex): &json::JsonElem
-
- - - -
-Implementation - - -
public fun borrow(obj: &JsonObject, index: &JsonIndex): &JsonElem{
-    simple_map::borrow(&obj.data, index)
-}
-
- - - -
- - - -## Function `borrow_mut` - - - -
public fun borrow_mut(obj: &mut json::JsonObject, index: &json::JsonIndex): &mut json::JsonElem
-
- - - -
-Implementation - - -
public fun borrow_mut(obj: &mut JsonObject, index: &JsonIndex): &mut JsonElem{
-    simple_map::borrow_mut(&mut obj.data, index)
-}
-
- - - -
- - - -## Function `find` - - - -
public fun find(obj: &json::JsonObject, index: &json::JsonIndex, key: &string::String): json::JsonIndex
-
- - - -
-Implementation - - -
public fun find(obj: &JsonObject, index: &JsonIndex, key: &String): JsonIndex {
-    let i = 0;
-    let elem = borrow(obj, index);
-
-    while (i < elem.value.child_length) {
-        let next_index = get_next_index(index, i);
-        let child_elem = borrow(obj, &next_index);
-        if ( *string::bytes(option::borrow(&child_elem.key)) == *string::bytes(key)) {
-            break
-        };
-        i = i + 1;
-    };
-
-    if( i >= elem.value.child_length) {
-        JsonIndex {
-            data: vector::empty(),
-        }
-    } else {
-        get_next_index(index, i)
-    }
-}
-
- - - -
- - - -## Function `is_null_index` - - - -
public fun is_null_index(index: &json::JsonIndex): bool
-
- - - -
-Implementation - - -
public fun is_null_index(index: &JsonIndex): bool {
-    if( vector::length(&index.data) == 0) {
-        true
-    } else {
-        false
-    }
-}
-
- - - -
- - - -## Function `set_elem` - - - -
fun set_elem(object: &mut json::JsonObject, index: json::JsonIndex, elem: json::JsonElem)
-
- - - -
-Implementation - - -
fun set_elem(object: &mut JsonObject, index: JsonIndex, elem: JsonElem) {
-    assert!(!simple_map::contains_key(&object.data, &index), EDUPLICATED_INDEX);
-    simple_map::add(&mut object.data, index, elem);
-}
-
- - - -
- - - -## Function `set_bool` - - - -
public fun set_bool(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, value: bool)
-
- - - -
-Implementation - - -
public fun set_bool(object: &mut JsonObject, index: JsonIndex, key: Option<String>, value: bool) {
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_bool(value),
-    });
-}
-
- - - -
- - - -## Function `set_number` - - - -
fun set_number(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, value: json::Number)
-
- - - -
-Implementation - - -
fun set_number(object: &mut JsonObject, index: JsonIndex, key: Option<String>, value: Number) {
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_number(value),
-    });
-}
-
- - - -
- - - -## Function `set_int_raw` - - - -
public fun set_int_raw(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, is_positive: bool, value: u256)
-
- - - -
-Implementation - - -
public fun set_int_raw(object:&mut JsonObject, index: JsonIndex, key: Option<String>, is_positive: bool, value: u256) {
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_int(is_positive, value),
-    });
-}
-
- - - -
- - - -## Function `set_int_string` - - - -
public fun set_int_string(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, is_positive: bool, value: u256)
-
- - - -
-Implementation - - -
public fun set_int_string(object:&mut JsonObject, index: JsonIndex, key: Option<String>, is_positive: bool, value: u256) {
-    let int_number = new_int(is_positive, value);
-    let int_string = stringify_number(as_number(int_number));
-
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_string(int_string),
-    });
-}
-
- - - -
- - - -## Function `set_dec_string` - - - -
public fun set_dec_string(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, is_positive: bool, value: decimal256::Decimal256)
-
- - - -
-Implementation - - -
public fun set_dec_string(object:&mut JsonObject, index: JsonIndex, key: Option<String>, is_positive: bool, value: Decimal256) {
-    let dec_number = new_dec(is_positive, value);
-    let dec_string = stringify_number(as_number(dec_number));
-
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_string(dec_string),
-    });
-}
-
- - - -
- - - -## Function `set_string` - - - -
public fun set_string(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, value: string::String)
-
- - - -
-Implementation - - -
public fun set_string(object: &mut JsonObject, index: JsonIndex, key: Option<String>, value: String) {
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_string(value),
-    });
-}
-
- - - -
- - - -## Function `set_array` - - - -
public fun set_array(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, child_length: u64)
-
- - - -
-Implementation - - -
public fun set_array(object: &mut JsonObject, index: JsonIndex, key: Option<String>, child_length: u64) {
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_array(child_length),
-    });
-}
-
- - - -
- - - -## Function `set_object` - - - -
public fun set_object(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, child_length: u64)
-
- - - -
-Implementation - - -
public fun set_object(object: &mut JsonObject, index: JsonIndex, key: Option<String>, child_length: u64) {
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_object(child_length),
-    });
-}
-
- - - -
- - - -## Function `new_bool` - - - -
public fun new_bool(value: bool): json::JsonValue
-
- - - -
-Implementation - - -
public fun new_bool(value: bool): JsonValue {
-    JsonValue {
-        type: JSON_VALUE_TYPE_BOOL,
-        value_bool: option::some<bool>(value),
-        value_number: option::none<Number>(),
-        value_string: option::none<String>(),
-        child_length: 0,
-    }
-}
-
- - - -
- - - -## Function `new_number` - - - -
fun new_number(value: json::Number): json::JsonValue
-
- - - -
-Implementation - - -
fun new_number(value: Number): JsonValue {
-    JsonValue {
-        type: JSON_VALUE_TYPE_NUMBER,
-        value_bool: option::none<bool>(),
-        value_number: option::some<Number>(value),
-        value_string: option::none<String>(),
-        child_length: 0,
-    }
-}
-
- - - -
- - - -## Function `new_int` - - - -
public fun new_int(is_positive: bool, value: u256): json::JsonValue
-
- - - -
-Implementation - - -
public fun new_int(is_positive: bool, value:u256): JsonValue {
-    new_number(Number {
-        type: NUMBER_TYPE_INT,
-        value: value,
-        is_positive,
-    })
-}
-
- - - -
- - - -## Function `new_dec` - - - -
public fun new_dec(is_positive: bool, value: decimal256::Decimal256): json::JsonValue
-
- - - -
-Implementation - - -
public fun new_dec(is_positive: bool, value:Decimal256): JsonValue {
-    new_number(Number {
-        type: NUMBER_TYPE_DEC,
-        value: decimal256::val(&value),
-        is_positive,
-    })
-}
-
- - - -
- - - -## Function `new_string` - - - -
public fun new_string(value: string::String): json::JsonValue
-
- - - -
-Implementation - - -
public fun new_string(value: String): JsonValue {
-    JsonValue {
-        type: JSON_VALUE_TYPE_STRING,
-        value_bool: option::none<bool>(),
-        value_number: option::none<Number>(),
-        value_string: option::some<String>(value),
-        child_length: 0,
-    }
-}
-
- - - -
- - - -## Function `new_array` - - - -
public fun new_array(length: u64): json::JsonValue
-
- - - -
-Implementation - - -
public fun new_array(length: u64): JsonValue {
-    JsonValue {
-        type: JSON_VALUE_TYPE_ARRAY,
-        value_bool: option::none<bool>(),
-        value_number: option::none<Number>(),
-        value_string: option::none<String>(),
-        child_length: length,
-    }
-}
-
- - - -
- - - -## Function `new_object` - - - -
public fun new_object(length: u64): json::JsonValue
-
- - - -
-Implementation - - -
public fun new_object(length: u64): JsonValue {
-    JsonValue {
-        type: JSON_VALUE_TYPE_OBJECT,
-        value_bool: option::none<bool>(),
-        value_number: option::none<Number>(),
-        value_string: option::none<String>(),
-        child_length: length,
-    }
-}
-
- - - -
- - - -## Function `is_null` - - - -
public fun is_null(json_string: &string::String): bool
-
- - - -
-Implementation - - -
public fun is_null(json_string: &String): bool {
-    get_type(json_string) == JSON_VALUE_TYPE_NULL
-}
-
- - - -
- - - -## Function `is_bool` - - - -
public fun is_bool(json_string: &string::String): bool
-
- - - -
-Implementation - - -
public fun is_bool(json_string: &String): bool {
-    get_type(json_string) == JSON_VALUE_TYPE_BOOL
-}
-
- - - -
- - - -## Function `is_number` - - - -
public fun is_number(json_string: &string::String): bool
-
- - - -
-Implementation - - -
public fun is_number(json_string: &String): bool {
-    get_type(json_string) == JSON_VALUE_TYPE_NUMBER
-}
-
- - - -
- - - -## Function `is_string` - - - -
public fun is_string(json_string: &string::String): bool
-
- - - -
-Implementation - - -
public fun is_string(json_string: &String): bool {
-    get_type(json_string) == JSON_VALUE_TYPE_STRING
-}
-
- - - -
- - - -## Function `is_array` - - - -
public fun is_array(json_string: &string::String): bool
-
- - - -
-Implementation - - -
public fun is_array(json_string: &String): bool {
-    get_type(json_string) == JSON_VALUE_TYPE_ARRAY
-}
-
- - - -
- - - -## Function `is_object` - - - -
public fun is_object(json_string: &string::String): bool
-
- - -
-Implementation - - -
public fun is_object(json_string: &String): bool {
-    get_type(json_string) == JSON_VALUE_TYPE_OBJECT
-}
-
- - - -
- - - -## Function `as_bool` - - - -
public fun as_bool(json_value: json::JsonValue): bool
-
- - - -
-Implementation - - -
public fun as_bool(json_value: JsonValue): bool {
-    assert!(json_value.type == JSON_VALUE_TYPE_BOOL, ETYPE_MISMATCH);
-    *option::borrow(&json_value.value_bool)
-}
-
- - - -
- - - -## Function `as_number` - - - -
fun as_number(json_value: json::JsonValue): json::Number
-
- - - -
-Implementation - - -
fun as_number(json_value: JsonValue): Number {
-    assert!(json_value.type == JSON_VALUE_TYPE_NUMBER, ETYPE_MISMATCH);
-    *option::borrow(&json_value.value_number)
-}
-
- - - -
- - - -## Function `as_int` - - - -
public fun as_int(json_value: json::JsonValue): (bool, u256)
-
- - - -
-Implementation - - -
public fun as_int(json_value: JsonValue): (bool, u256) {// (signed, abs_val)
-    let number = as_number(json_value);
-    assert!(number.type == NUMBER_TYPE_INT, error::invalid_argument(ETYPE_MISMATCH));
-    (number.is_positive, number.value)
-}
-
- - - -
- - - -## Function `as_dec` - - - -
public fun as_dec(json_value: json::JsonValue): (bool, decimal256::Decimal256)
-
- - - -
-Implementation - - -
public fun as_dec(json_value: JsonValue): (bool, Decimal256) {// (signed, abs_val)
-    let number = as_number(json_value);
-    assert!(number.type == NUMBER_TYPE_DEC, error::invalid_argument(ETYPE_MISMATCH));
-    (number.is_positive, decimal256::new(number.value))
-}
-
- - - -
- - - -## Function `as_string` - - - -
public fun as_string(json_value: json::JsonValue): string::String
-
- - - -
-Implementation - - -
public fun as_string(json_value: JsonValue): String {
-    assert!(json_value.type == JSON_VALUE_TYPE_STRING, ETYPE_MISMATCH);
-    *option::borrow(&json_value.value_string)
-}
-
- - - -
- - - -## Function `unpack_elem` - - - -
public fun unpack_elem(elem: &json::JsonElem): (option::Option<string::String>, json::JsonValue)
-
- - - -
-Implementation - - -
public fun unpack_elem(elem: &JsonElem): (Option<String>, JsonValue) {
-    (elem.key, elem.value)
-}
-
- - - -
- - - -## Function `get_child_length` - - - -
public(friend) fun get_child_length(elem: &json::JsonElem): u64
-
- - - -
-Implementation - - -
public(friend) fun get_child_length(elem: &JsonElem): u64 {
-    elem.value.child_length
-}
-
- - - -
- - - -## Function `set_child_length` - - - -
public(friend) fun set_child_length(elem: &mut json::JsonElem, length: u64)
-
- - - -
-Implementation - - -
public(friend) fun set_child_length(elem: &mut JsonElem, length: u64) {
-    elem.value.child_length = length;
-}
-
- - - -
- - - -## Function `get_type` - - - -
public fun get_type(value: &string::String): u8
-
- - - -
-Implementation - - -
public native fun get_type(value: &String): u8;
-
- - - -
- - - -## Function `parse_bool` - - - -
fun parse_bool(value: string::String): bool
-
- - - -
-Implementation - - -
native fun parse_bool(value: String): bool;
-
- - - -
- - - -## Function `parse_number` - - - -
fun parse_number(value: string::String): json::Number
-
- - - -
-Implementation - - -
native fun parse_number(value: String): Number;
-
- - - -
- - - -## Function `parse_string` - - - -
fun parse_string(value: string::String): string::String
-
- - - -
-Implementation - - -
native fun parse_string(value: String): String;
-
- - - -
- - - -## Function `parse_array` - - - -
fun parse_array(value: string::String): vector<json::NativeArrayValue>
-
- - - -
-Implementation - - -
native fun parse_array(value: String): vector<NativeArrayValue>;
-
- - - -
- - - -## Function `parse_object` - - - -
fun parse_object(value: string::String): vector<json::NativeObjectValue>
-
- - - -
-Implementation - - -
native fun parse_object(value: String): vector<NativeObjectValue>;
-
- - - -
- - - -## Function `stringify_bool` - - - -
fun stringify_bool(value: bool): string::String
-
- - - -
-Implementation - - -
native fun stringify_bool(value: bool): String;
-
- - - -
- - - -## Function `stringify_number` - - - -
fun stringify_number(value: json::Number): string::String
-
- - - -
-Implementation - - -
native fun stringify_number(value: Number): String;
-
- - - -
- - - -## Function `stringify_string` - - - -
fun stringify_string(value: string::String): string::String
+
public fun marshal<T: drop>(value: &T): vector<u8>
 
-
-Implementation +##### Implementation -
native fun stringify_string(value: String): String;
+
native public fun marshal<T: drop>(value: &T): vector<u8>;
 
-
+ - +## Function `marshal_to_string` -## Function `stringify_array` +Marshal data to JSON string. +NOTE: key _type_ is converted to @type +NOTE: key _move_ is converted to move -
fun stringify_array(value: vector<string::String>): string::String
+
public fun marshal_to_string<T: drop>(value: &T): string::String
 
-
-Implementation +##### Implementation -
native fun stringify_array(value: vector<String>): String;
+
native public fun marshal_to_string<T: drop>(value: &T): String;
 
-
+ - +## Function `unmarshal` -## Function `stringify_object` +Unmarshal JSON bytes to the given struct. +NOTE: key @type is converted to _type_ +NOTE: key move is converted to _move_ -
fun stringify_object(value: vector<json::KeyValue>): string::String
+
public fun unmarshal<T: drop>(json: vector<u8>): T
 
-
-Implementation +##### Implementation -
native fun stringify_object(value: vector<KeyValue>): String;
+
native public fun unmarshal<T: drop>(json: vector<u8>): T;
 
- - - -
diff --git a/initia_stdlib/doc/keccak.md b/initia_stdlib/doc/keccak.md new file mode 100644 index 0000000..e1b4f62 --- /dev/null +++ b/initia_stdlib/doc/keccak.md @@ -0,0 +1,36 @@ + + + +# Module `0x1::keccak` + +Cryptographic hashes: +- Keccak-256: see https://keccak.team/keccak.html + +In addition, SHA2-256 and SHA3-256 are available in std::hash. Note that SHA3-256 is a variant of Keccak: it is +NOT the same as Keccak-256. + + +- [Function `keccak256`](#0x1_keccak_keccak256) + + +
+ + + + + +## Function `keccak256` + +Returns the Keccak-256 hash of bytes. + + +
public fun keccak256(byte: vector<u8>): vector<u8>
+
+ + + +##### Implementation + + +
native public fun keccak256(byte: vector<u8>): vector<u8>;
+
diff --git a/initia_stdlib/doc/managed_coin.md b/initia_stdlib/doc/managed_coin.md index 50748ed..892ff61 100644 --- a/initia_stdlib/doc/managed_coin.md +++ b/initia_stdlib/doc/managed_coin.md @@ -10,9 +10,11 @@ By utilizing this current module, a developer can create his own coin and care l - [Resource `Capabilities`](#0x1_managed_coin_Capabilities) - [Constants](#@Constants_0) +- [Function `sudo_mint`](#0x1_managed_coin_sudo_mint) - [Function `initialize`](#0x1_managed_coin_initialize) - [Function `burn`](#0x1_managed_coin_burn) - [Function `mint`](#0x1_managed_coin_mint) +- [Function `mint_to`](#0x1_managed_coin_mint_to)
use 0x1::coin;
@@ -39,8 +41,7 @@ The resource is stored on the account that initialized coin CoinType
-Fields
+##### Fields
 
 
 
@@ -65,8 +66,6 @@ The resource is stored on the account that initialized coin CoinType - - ## Constants @@ -92,6 +91,49 @@ Metadata has no capabilities (burn/mint). + + +## Function `sudo_mint` + +Create new metadata coins and deposit them into dst_addr's account. + + +
public entry fun sudo_mint(account: &signer, dst_addr: address, metadata: object::Object<fungible_asset::Metadata>, amount: u64)
+
+ + + +##### Implementation + + +
public entry fun sudo_mint(
+    account: &signer,
+    dst_addr: address,
+    metadata: Object<Metadata>,
+    amount: u64
+) acquires Capabilities {
+    check_sudo(account);
+
+    let account_addr = signer::address_of(account);
+    assert!(
+        object::is_owner(metadata, account_addr),
+        error::not_found(EUNAUTHORIZED)
+    );
+
+    let object_addr = object::object_address(&metadata);
+    assert!(
+        exists<Capabilities>(object_addr),
+        error::not_found(ENO_CAPABILITIES)
+    );
+
+    let capabilities = borrow_global<Capabilities>(object_addr);
+    let fa = coin::mint(&capabilities.mint_cap, amount);
+    coin::sudo_deposit(dst_addr, fa);
+}
+
+ + + ## Function `initialize` @@ -105,8 +147,7 @@ Mint and Burn Capabilities will be stored under metadata in < -
-Implementation +##### Implementation
public entry fun initialize(
@@ -116,31 +157,29 @@ Mint and Burn Capabilities will be stored under metadata in <
     symbol: String,
     decimals: u8,
     icon_uri: String,
-    project_uri: String,
+    project_uri: String
 ) {
-    let (mint_cap, burn_cap, freeze_cap, extend_ref) = coin::initialize_and_generate_extend_ref (
-        account,
-        maximum_supply,
-        name,
-        symbol,
-        decimals,
-        icon_uri,
-        project_uri,
-    );
+    let (mint_cap, burn_cap, freeze_cap, extend_ref) =
+        coin::initialize_and_generate_extend_ref(
+            account,
+            maximum_supply,
+            name,
+            symbol,
+            decimals,
+            icon_uri,
+            project_uri
+        );
 
     let metadata_signer = object::generate_signer_for_extending(&extend_ref);
-    move_to(&metadata_signer, Capabilities {
-        mint_cap,
-        burn_cap,
-        freeze_cap,
-    });
+    move_to(
+        &metadata_signer,
+        Capabilities { mint_cap, burn_cap, freeze_cap }
+    );
 }
 
-
- ## Function `burn` @@ -153,26 +192,23 @@ Withdraw an amount of metadata coin from burn( - account: &signer, - metadata: Object<Metadata>, - amount: u64, + account: &signer, metadata: Object<Metadata>, amount: u64 ) acquires Capabilities { let account_addr = signer::address_of(account); assert!( object::is_owner(metadata, account_addr), - error::not_found(EUNAUTHORIZED), + error::not_found(EUNAUTHORIZED) ); - let object_addr = object::object_address(metadata); + let object_addr = object::object_address(&metadata); assert!( exists<Capabilities>(object_addr), - error::not_found(ENO_CAPABILITIES), + error::not_found(ENO_CAPABILITIES) ); let capabilities = borrow_global<Capabilities>(object_addr); @@ -184,48 +220,67 @@ Withdraw an amount of metadata coin from ## Function `mint` -Create new metadata coins and deposit them into dst_addr's account. +Create new metadata coins. -
public entry fun mint(account: &signer, dst_addr: address, metadata: object::Object<fungible_asset::Metadata>, amount: u64)
+
public fun mint(account: &signer, metadata: object::Object<fungible_asset::Metadata>, amount: u64): fungible_asset::FungibleAsset
 
-
-Implementation +##### Implementation -
public entry fun mint(
-    account: &signer,
-    dst_addr: address,
-    metadata: Object<Metadata>,
-    amount: u64,
-) acquires Capabilities {
+
public fun mint(
+    account: &signer, metadata: Object<Metadata>, amount: u64
+): FungibleAsset acquires Capabilities {
     let account_addr = signer::address_of(account);
 
     assert!(
         object::is_owner(metadata, account_addr),
-        error::not_found(EUNAUTHORIZED),
+        error::not_found(EUNAUTHORIZED)
     );
 
-    let object_addr = object::object_address(metadata);
+    let object_addr = object::object_address(&metadata);
     assert!(
         exists<Capabilities>(object_addr),
-        error::not_found(ENO_CAPABILITIES),
+        error::not_found(ENO_CAPABILITIES)
     );
 
     let capabilities = borrow_global<Capabilities>(object_addr);
-    coin::mint_to(&capabilities.mint_cap, dst_addr, amount);
+    coin::mint(&capabilities.mint_cap, amount)
 }
 
-
+ + +## Function `mint_to` + +Create new metadata coins and deposit them into dst_addr's account. + + +
public entry fun mint_to(account: &signer, dst_addr: address, metadata: object::Object<fungible_asset::Metadata>, amount: u64)
+
+ + + +##### Implementation + + +
public entry fun mint_to(
+    account: &signer,
+    dst_addr: address,
+    metadata: Object<Metadata>,
+    amount: u64
+) acquires Capabilities {
+    let fa = mint(account, metadata, amount);
+
+    coin::deposit(dst_addr, fa);
+}
+
diff --git a/initia_stdlib/doc/math128.md b/initia_stdlib/doc/math128.md index 73bf758..c625ed3 100644 --- a/initia_stdlib/doc/math128.md +++ b/initia_stdlib/doc/math128.md @@ -63,8 +63,7 @@ Return the largest of two numbers. -
-Implementation +##### Implementation
public fun max(a: u128, b: u128): u128 {
@@ -74,8 +73,6 @@ Return the largest of two numbers.
 
 
 
-
- ## Function `min` @@ -88,8 +85,7 @@ Return the smallest of two numbers. -
-Implementation +##### Implementation
public fun min(a: u128, b: u128): u128 {
@@ -99,8 +95,6 @@ Return the smallest of two numbers.
 
 
 
-
- ## Function `average` @@ -113,8 +107,7 @@ Return the average of two. -
-Implementation +##### Implementation
public fun average(a: u128, b: u128): u128 {
@@ -128,8 +121,6 @@ Return the average of two.
 
 
 
-
- ## Function `mul_div` @@ -142,8 +133,7 @@ Returns a * b / c going through u128 to prevent intermediate overflow -
-Implementation +##### Implementation
public fun mul_div(a: u128, b: u128, c: u128): u128 {
@@ -153,8 +143,6 @@ Returns a * b / c going through u128 to prevent intermediate overflow
 
 
 
-
- ## Function `clamp` @@ -167,8 +155,7 @@ Return x clamped to the interval [lower, upper]. -
-Implementation +##### Implementation
public fun clamp(x: u128, lower: u128, upper: u128): u128 {
@@ -178,8 +165,6 @@ Return x clamped to the interval [lower, upper].
 
 
 
-
- ## Function `pow` @@ -192,14 +177,12 @@ Return the value of n raised to power e -
-Implementation +##### Implementation
public fun pow(n: u128, e: u128): u128 {
-    if (e == 0) {
-        1
-    } else {
+    if (e == 0) { 1 }
+    else {
         let p = 1;
         while (e > 1) {
             if (e % 2 == 1) {
@@ -215,8 +198,6 @@ Return the value of n raised to power e
 
 
 
-
- ## Function `floor_log2` @@ -229,13 +210,15 @@ Returns floor(log2(x)) -
-Implementation +##### Implementation
public fun floor_log2(x: u128): u8 {
     let res = 0;
-    assert!(x != 0, std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2));
+    assert!(
+        x != 0,
+        std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2)
+    );
     // Effectively the position of the most significant set bit
     let n = 64;
     while (n > 0) {
@@ -251,8 +234,6 @@ Returns floor(log2(x))
 
 
 
-
- ## Function `log2` @@ -264,8 +245,7 @@ Returns floor(log2(x)) -
-Implementation +##### Implementation
public fun log2(x: u128): FixedPoint32 {
@@ -284,17 +264,18 @@ Returns floor(log2(x))
         x = (x * x) >> 32;
         // x is now in [1, 4)
         // if x in [2, 4) then log x = 1 + log (x / 2)
-        if (x >= (2 << 32)) { frac = frac + delta; x = x >> 1; };
+        if (x >= (2 << 32)) {
+            frac = frac + delta;
+            x = x >> 1;
+        };
         delta = delta >> 1;
     };
-    fixed_point32::create_from_raw_value (((integer_part as u64) << 32) + frac)
+    fixed_point32::create_from_raw_value(((integer_part as u64) << 32) + frac)
 }
 
-
- ## Function `log2_64` @@ -306,8 +287,7 @@ Returns floor(log2(x)) -
-Implementation +##### Implementation
public fun log2_64(x: u128): FixedPoint64 {
@@ -326,17 +306,18 @@ Returns floor(log2(x))
         x = (x * x) >> 63;
         // x is now in [1, 4)
         // if x in [2, 4) then log x = 1 + log (x / 2)
-        if (x >= (2 << 63)) { frac = frac + delta; x = x >> 1; };
+        if (x >= (2 << 63)) {
+            frac = frac + delta;
+            x = x >> 1;
+        };
         delta = delta >> 1;
     };
-    fixed_point64::create_from_raw_value (((integer_part as u128) << 64) + frac)
+    fixed_point64::create_from_raw_value(((integer_part as u128) << 64) + frac)
 }
 
-
- ## Function `sqrt` @@ -349,8 +330,7 @@ Returns square root of x, precisely floor(sqrt(x)) -
-Implementation +##### Implementation
public fun sqrt(x: u128): u128 {
@@ -375,8 +355,6 @@ Returns square root of x, precisely floor(sqrt(x))
 
 
 
-
- ## Function `ceil_div` @@ -388,8 +366,7 @@ Returns square root of x, precisely floor(sqrt(x)) -
-Implementation +##### Implementation
public fun ceil_div(x: u128, y: u128): u128 {
@@ -398,11 +375,6 @@ Returns square root of x, precisely floor(sqrt(x))
     if (x == 0) {
         assert!(y != 0, EDIVISION_BY_ZERO);
         0
-    }
-    else (x - 1) / y + 1
+    } else (x - 1) / y + 1
 }
 
- - - -
diff --git a/initia_stdlib/doc/math64.md b/initia_stdlib/doc/math64.md index b9884bb..6d866ba 100644 --- a/initia_stdlib/doc/math64.md +++ b/initia_stdlib/doc/math64.md @@ -34,7 +34,7 @@ Standard math utilities missing in the Move Language. -
const EDIVISION_BY_ZERO: u64 = 1;
+
const EDIVISION_BY_ZERO: u64 = 2;
 
@@ -61,8 +61,7 @@ Return the largest of two numbers. -
-Implementation +##### Implementation
public fun max(a: u64, b: u64): u64 {
@@ -72,8 +71,6 @@ Return the largest of two numbers.
 
 
 
-
- ## Function `min` @@ -86,8 +83,7 @@ Return the smallest of two numbers. -
-Implementation +##### Implementation
public fun min(a: u64, b: u64): u64 {
@@ -97,8 +93,6 @@ Return the smallest of two numbers.
 
 
 
-
- ## Function `average` @@ -111,8 +105,7 @@ Return the average of two. -
-Implementation +##### Implementation
public fun average(a: u64, b: u64): u64 {
@@ -126,8 +119,6 @@ Return the average of two.
 
 
 
-
- ## Function `mul_div` @@ -140,8 +131,7 @@ Returns a * b / c going through u128 to prevent intermediate overflow -
-Implementation +##### Implementation
public fun mul_div(a: u64, b: u64, c: u64): u64 {
@@ -151,8 +141,6 @@ Returns a * b / c going through u128 to prevent intermediate overflow
 
 
 
-
- ## Function `clamp` @@ -165,8 +153,7 @@ Return x clamped to the interval [lower, upper]. -
-Implementation +##### Implementation
public fun clamp(x: u64, lower: u64, upper: u64): u64 {
@@ -176,8 +163,6 @@ Return x clamped to the interval [lower, upper].
 
 
 
-
- ## Function `pow` @@ -190,14 +175,12 @@ Return the value of n raised to power e -
-Implementation +##### Implementation
public fun pow(n: u64, e: u64): u64 {
-    if (e == 0) {
-        1
-    } else {
+    if (e == 0) { 1 }
+    else {
         let p = 1;
         while (e > 1) {
             if (e % 2 == 1) {
@@ -213,8 +196,6 @@ Return the value of n raised to power e
 
 
 
-
- ## Function `floor_log2` @@ -227,13 +208,15 @@ Returns floor(lg2(x)) -
-Implementation +##### Implementation
public fun floor_log2(x: u64): u8 {
     let res = 0;
-    assert!(x != 0, std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2));
+    assert!(
+        x != 0,
+        std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2)
+    );
     // Effectively the position of the most significant set bit
     let n = 32;
     while (n > 0) {
@@ -249,8 +232,6 @@ Returns floor(lg2(x))
 
 
 
-
- ## Function `log2` @@ -262,18 +243,19 @@ Returns floor(lg2(x)) -
-Implementation +##### Implementation
public fun log2(x: u64): FixedPoint32 {
     let integer_part = floor_log2(x);
     // Normalize x to [1, 2) in fixed point 32.
-    let y = (if (x >= 1 << 32) {
-        x >> (integer_part - 32)
-    } else {
-        x << (32 - integer_part)
-    } as u128);
+    let y = (
+        if (x >= 1 << 32) {
+            x >> (integer_part - 32)
+        } else {
+            x << (32 - integer_part)
+        } as u128
+    );
     let frac = 0;
     let delta = 1 << 31;
     while (delta != 0) {
@@ -282,17 +264,18 @@ Returns floor(lg2(x))
         y = (y * y) >> 32;
         // x is now in [1, 4)
         // if x in [2, 4) then log x = 1 + log (x / 2)
-        if (y >= (2 << 32)) { frac = frac + delta; y = y >> 1; };
+        if (y >= (2 << 32)) {
+            frac = frac + delta;
+            y = y >> 1;
+        };
         delta = delta >> 1;
     };
-    fixed_point32::create_from_raw_value (((integer_part as u64) << 32) + frac)
+    fixed_point32::create_from_raw_value(((integer_part as u64) << 32) + frac)
 }
 
-
- ## Function `sqrt` @@ -305,8 +288,7 @@ Returns square root of x, precisely floor(sqrt(x)) -
-Implementation +##### Implementation
public fun sqrt(x: u64): u64 {
@@ -330,8 +312,6 @@ Returns square root of x, precisely floor(sqrt(x))
 
 
 
-
- ## Function `ceil_div` @@ -343,8 +323,7 @@ Returns square root of x, precisely floor(sqrt(x)) -
-Implementation +##### Implementation
public fun ceil_div(x: u64, y: u64): u64 {
@@ -353,11 +332,6 @@ Returns square root of x, precisely floor(sqrt(x))
     if (x == 0) {
         assert!(y != 0, EDIVISION_BY_ZERO);
         0
-    }
-    else (x - 1) / y + 1
+    } else (x - 1) / y + 1
 }
 
- - - -
diff --git a/initia_stdlib/doc/minitswap.md b/initia_stdlib/doc/minitswap.md index e10d74f..3617bc6 100644 --- a/initia_stdlib/doc/minitswap.md +++ b/initia_stdlib/doc/minitswap.md @@ -7,65 +7,106 @@ - [Resource `ModuleStore`](#0x1_minitswap_ModuleStore) - [Resource `VirtualPool`](#0x1_minitswap_VirtualPool) +- [Struct `Pools`](#0x1_minitswap_Pools) +- [Struct `UnbondEntity`](#0x1_minitswap_UnbondEntity) +- [Struct `ArbInfo`](#0x1_minitswap_ArbInfo) +- [Struct `CreatePoolEvent`](#0x1_minitswap_CreatePoolEvent) +- [Struct `ChangePoolSizeEvent`](#0x1_minitswap_ChangePoolSizeEvent) +- [Struct `UpdatePoolParamsEvent`](#0x1_minitswap_UpdatePoolParamsEvent) - [Struct `ProvideEvent`](#0x1_minitswap_ProvideEvent) -- [Struct `WithdrawEvent`](#0x1_minitswap_WithdrawEvent) +- [Struct `UnbondEvent`](#0x1_minitswap_UnbondEvent) +- [Struct `WithdrawUnbondEvent`](#0x1_minitswap_WithdrawUnbondEvent) - [Struct `SwapEvent`](#0x1_minitswap_SwapEvent) -- [Struct `RebalanceEvent`](#0x1_minitswap_RebalanceEvent) +- [Struct `CreateStableswapPoolEvent`](#0x1_minitswap_CreateStableswapPoolEvent) +- [Struct `InitiateArbEvent`](#0x1_minitswap_InitiateArbEvent) +- [Struct `FinalizeArbEvent`](#0x1_minitswap_FinalizeArbEvent) +- [Struct `RevertArbEvent`](#0x1_minitswap_RevertArbEvent) +- [Struct `UnbondResponse`](#0x1_minitswap_UnbondResponse) +- [Struct `ArbResponse`](#0x1_minitswap_ArbResponse) +- [Struct `ModuleStoreResponse`](#0x1_minitswap_ModuleStoreResponse) +- [Struct `PoolsResponse`](#0x1_minitswap_PoolsResponse) +- [Struct `PoolsDetailResponse`](#0x1_minitswap_PoolsDetailResponse) +- [Struct `VirtualPoolDetail`](#0x1_minitswap_VirtualPoolDetail) +- [Struct `IBCMemo`](#0x1_minitswap_IBCMemo) +- [Struct `MemoMove`](#0x1_minitswap_MemoMove) +- [Struct `MemoAsyncCallback`](#0x1_minitswap_MemoAsyncCallback) +- [Struct `MemoMoveMessage`](#0x1_minitswap_MemoMoveMessage) +- [Struct `MemoWasm`](#0x1_minitswap_MemoWasm) +- [Struct `MemoWasmMessage`](#0x1_minitswap_MemoWasmMessage) +- [Struct `MemoWasmFunds`](#0x1_minitswap_MemoWasmFunds) +- [Struct `MemoWasmMinitswapHook`](#0x1_minitswap_MemoWasmMinitswapHook) +- [Struct `MemoWasmMinitswapHookMsg`](#0x1_minitswap_MemoWasmMinitswapHookMsg) +- [Struct `FinalizeTokenWithdrawalRequest`](#0x1_minitswap_FinalizeTokenWithdrawalRequest) +- [Struct `CosmosCoin`](#0x1_minitswap_CosmosCoin) - [Constants](#@Constants_0) -- [Function `init_module`](#0x1_minitswap_init_module) - [Function `get_pool_amount`](#0x1_minitswap_get_pool_amount) - [Function `get_pool_amount_by_denom`](#0x1_minitswap_get_pool_amount_by_denom) - [Function `get_peg_keeper_balance`](#0x1_minitswap_get_peg_keeper_balance) - [Function `get_peg_keeper_balance_by_denom`](#0x1_minitswap_get_peg_keeper_balance_by_denom) - [Function `swap_simulation`](#0x1_minitswap_swap_simulation) +- [Function `swap_simulation_given_out`](#0x1_minitswap_swap_simulation_given_out) - [Function `swap_simulation_by_denom`](#0x1_minitswap_swap_simulation_by_denom) +- [Function `spot_price`](#0x1_minitswap_spot_price) +- [Function `get_unbond_list`](#0x1_minitswap_get_unbond_list) +- [Function `get_arb_info`](#0x1_minitswap_get_arb_info) +- [Function `get_arb_infos`](#0x1_minitswap_get_arb_infos) +- [Function `get_module_store`](#0x1_minitswap_get_module_store) +- [Function `get_pools`](#0x1_minitswap_get_pools) +- [Function `get_pools_list`](#0x1_minitswap_get_pools_list) +- [Function `get_pools_detail`](#0x1_minitswap_get_pools_detail) +- [Function `get_pools_detail_list`](#0x1_minitswap_get_pools_detail_list) +- [Function `unpack_unbond_response`](#0x1_minitswap_unpack_unbond_response) +- [Function `unpack_arb_response`](#0x1_minitswap_unpack_arb_response) +- [Function `unpack_module_store_response`](#0x1_minitswap_unpack_module_store_response) +- [Function `unpack_pools_response`](#0x1_minitswap_unpack_pools_response) +- [Function `unpack_pools_detail_response`](#0x1_minitswap_unpack_pools_detail_response) +- [Function `unpack_virtual_pool_detail`](#0x1_minitswap_unpack_virtual_pool_detail) - [Function `create_pool`](#0x1_minitswap_create_pool) +- [Function `set_emergency_state`](#0x1_minitswap_set_emergency_state) - [Function `deactivate`](#0x1_minitswap_deactivate) - [Function `activate`](#0x1_minitswap_activate) - [Function `change_pool_size`](#0x1_minitswap_change_pool_size) - [Function `update_module_params`](#0x1_minitswap_update_module_params) - [Function `update_pool_params`](#0x1_minitswap_update_pool_params) - [Function `provide`](#0x1_minitswap_provide) -- [Function `withdraw`](#0x1_minitswap_withdraw) +- [Function `unbond`](#0x1_minitswap_unbond) +- [Function `withdraw_unbond`](#0x1_minitswap_withdraw_unbond) - [Function `swap`](#0x1_minitswap_swap) -- [Function `rebalance`](#0x1_minitswap_rebalance) +- [Function `finalize_arb`](#0x1_minitswap_finalize_arb) +- [Function `finalize_arb_hook`](#0x1_minitswap_finalize_arb_hook) +- [Function `create_stableswap_pool`](#0x1_minitswap_create_stableswap_pool) - [Function `provide_internal`](#0x1_minitswap_provide_internal) -- [Function `withdraw_internal`](#0x1_minitswap_withdraw_internal) +- [Function `unbond_internal`](#0x1_minitswap_unbond_internal) - [Function `swap_internal`](#0x1_minitswap_swap_internal) -- [Function `rebalance_internal`](#0x1_minitswap_rebalance_internal) -- [Function `borrow_all_mut`](#0x1_minitswap_borrow_all_mut) -- [Function `borrow_all`](#0x1_minitswap_borrow_all) -- [Function `calc_peg_keeper_swap`](#0x1_minitswap_calc_peg_keeper_swap) -- [Function `l1_init_metadata`](#0x1_minitswap_l1_init_metadata) -- [Function `share_token_metadata`](#0x1_minitswap_share_token_metadata) -- [Function `total_share`](#0x1_minitswap_total_share) -- [Function `assert_is_chain`](#0x1_minitswap_assert_is_chain) -- [Function `mul_div`](#0x1_minitswap_mul_div) -- [Function `is_l1_init`](#0x1_minitswap_is_l1_init) -- [Function `is_l1_init_metadata`](#0x1_minitswap_is_l1_init_metadata) -- [Function `get_d0`](#0x1_minitswap_get_d0) -- [Function `get_d`](#0x1_minitswap_get_d) -- [Function `get_return_amount`](#0x1_minitswap_get_return_amount) -- [Function `get_y`](#0x1_minitswap_get_y) -- [Function `get_fully_recovered_ratio`](#0x1_minitswap_get_fully_recovered_ratio) -- [Function `get_fully_recovered_pool_amounts`](#0x1_minitswap_get_fully_recovered_pool_amounts) -- [Function `decimal128_safe_mul`](#0x1_minitswap_decimal128_safe_mul) -- [Function `decimal128_safe_from_ratio`](#0x1_minitswap_decimal128_safe_from_ratio) -- [Function `assert_min_amount`](#0x1_minitswap_assert_min_amount) - - -
use 0x1::block;
+-  [Function `ibc_ack`](#0x1_minitswap_ibc_ack)
+-  [Function `ibc_timeout`](#0x1_minitswap_ibc_timeout)
+-  [Function `safe_swap_simulation`](#0x1_minitswap_safe_swap_simulation)
+-  [Function `safe_swap_simulation_given_out`](#0x1_minitswap_safe_swap_simulation_given_out)
+
+
+
use 0x1::address;
+use 0x1::base64;
+use 0x1::bcs;
+use 0x1::bigdecimal;
+use 0x1::block;
 use 0x1::coin;
-use 0x1::decimal128;
+use 0x1::cosmos;
 use 0x1::error;
 use 0x1::event;
 use 0x1::fungible_asset;
+use 0x1::hash;
+use 0x1::hex;
+use 0x1::json;
 use 0x1::object;
 use 0x1::option;
 use 0x1::primary_fungible_store;
 use 0x1::signer;
+use 0x1::stableswap;
 use 0x1::string;
+use 0x1::string_utils;
 use 0x1::table;
+use 0x1::table_key;
+use 0x1::vector;
 
@@ -81,8 +122,7 @@ -
-Fields +##### Fields
@@ -93,28 +133,46 @@ Extend reference
-pools: table::Table<object::Object<fungible_asset::Metadata>, object::Object<minitswap::VirtualPool>> +pools: table::Table<object::Object<fungible_asset::Metadata>, minitswap::Pools>
List of pools
-l1_init_amount: u64 +max_change_rate: bigdecimal::BigDecimal +
+
+ Max pool size change rate +
+
+emergency_state: bool +
+
+ If this state is True, every depositor related transaction sent to Minitswap will fail +
+
+admin: address +
+
+ admin address who can change emergency_state and pool active +
+
+depositor_owned_init: u64
Not real balance, the amount for shares
-swap_fee_rate: decimal128::Decimal128 +unbond_period: u64
- Swap fee rate + unbond period
-max_change_rate: decimal128::Decimal128 +unbond_wait_list: table::Table<vector<u8>, minitswap::UnbondEntity>
- Max pool size change rate + unbond wait list. key: address + release time
mint_cap: coin::MintCapability @@ -128,11 +186,75 @@
burn capability of liquidity token
+
+stableswap_ann: u64 +
+
+ ANN +
+
+stableswap_swap_fee_rate: bigdecimal::BigDecimal +
+
+ swap fee rate +
+
+swap_fee_rate: bigdecimal::BigDecimal +
+
+ Swap fee rate +
+
+arb_fee_rate: bigdecimal::BigDecimal +
+
+ Swap fee rate +
+
+trigger_fee: u64 +
+
+ The amount of uinit that the user will take during finalization of in-house arb +
+
+min_arb_profit: u64 +
+
+ The minimum time needed to trigger the arbitrage +
+
+ibc_timeout: u64 +
+
+ How much minimum pegkeeper ibc_op_init balance is needed to trigger the arb +
+
+max_arb_batch: u64 +
+
+ Maximum arb_batch size +
+
+min_arb_interval: u64 +
+
+ Minimum arb interval +
+
+global_arb_batch_map: table::Table<vector<u8>, object::Object<minitswap::VirtualPool>> +
+
+ global arb map. index => Virtual Pool +
+
+arb_batch_index: u64 +
+
+ arb batc index +
-
- ## Resource `VirtualPool` @@ -144,12 +266,17 @@ -
-Fields +##### Fields
+ibc_op_init_metadata: object::Object<fungible_asset::Metadata> +
+
+ IBC OP init metadata +
+
extend_ref: object::ExtendRef
@@ -162,34 +289,34 @@ Z. Virtual pool size
-recover_velocity: decimal128::Decimal128 +recover_velocity: bigdecimal::BigDecimal
V. Recover velocity. Real recover amount = Vt
-max_ratio: decimal128::Decimal128 +max_ratio: bigdecimal::BigDecimal
R_max max recover ratio
-recover_param: decimal128::Decimal128 +recover_param: bigdecimal::BigDecimal
f. Flexibility
-l1_pool_amount: u64 +init_pool_amount: u64
- Virtual pool amount of L1 INIT + Virtual pool amount of INIT
-l2_pool_amount: u64 +ibc_op_init_pool_amount: u64
- Virtual pool amount of L2 INIT + Virtual pool amount of ibc_op_INIT
last_recovered_timestamp: u64 @@ -198,16 +325,22 @@ last recovered timestamp
-virtual_l1_balance: u64 +virtual_init_balance: u64 +
+
+ INIT balance of peg keeper (negative value) +
+
+virtual_ibc_op_init_balance: u64
- L1 INIT balance of peg keeper (negative value) + ibc op INIT balance of peg keeper
-virtual_l2_balance: u64 +peg_keeper_owned_ibc_op_init_balance: u64
- L2 INIT balance of peg keeper + ibc op INIT balance of peg keeper which also include unprocessed arb_batch state.
ann: u64 @@ -221,72 +354,74 @@
Is pool in active
+
+op_bridge_id: u64 +
+
+ op bridge id +
+
+ibc_channel: string::String +
+
+ ibc channel +
+
+vm_type: u8 +
+
+ layer 2 vm type. One of MOVE or COSMWASM +
+
+hook_contract: string::String +
+
+ hook contract +
+
+arb_batch_map: table::Table<vector<u8>, minitswap::ArbInfo> +
+
+ ongoing in house arb info +
-
- - + -## Struct `ProvideEvent` +## Struct `Pools` -Event emitted when provide. -
#[event]
-struct ProvideEvent has drop, store
+
struct Pools has store
 
-
-Fields +##### Fields
-provide_amount: u64 +op_bridge_id: u64
-share_amount: u64 +ibc_channel: string::String
-
- - -
- - - -## Struct `WithdrawEvent` - -Event emitted when withdraw. - - -
#[event]
-struct WithdrawEvent has drop, store
-
- - - -
-Fields - - -
-withdraw_amount: u64 +virtual_pool: option::Option<object::Object<minitswap::VirtualPool>>
-share_amount: u64 +stableswap_pool: option::Option<object::Object<stableswap::Pool>>
@@ -294,64 +429,83 @@ Event emitted when withdraw.
-
- - + -## Struct `SwapEvent` +## Struct `UnbondEntity` -Event emitted when swap token. -
#[event]
-struct SwapEvent has drop, store
+
struct UnbondEntity has store
 
-
-Fields +##### Fields
-offer_coin: object::Object<fungible_asset::Metadata> +account: address
-return_coin: object::Object<fungible_asset::Metadata> +share_amount: u64
-peg_keeper_offer_amount: u64 +withdraw_amount: u64
-peg_keeper_return_amount: u64 +release_time: u64 +
+
+ +
+
+ + + + +## Struct `ArbInfo` + + + +
struct ArbInfo has store
+
+ + + +##### Fields + + +
+
+executed_time: u64
-offer_amount: u64 +init_used: u64
-return_amount: u64 +ibc_op_init_sent: u64
-fee_amount: u64 +triggering_fee: u64
@@ -359,152 +513,1472 @@ Event emitted when swap token.
-
+ - +## Struct `CreatePoolEvent` -## Struct `RebalanceEvent` - -Event emitted when rebalance peg keeper's balances. +Event emitted when virtual pool created
#[event]
-struct RebalanceEvent has drop, store
+struct CreatePoolEvent has drop, store
 
-
-Fields +##### Fields
-offer_coin: object::Object<fungible_asset::Metadata> +ibc_op_init_metadata: object::Object<fungible_asset::Metadata>
-return_coin: object::Object<fungible_asset::Metadata> +recover_velocity: bigdecimal::BigDecimal
-offer_amount: u64 +pool_size: u64
-return_amount: u64 +ann: u64
-fee_amount: u64 +max_ratio: bigdecimal::BigDecimal
-
- - -
+
+recover_param: bigdecimal::BigDecimal +
+
- +
+
-## Constants + - +## Struct `ChangePoolSizeEvent` +Event emitted when virtual pool size changed -
const EMIN_RETURN: u64 = 9;
+
#[event]
+struct ChangePoolSizeEvent has drop, store
 
- - - - -
const A_PRECISION: u256 = 100;
-
+##### Fields +
+
+ibc_op_init_metadata: object::Object<fungible_asset::Metadata> +
+
- - +
+
+pool_size: u64 +
+
+
+
+depositor_owned_init_increase: u64 +
+
-
const EINACTIVE: u64 = 5;
-
+
+
+ - +## Struct `UpdatePoolParamsEvent` +Event emitted when update param of virtual pool -
const EL2_PRICE_TOO_LOW: u64 = 7;
+
#[event]
+struct UpdatePoolParamsEvent has drop, store
 
- - +##### Fields -
const EMAX_CHANGE: u64 = 8;
-
+
+
+ibc_op_init_metadata: object::Object<fungible_asset::Metadata> +
+
+
+
+recover_velocity: option::Option<bigdecimal::BigDecimal> +
+
+
+
+ann: option::Option<u64> +
+
- +
+
+max_ratio: option::Option<bigdecimal::BigDecimal> +
+
+
+
+recover_param: option::Option<bigdecimal::BigDecimal> +
+
+
+
+hook_contract: option::Option<string::String> +
+
-
const ENOT_CHAIN: u64 = 1;
-
+
+
+ - +## Struct `ProvideEvent` +Event emitted when provide. -
const ENOT_ENOUGH_BALANCE: u64 = 4;
+
#[event]
+struct ProvideEvent has drop, store
 
- +##### Fields +
+
+provide_amount: u64 +
+
+ +
+
+share_amount: u64 +
+
-
const ENOT_L1_INIT: u64 = 3;
-
+
+
+ - +## Struct `UnbondEvent` +Event emitted when unbond. -
const ENOT_SHARE_TOKEN: u64 = 6;
+
#[event]
+struct UnbondEvent has drop, store
 
- - +##### Fields -
const EPOOL_NOT_FOUND: u64 = 2;
+
+
+account: address +
+
+ +
+
+share_amount: u64 +
+
+ +
+
+withdraw_amount: u64 +
+
+ +
+
+release_time: u64 +
+
+ +
+
+ + + + +## Struct `WithdrawUnbondEvent` + +Event emitted when withdraw unbond. + + +
#[event]
+struct WithdrawUnbondEvent has drop, store
+
+ + + +##### Fields + + +
+
+account: address +
+
+ +
+
+share_amount: u64 +
+
+ +
+
+withdraw_amount: u64 +
+
+ +
+
+release_time: u64 +
+
+ +
+
+ + + + +## Struct `SwapEvent` + +Event emitted when swap token. + + +
#[event]
+struct SwapEvent has drop, store
+
+ + + +##### Fields + + +
+
+offer_coin: object::Object<fungible_asset::Metadata> +
+
+ +
+
+return_coin: object::Object<fungible_asset::Metadata> +
+
+ +
+
+peg_keeper_offer_amount: u64 +
+
+ +
+
+peg_keeper_return_amount: u64 +
+
+ +
+
+offer_amount: u64 +
+
+ +
+
+return_amount: u64 +
+
+ +
+
+init_swap_fee_amount: u64 +
+
+ +
+
+init_arb_fee_amount: u64 +
+
+ +
+
+ibc_op_init_swap_fee_amount: u64 +
+
+ +
+
+ibc_op_init_arb_fee_amount: u64 +
+
+ +
+
+ + + + +## Struct `CreateStableswapPoolEvent` + +Event emitted when stable swap pool created + + +
#[event]
+struct CreateStableswapPoolEvent has drop, store
+
+ + + +##### Fields + + +
+
+ibc_op_init_metadata: object::Object<fungible_asset::Metadata> +
+
+ +
+
+pool: object::Object<stableswap::Pool> +
+
+ +
+
+ + + + +## Struct `InitiateArbEvent` + +Event emitted when arb initiated + + +
#[event]
+struct InitiateArbEvent has drop, store
+
+ + + +##### Fields + + +
+
+arb_index: u64 +
+
+ +
+
+pool: object::Object<minitswap::VirtualPool> +
+
+ +
+
+executed_time: u64 +
+
+ +
+
+init_used: u64 +
+
+ +
+
+ibc_op_init_sent: u64 +
+
+ +
+
+triggering_fee: u64 +
+
+ +
+
+ + + + +## Struct `FinalizeArbEvent` + +Event emitted when arb finalized + + +
#[event]
+struct FinalizeArbEvent has drop, store
+
+ + + +##### Fields + + +
+
+arb_index: u64 +
+
+ +
+
+pool: object::Object<minitswap::VirtualPool> +
+
+ +
+
+init_used: u64 +
+
+ +
+
+ibc_op_init_sent: u64 +
+
+ +
+
+triggering_fee: u64 +
+
+ +
+
+ + + + +## Struct `RevertArbEvent` + +Event emitted when arb reverted + + +
#[event]
+struct RevertArbEvent has drop, store
+
+ + + +##### Fields + + +
+
+arb_index: u64 +
+
+ +
+
+pool: object::Object<minitswap::VirtualPool> +
+
+ +
+
+init_used: u64 +
+
+ +
+
+ibc_op_init_sent: u64 +
+
+ +
+
+triggering_fee: u64 +
+
+ +
+
+ + + + +## Struct `UnbondResponse` + + + +
struct UnbondResponse has drop
+
+ + + +##### Fields + + +
+
+account: address +
+
+ +
+
+share_amount: u64 +
+
+ +
+
+withdraw_amount: u64 +
+
+ +
+
+release_time: u64 +
+
+ +
+
+ + + + +## Struct `ArbResponse` + + + +
struct ArbResponse has drop
+
+ + + +##### Fields + + +
+
+ibc_op_init_metadata: object::Object<fungible_asset::Metadata> +
+
+ +
+
+id: u64 +
+
+ +
+
+executed_time: u64 +
+
+ +
+
+init_used: u64 +
+
+ +
+
+ibc_op_init_sent: u64 +
+
+ +
+
+triggering_fee: u64 +
+
+ +
+
+ + + + +## Struct `ModuleStoreResponse` + + + +
struct ModuleStoreResponse has drop
+
+ + + +##### Fields + + +
+
+max_change_rate: bigdecimal::BigDecimal +
+
+ +
+
+emergency_state: bool +
+
+ +
+
+admin: address +
+
+ +
+
+depositor_owned_init: u64 +
+
+ +
+
+unbond_period: u64 +
+
+ +
+
+swap_fee_rate: bigdecimal::BigDecimal +
+
+ +
+
+arb_fee_rate: bigdecimal::BigDecimal +
+
+ +
+
+trigger_fee: u64 +
+
+ +
+
+min_arb_profit: u64 +
+
+ +
+
+ibc_timeout: u64 +
+
+ +
+
+max_arb_batch: u64 +
+
+ +
+
+min_arb_interval: u64 +
+
+ +
+
+arb_batch_index: u64 +
+
+ +
+
+ + + + +## Struct `PoolsResponse` + + + +
struct PoolsResponse has drop
+
+ + + +##### Fields + + +
+
+ibc_op_init_metadata: object::Object<fungible_asset::Metadata> +
+
+ +
+
+ibc_op_init_denom: string::String +
+
+ +
+
+op_bridge_id: u64 +
+
+ +
+
+ibc_channel: string::String +
+
+ +
+
+virtual_pool: option::Option<object::Object<minitswap::VirtualPool>> +
+
+ +
+
+stableswap_pool: option::Option<object::Object<stableswap::Pool>> +
+
+ +
+
+ + + + +## Struct `PoolsDetailResponse` + + + +
struct PoolsDetailResponse has drop
+
+ + + +##### Fields + + +
+
+ibc_op_init_metadata: object::Object<fungible_asset::Metadata> +
+
+ +
+
+ibc_op_init_denom: string::String +
+
+ +
+
+op_bridge_id: u64 +
+
+ +
+
+ibc_channel: string::String +
+
+ +
+
+virtual_pool: option::Option<minitswap::VirtualPoolDetail> +
+
+ +
+
+stableswap_pool: option::Option<stableswap::PoolResponse> +
+
+ +
+
+ + + + +## Struct `VirtualPoolDetail` + + + +
struct VirtualPoolDetail has drop
+
+ + + +##### Fields + + +
+
+pool_size: u64 +
+
+ +
+
+recover_velocity: bigdecimal::BigDecimal +
+
+ +
+
+max_ratio: bigdecimal::BigDecimal +
+
+ +
+
+recover_param: bigdecimal::BigDecimal +
+
+ +
+
+init_pool_amount: u64 +
+
+ +
+
+ibc_op_init_pool_amount: u64 +
+
+ +
+
+last_recovered_timestamp: u64 +
+
+ +
+
+virtual_init_balance: u64 +
+
+ +
+
+virtual_ibc_op_init_balance: u64 +
+
+ +
+
+peg_keeper_owned_ibc_op_init_balance: u64 +
+
+ +
+
+ann: u64 +
+
+ +
+
+active: bool +
+
+ +
+
+ + + + +## Struct `IBCMemo` + + + +
struct IBCMemo has copy, drop
+
+ + + +##### Fields + + +
+
+_move_: minitswap::MemoMove +
+
+ +
+
+wasm: option::Option<minitswap::MemoWasm> +
+
+ +
+
+ + + + +## Struct `MemoMove` + + + +
struct MemoMove has copy, drop
+
+ + + +##### Fields + + +
+
+message: option::Option<minitswap::MemoMoveMessage> +
+
+ +
+
+async_callback: minitswap::MemoAsyncCallback +
+
+ +
+
+ + + + +## Struct `MemoAsyncCallback` + + + +
struct MemoAsyncCallback has copy, drop
+
+ + + +##### Fields + + +
+
+id: u64 +
+
+ +
+
+module_address: address +
+
+ +
+
+module_name: string::String +
+
+ +
+
+ + + + +## Struct `MemoMoveMessage` + + + +
struct MemoMoveMessage has copy, drop
+
+ + + +##### Fields + + +
+
+module_address: string::String +
+
+ +
+
+module_name: string::String +
+
+ +
+
+function_name: string::String +
+
+ +
+
+type_args: vector<string::String> +
+
+ +
+
+args: vector<string::String> +
+
+ +
+
+ + + + +## Struct `MemoWasm` + + + +
struct MemoWasm has copy, drop
+
+ + + +##### Fields + + +
+
+message: minitswap::MemoWasmMessage +
+
+ +
+
+ + + + +## Struct `MemoWasmMessage` + + + +
struct MemoWasmMessage has copy, drop
+
+ + + +##### Fields + + +
+
+contracts: string::String +
+
+ +
+
+funds: vector<minitswap::MemoWasmFunds> +
+
+ +
+
+msg: minitswap::MemoWasmMinitswapHook +
+
+ +
+
+ + + + +## Struct `MemoWasmFunds` + + + +
struct MemoWasmFunds has copy, drop
+
+ + + +##### Fields + + +
+
+denom: string::String +
+
+ +
+
+amount: string::String +
+
+ +
+
+ + + + +## Struct `MemoWasmMinitswapHook` + + + +
struct MemoWasmMinitswapHook has copy, drop
+
+ + + +##### Fields + + +
+
+minitswap_hook: minitswap::MemoWasmMinitswapHookMsg +
+
+ +
+
+ + + + +## Struct `MemoWasmMinitswapHookMsg` + + + +
struct MemoWasmMinitswapHookMsg has copy, drop
+
+ + + +##### Fields + + +
+
+receiver: string::String +
+
+ +
+
+ + + + +## Struct `FinalizeTokenWithdrawalRequest` + + + +
struct FinalizeTokenWithdrawalRequest has copy, drop
+
+ + + +##### Fields + + +
+
+_type_: string::String +
+
+ +
+
+bridge_id: u64 +
+
+ +
+
+output_index: u64 +
+
+ +
+
+withdrawal_proofs: vector<string::String> +
+
+ +
+
+sender: string::String +
+
+ +
+
+receiver: string::String +
+
+ +
+
+sequence: u64 +
+
+ +
+
+amount: minitswap::CosmosCoin +
+
+ +
+
+version: string::String +
+
+ +
+
+state_root: string::String +
+
+ +
+
+storage_root: string::String +
+
+ +
+
+latest_block_hash: string::String +
+
+ +
+
+ + + + +## Struct `CosmosCoin` + + + +
struct CosmosCoin has copy, drop
+
+ + + +##### Fields + + +
+
+denom: string::String +
+
+ +
+
+amount: u64 +
+
+ +
+
+ + + + +## Constants + + + + + + +
const EAMOUNT_MISMATCH: u64 = 13;
+
+ + + + + + + +
const EUNAUTHORIZED: u64 = 1;
+
+ + + + + + + +
const EMIN_RETURN: u64 = 9;
+
+ + + + + + + +
const MAX_LIMIT: u64 = 30;
+
+ + + + + + + +
const A_PRECISION: u256 = 100;
+
+ + + + + + + +
const COSMWASM: u8 = 1;
+
+ + + + + + + +
const EEMERGENCY: u64 = 14;
+
+ + + + + + + +
const EIBC_OP_INIT_PRICE_TOO_LOW: u64 = 7;
+
+ + + + + + + +
const EINACTIVE: u64 = 5;
+
+ + + + + + + +
const EINVAILD_METADATA: u64 = 16;
+
+ + + + + + + +
const EMAX_CHANGE: u64 = 8;
+
+ + + + + + + +
const ENOT_ENOUGH_BALANCE: u64 = 4;
+
+ + + + + + + +
const ENOT_INIT: u64 = 3;
+
+ + + + + + + +
const ENOT_SHARE_TOKEN: u64 = 6;
+
+ + + + + + + +
const EPOOL_NOT_FOUND: u64 = 2;
 
@@ -518,68 +1992,68 @@ Event emitted when rebalance peg keeper's balances. - + -
const SYMBOL: vector<u8> = [109, 105, 110, 105, 116, 115, 119, 97, 112, 95, 108, 112];
+
const ERELEASE_TIME: u64 = 15;
 
- + -
const U64_MAX: u128 = 18446744073709551615;
+
const ESMALL_ARB_PROFIT: u64 = 17;
 
- + + + + +
const EVIRTUAL_POOL_EXISTS: u64 = 18;
+
+ + -## Function `init_module` + -
fun init_module(chain: &signer)
+
const EVM_TYPE: u64 = 12;
 
-
-Implementation + -
fun init_module(chain: &signer) {
-    let constructor_ref = object::create_object(@initia_std, false);
-    let extend_ref = object::generate_extend_ref(&constructor_ref);
 
-    let (mint_cap, burn_cap, _) = coin::initialize(
-        chain,
-        option::some(U64_MAX),
-        string::utf8(b"minitswap liquidity token"),
-        string::utf8(SYMBOL),
-        6,
-        string::utf8(b""),
-        string::utf8(b""),
-    );
+
const MOVE: u8 = 0;
+
- move_to(chain, ModuleStore { - extend_ref, - pools: table::new(), - l1_init_amount: 0, - swap_fee_rate: decimal128::from_ratio(1, 1000), // 0.1% - max_change_rate: decimal128::from_ratio(1, 10), // 10% - mint_cap, - burn_cap, - }); -} + + + + + + +
const SYMBOL: vector<u8> = [117, 111, 105, 110, 105, 116];
 
-
+ + + + +
const U64_MAX: u128 = 18446744073709551615;
+
+ + @@ -588,34 +2062,44 @@ Event emitted when rebalance peg keeper's balances.
#[view]
-public fun get_pool_amount(l2_init_metadata: object::Object<fungible_asset::Metadata>, after_peg_keeper_swap: bool): (u64, u64)
+public fun get_pool_amount(ibc_op_init_metadata: object::Object<fungible_asset::Metadata>, after_peg_keeper_swap: bool): (u64, u64)
 
-
-Implementation +##### Implementation
public fun get_pool_amount(
-    l2_init_metadata: Object<Metadata>,
-    after_peg_keeper_swap: bool,
+    ibc_op_init_metadata: Object<Metadata>, after_peg_keeper_swap: bool
 ): (u64, u64) acquires ModuleStore, VirtualPool {
-    let (_, pool) = borrow_all(l2_init_metadata);
+    let virtual_pool_exists = virtual_pool_exists(ibc_op_init_metadata);
+
+    assert!(
+        virtual_pool_exists,
+        error::invalid_argument(EPOOL_NOT_FOUND)
+    );
+
+    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
+    let pools = table::borrow(&mut module_store.pools, ibc_op_init_metadata);
+    let pool =
+        borrow_global_mut<VirtualPool>(
+            object::object_address(&*option::borrow(&pools.virtual_pool))
+        );
     assert!(pool.active, error::invalid_state(EINACTIVE));
-    let (swap_amount, return_amount) = if (after_peg_keeper_swap) {
-        calc_peg_keeper_swap(pool)
-    } else {
-        (0, 0)
-    };
-    return (pool.l1_pool_amount + swap_amount, pool.l2_pool_amount - return_amount)
+    let (swap_amount, return_amount) =
+        if (after_peg_keeper_swap) {
+            calc_peg_keeper_swap(pool)
+        } else { (0, 0) };
+    return (
+        pool.init_pool_amount + swap_amount,
+        pool.ibc_op_init_pool_amount - return_amount
+    )
 }
 
-
- ## Function `get_pool_amount_by_denom` @@ -623,28 +2107,24 @@ Event emitted when rebalance peg keeper's balances.
#[view]
-public fun get_pool_amount_by_denom(l2_init_denom: string::String, after_peg_keeper_swap: bool): (u64, u64)
+public fun get_pool_amount_by_denom(ibc_op_init_denom: string::String, after_peg_keeper_swap: bool): (u64, u64)
 
-
-Implementation +##### Implementation
public fun get_pool_amount_by_denom(
-    l2_init_denom: String,
-    after_peg_keeper_swap: bool,
+    ibc_op_init_denom: String, after_peg_keeper_swap: bool
 ): (u64, u64) acquires ModuleStore, VirtualPool {
-    let l2_init_metadata = coin::denom_to_metadata(l2_init_denom);
-    get_pool_amount(l2_init_metadata, after_peg_keeper_swap)
+    let ibc_op_init_metadata = coin::denom_to_metadata(ibc_op_init_denom);
+    get_pool_amount(ibc_op_init_metadata, after_peg_keeper_swap)
 }
 
-
- ## Function `get_peg_keeper_balance` @@ -652,35 +2132,33 @@ Event emitted when rebalance peg keeper's balances.
#[view]
-public fun get_peg_keeper_balance(l2_init_metadata: object::Object<fungible_asset::Metadata>, after_peg_keeper_swap: bool): (u64, u64)
+public fun get_peg_keeper_balance(ibc_op_init_metadata: object::Object<fungible_asset::Metadata>, after_peg_keeper_swap: bool): (u64, u64)
 
-
-Implementation +##### Implementation
public fun get_peg_keeper_balance(
-    l2_init_metadata: Object<Metadata>,
-    after_peg_keeper_swap: bool,
+    ibc_op_init_metadata: Object<Metadata>, after_peg_keeper_swap: bool
 ): (u64, u64) acquires ModuleStore, VirtualPool {
-    let (_, pool) = borrow_all(l2_init_metadata);
+    let (_, pool) = borrow_all(ibc_op_init_metadata);
     assert!(pool.active, error::invalid_state(EINACTIVE));
-    let (swap_amount, return_amount) = if (after_peg_keeper_swap) {
-        calc_peg_keeper_swap(pool)
-    } else {
-        (0, 0)
-    };
-
-    return (pool.virtual_l1_balance + swap_amount, pool.virtual_l2_balance + return_amount)
+    let (swap_amount, return_amount) =
+        if (after_peg_keeper_swap) {
+            calc_peg_keeper_swap(pool)
+        } else { (0, 0) };
+
+    return (
+        pool.virtual_init_balance + swap_amount,
+        pool.virtual_ibc_op_init_balance + return_amount
+    )
 }
 
-
- ## Function `get_peg_keeper_balance_by_denom` @@ -688,28 +2166,24 @@ Event emitted when rebalance peg keeper's balances.
#[view]
-public fun get_peg_keeper_balance_by_denom(l2_init_denom: string::String, after_peg_keeper_swap: bool): (u64, u64)
+public fun get_peg_keeper_balance_by_denom(ibc_op_init_denom: string::String, after_peg_keeper_swap: bool): (u64, u64)
 
-
-Implementation +##### Implementation
public fun get_peg_keeper_balance_by_denom(
-    l2_init_denom: String,
-    after_peg_keeper_swap: bool,
+    ibc_op_init_denom: String, after_peg_keeper_swap: bool
 ): (u64, u64) acquires ModuleStore, VirtualPool {
-    let l2_init_metadata = coin::denom_to_metadata(l2_init_denom);
-    get_peg_keeper_balance(l2_init_metadata, after_peg_keeper_swap)
+    let ibc_op_init_metadata = coin::denom_to_metadata(ibc_op_init_denom);
+    get_peg_keeper_balance(ibc_op_init_metadata, after_peg_keeper_swap)
 }
 
-
- ## Function `swap_simulation` @@ -722,53 +2196,65 @@ Event emitted when rebalance peg keeper's balances. -
-Implementation +##### Implementation
public fun swap_simulation(
     offer_metadata: Object<Metadata>,
     return_metadata: Object<Metadata>,
-    offer_amount: u64,
+    offer_amount: u64
 ): (u64, u64) acquires ModuleStore, VirtualPool {
-    let is_l1_init_offered = is_l1_init_metadata(offer_metadata);
-    let l2_init_metadata = if(is_l1_init_offered) {
-        return_metadata
-    } else {
-        offer_metadata
-    };
-
-    let (_, pool) = borrow_all(l2_init_metadata);
-    let (peg_keeper_offer_amount, peg_keeper_return_amount) = calc_peg_keeper_swap(pool);
-
-    let (l1_pool_amount, l2_pool_amount) = get_pool_amount(l2_init_metadata, true);
-    l1_pool_amount = l1_pool_amount + peg_keeper_offer_amount;
-    l2_pool_amount = l2_pool_amount - peg_keeper_return_amount;
-
-    let (module_store, pool) = borrow_all(l2_init_metadata);
-    let fee_amount = 0;
-    let return_amount = if (is_l1_init_offered) {
-        // 0 fee for L1 > L2
-        let return_amount = get_return_amount(offer_amount, l1_pool_amount, l2_pool_amount, pool.pool_size, pool.ann);
-        assert!(
-            l2_pool_amount >= pool.pool_size && l1_pool_amount <= pool.pool_size,
-            error::invalid_state(EL2_PRICE_TOO_LOW),
+    let (return_amount, fee_amount) =
+        safe_swap_simulation(
+            offer_metadata,
+            return_metadata,
+            offer_amount
         );
-        return_amount
-    } else {
-        let return_amount = get_return_amount(offer_amount, l2_pool_amount, l1_pool_amount, pool.pool_size, pool.ann);
-        fee_amount = decimal128::mul_u64(&module_store.swap_fee_rate, return_amount);
-        let return_amount = return_amount - fee_amount;
-        return_amount
-    };
-
+    assert!(
+        return_amount != 0,
+        error::invalid_state(EIBC_OP_INIT_PRICE_TOO_LOW)
+    );
     (return_amount, fee_amount)
 }
 
-
+ + +## Function `swap_simulation_given_out` + + + +
#[view]
+public fun swap_simulation_given_out(offer_metadata: object::Object<fungible_asset::Metadata>, return_metadata: object::Object<fungible_asset::Metadata>, return_amount: u64): (u64, u64)
+
+ + + +##### Implementation + + +
public fun swap_simulation_given_out(
+    offer_metadata: Object<Metadata>,
+    return_metadata: Object<Metadata>,
+    return_amount: u64
+): (u64, u64) acquires ModuleStore, VirtualPool {
+    let (return_amount, fee_amount) =
+        safe_swap_simulation_given_out(
+            offer_metadata,
+            return_metadata,
+            return_amount
+        );
+    assert!(
+        return_amount != (U64_MAX as u64),
+        error::invalid_state(EIBC_OP_INIT_PRICE_TOO_LOW)
+    );
+    (return_amount, fee_amount)
+}
+
+ + @@ -782,1301 +2268,2248 @@ Event emitted when rebalance peg keeper's balances. -
-Implementation +##### Implementation
public fun swap_simulation_by_denom(
-    offer_denom: String,
-    return_denom: String,
-    offer_amount: u64,
+    offer_denom: String, return_denom: String, offer_amount: u64
 ): (u64, u64) acquires ModuleStore, VirtualPool {
     let offer_metadata = coin::denom_to_metadata(offer_denom);
     let return_metadata = coin::denom_to_metadata(return_denom);
-    swap_simulation(offer_metadata, return_metadata, offer_amount)
+    swap_simulation(
+        offer_metadata,
+        return_metadata,
+        offer_amount
+    )
 }
 
-
+ - +## Function `spot_price` -## Function `create_pool` + + +
#[view]
+public fun spot_price(base_metadata: object::Object<fungible_asset::Metadata>, quote_metadata: object::Object<fungible_asset::Metadata>): bigdecimal::BigDecimal
+
-
public entry fun create_pool(chain: &signer, l2_init_metadata: object::Object<fungible_asset::Metadata>, recover_velocity: decimal128::Decimal128, pool_size: u64, ann: u64, max_ratio: decimal128::Decimal128, recover_param: decimal128::Decimal128)
+##### Implementation
+
+
+
public fun spot_price(
+    base_metadata: Object<Metadata>, quote_metadata: Object<Metadata>
+): BigDecimal acquires ModuleStore, VirtualPool {
+    let is_init_quote = is_init_metadata(quote_metadata);
+    let ibc_op_init_metadata = if (is_init_quote) {
+        base_metadata
+    } else {
+        quote_metadata
+    };
+
+    let virtual_pool_exists = virtual_pool_exists(ibc_op_init_metadata);
+
+    assert!(
+        virtual_pool_exists,
+        error::invalid_argument(EPOOL_NOT_FOUND)
+    );
+
+    let (init_pool_amount, ibc_op_init_pool_amount) =
+        get_pool_amount(ibc_op_init_metadata, !is_init_quote);
+    let (_, pool) = borrow_all(ibc_op_init_metadata);
+
+    let swap_amount = 1000000;
+    let ibc_op_init_return_amount =
+        get_return_amount(
+            swap_amount,
+            init_pool_amount,
+            ibc_op_init_pool_amount,
+            pool.pool_size,
+            pool.ann
+        );
+    let init_return_amount =
+        get_return_amount(
+            swap_amount,
+            ibc_op_init_pool_amount,
+            init_pool_amount,
+            pool.pool_size,
+            pool.ann
+        );
+
+    if (is_init_quote) {
+        bigdecimal::from_ratio_u64(
+            init_return_amount + swap_amount,
+            ibc_op_init_return_amount + swap_amount
+        )
+    } else {
+        bigdecimal::from_ratio_u64(
+            ibc_op_init_return_amount + swap_amount,
+            init_return_amount + swap_amount
+        )
+    }
+}
 
-
-Implementation + +## Function `get_unbond_list` -
public entry fun create_pool(
-    chain: &signer,
-    l2_init_metadata: Object<Metadata>,
-    recover_velocity: Decimal128,
-    pool_size: u64,
-    ann: u64,
-    max_ratio: Decimal128,
-    recover_param: Decimal128,
-) acquires ModuleStore {
-    assert_is_chain(chain);
-    assert!(pool_size > 0, error::invalid_argument(EPOOL_SIZE));
-    let constructor_ref = object::create_object(@initia_std, false);
-    let extend_ref = object::generate_extend_ref(&constructor_ref);
-    let pool_signer = object::generate_signer(&constructor_ref);
-    let (_, timestamp) = block::get_block_info();
 
-    move_to(
-        &pool_signer,
-        VirtualPool {
-            extend_ref,
-            recover_velocity,
-            pool_size,
-            max_ratio,
-            recover_param,
-            l1_pool_amount: pool_size,
-            l2_pool_amount: pool_size,
-            last_recovered_timestamp: timestamp,
-            virtual_l1_balance: 0,
-            virtual_l2_balance: 0,
-            ann,
-            active: true,
-        }
+
+
#[view]
+public fun get_unbond_list(account: address, start_after: option::Option<u64>, limit: u64): vector<minitswap::UnbondResponse>
+
+ + + +##### Implementation + + +
public fun get_unbond_list(
+    account: address, start_after: Option<u64>, limit: u64
+): vector<UnbondResponse> acquires ModuleStore {
+    let module_store = borrow_global<ModuleStore>(@initia_std);
+    let start_key =
+        if (option::is_some(&start_after)) {
+            generate_unbond_key(
+                account,
+                *option::borrow(&start_after) + 1
+            )
+        } else {
+            generate_unbond_key(account, 0)
+        };
+
+    if (limit > MAX_LIMIT) {
+        limit = MAX_LIMIT
+    };
+
+    let iter =
+        table::iter(
+            &module_store.unbond_wait_list,
+            option::some(start_key),
+            option::none(),
+            1
+        );
+
+    let i = 0;
+    let res: vector<UnbondResponse> = vector[];
+    while (i < limit && table::prepare(iter)) {
+        let (_, value) = table::next<vector<u8>, UnbondEntity>(iter);
+        if (value.account != account) break;
+
+        vector::push_back(
+            &mut res,
+            UnbondResponse {
+                account: value.account,
+                share_amount: value.share_amount,
+                withdraw_amount: value.withdraw_amount,
+                release_time: value.release_time
+            }
+        );
+    };
+
+    return res
+}
+
+ + + + + +## Function `get_arb_info` + + + +
#[view]
+public fun get_arb_info(id: u64): minitswap::ArbResponse
+
+ + + +##### Implementation + + +
public fun get_arb_info(id: u64): ArbResponse acquires ModuleStore, VirtualPool {
+    let module_store = borrow_global<ModuleStore>(@initia_std);
+    let pool_obj =
+        table::borrow(
+            &module_store.global_arb_batch_map,
+            table_key::encode_u64(id)
+        );
+    let pool = borrow_global<VirtualPool>(object::object_address(&*pool_obj));
+    let arb_info = table::borrow(
+        &pool.arb_batch_map,
+        table_key::encode_u64(id)
     );
 
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    table::add(&mut module_store.pools, l2_init_metadata, object::object_from_constructor_ref<VirtualPool>(&constructor_ref));
+    return ArbResponse {
+        ibc_op_init_metadata: pool.ibc_op_init_metadata,
+        id,
+        executed_time: arb_info.executed_time,
+        init_used: arb_info.init_used,
+        ibc_op_init_sent: arb_info.ibc_op_init_sent,
+        triggering_fee: arb_info.triggering_fee
+    }
+}
+
+ + + + + +## Function `get_arb_infos` + + + +
#[view]
+public fun get_arb_infos(ibc_op_init_metadata: object::Object<fungible_asset::Metadata>, start_after: option::Option<u64>, limit: u64): vector<minitswap::ArbResponse>
+
+ + + +##### Implementation + + +
public fun get_arb_infos(
+    ibc_op_init_metadata: Object<Metadata>, start_after: Option<u64>, limit: u64
+): vector<ArbResponse> acquires ModuleStore, VirtualPool {
+    let (_, pool) = borrow_all(ibc_op_init_metadata);
+    let start_key =
+        if (option::is_some(&start_after)) {
+            table_key::encode_u64(*option::borrow(&start_after) + 1)
+        } else {
+            table_key::encode_u64(0)
+        };
+
+    if (limit > MAX_LIMIT) {
+        limit = MAX_LIMIT
+    };
+
+    let iter =
+        table::iter(
+            &pool.arb_batch_map,
+            option::some(start_key),
+            option::none(),
+            1
+        );
+
+    let i = 0;
+    let res: vector<ArbResponse> = vector[];
+    while (i < limit && table::prepare(iter)) {
+        let (key, arb_info) = table::next<vector<u8>, ArbInfo>(iter);
+        let id = table_key::decode_u64(key);
+
+        vector::push_back(
+            &mut res,
+            ArbResponse {
+                ibc_op_init_metadata: pool.ibc_op_init_metadata,
+                id,
+                executed_time: arb_info.executed_time,
+                init_used: arb_info.init_used,
+                ibc_op_init_sent: arb_info.ibc_op_init_sent,
+                triggering_fee: arb_info.triggering_fee
+            }
+        );
+    };
+
+    return res
 }
 
-
+ - - -## Function `deactivate` +## Function `get_module_store` -
public entry fun deactivate(chain: &signer, l2_init_metadata: object::Object<fungible_asset::Metadata>)
+
#[view]
+public fun get_module_store(): minitswap::ModuleStoreResponse
 
-
-Implementation +##### Implementation -
public entry fun deactivate(chain: &signer, l2_init_metadata: Object<Metadata>) acquires ModuleStore, VirtualPool {
-    assert_is_chain(chain);
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let pool_obj = table::borrow(&mut module_store.pools, l2_init_metadata);
-    let pool = borrow_global_mut<VirtualPool>(object::object_address(*pool_obj));
-    pool.active = false
+
public fun get_module_store(): ModuleStoreResponse acquires ModuleStore {
+    let module_store = borrow_global<ModuleStore>(@initia_std);
+
+    return ModuleStoreResponse {
+        max_change_rate: module_store.max_change_rate,
+        emergency_state: module_store.emergency_state,
+        admin: module_store.admin,
+        depositor_owned_init: module_store.depositor_owned_init,
+        unbond_period: module_store.unbond_period,
+        swap_fee_rate: module_store.swap_fee_rate,
+        arb_fee_rate: module_store.arb_fee_rate,
+        trigger_fee: module_store.trigger_fee,
+        min_arb_profit: module_store.min_arb_profit,
+        ibc_timeout: module_store.ibc_timeout,
+        max_arb_batch: module_store.max_arb_batch,
+        min_arb_interval: module_store.min_arb_interval,
+        arb_batch_index: module_store.arb_batch_index
+    }
 }
 
-
- - + -## Function `activate` +## Function `get_pools` -
public entry fun activate(chain: &signer, l2_init_metadata: object::Object<fungible_asset::Metadata>)
+
#[view]
+public fun get_pools(ibc_op_init_metadata: object::Object<fungible_asset::Metadata>): minitswap::PoolsResponse
 
-
-Implementation +##### Implementation -
public entry fun activate(chain: &signer, l2_init_metadata: Object<Metadata>) acquires ModuleStore, VirtualPool {
-    assert_is_chain(chain);
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let pool_obj = table::borrow(&mut module_store.pools, l2_init_metadata);
-    let pool = borrow_global_mut<VirtualPool>(object::object_address(*pool_obj));
-    pool.active = true
+
public fun get_pools(ibc_op_init_metadata: Object<Metadata>): PoolsResponse acquires ModuleStore {
+    let module_store = borrow_global<ModuleStore>(@initia_std);
+    let pools = table::borrow(&module_store.pools, ibc_op_init_metadata);
+    return PoolsResponse {
+        ibc_op_init_metadata,
+        ibc_op_init_denom: coin::symbol(ibc_op_init_metadata),
+        op_bridge_id: pools.op_bridge_id,
+        ibc_channel: pools.ibc_channel,
+        virtual_pool: pools.virtual_pool,
+        stableswap_pool: pools.stableswap_pool
+    }
 }
 
-
- - + -## Function `change_pool_size` +## Function `get_pools_list` -
public entry fun change_pool_size(chain: &signer, l2_init_metadata: object::Object<fungible_asset::Metadata>, new_pool_size: u64)
+
#[view]
+public fun get_pools_list(start_after: option::Option<object::Object<fungible_asset::Metadata>>, limit: u64): vector<minitswap::PoolsResponse>
 
-
-Implementation +##### Implementation -
public entry fun change_pool_size(
-    chain: &signer,
-    l2_init_metadata: Object<Metadata>,
-    new_pool_size: u64
-) acquires ModuleStore, VirtualPool {
-    assert_is_chain(chain);
-    assert!(new_pool_size > 0, error::invalid_argument(EPOOL_SIZE));
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let pool_obj = table::borrow(&mut module_store.pools, l2_init_metadata);
-    let pool = borrow_global_mut<VirtualPool>(object::object_address(*pool_obj));
+
public fun get_pools_list(
+    start_after: Option<Object<Metadata>>, limit: u64
+): vector<PoolsResponse> acquires ModuleStore {
+    let module_store = borrow_global<ModuleStore>(@initia_std);
 
-    let change_rate = if (new_pool_size > pool.pool_size) {
-        decimal128::from_ratio_u64(new_pool_size - pool.pool_size, pool.pool_size)
-    } else {
-        decimal128::from_ratio_u64(pool.pool_size - new_pool_size, pool.pool_size)
+    if (limit > MAX_LIMIT) {
+        limit = MAX_LIMIT
     };
 
-    assert!(decimal128::val(&module_store.max_change_rate) >= decimal128::val(&change_rate), error::invalid_argument(EMAX_CHANGE));
-
-    if (new_pool_size < pool.pool_size) {
-        /*
-            Decrease size process
-            1. Change pool amount as ratio
-            2. Calculate diff, update peg keeper's balances
-
-            Net Effect
-            This action is same with swap L1 > L2 until pool ratio to be 5:5,
-            change pool size and sell some portion of L2 at same price
-            - L1 and L2 balances of peg keepers -> L1 decrease L2 increase,
-                but L1 decreased amount is smaller than L2 increased amount.
-            - Pool ratio doesn't change (= price not change)
-        */
-        let current_l1_delta = pool.pool_size - pool.l1_pool_amount;
-        let current_l2_delta = pool.l2_pool_amount - pool.pool_size;
-
-        let ratio = decimal128::from_ratio_u64(new_pool_size, pool.pool_size);
-        pool.l1_pool_amount = decimal128::mul_u64(&ratio, pool.l1_pool_amount);
-        pool.l2_pool_amount = decimal128::mul_u64(&ratio, pool.l2_pool_amount);
-        pool.pool_size = new_pool_size;
-
-        let l1_delta = pool.pool_size - pool.l1_pool_amount;
-        let l2_delta = pool.l2_pool_amount - pool.pool_size;
-
-        let net_l1_delta = current_l1_delta - l1_delta;
-        let net_l2_delta = current_l2_delta - l2_delta;
-
-        pool.virtual_l1_balance = pool.virtual_l1_balance + net_l1_delta;
-        pool.virtual_l2_balance = pool.virtual_l2_balance + net_l2_delta;
-    } else {
-        /*
-            Increase size process
-            1. Swap L1 > L2 to make 5:5
-            2. Change pool size
-            3. Swap back L2 > L1
-                a. If L1 init balance of peg keeper is greater than 0, return it to provider
-
-            Net Effect
-            - L1 and L2 balances of peg keepers -> + for L1 and even for L2
-            - Ratio of pool -> L2 price decrease
-        */
-
-        // 1. swap to make 5:5
-        let l1_swap_amount = pool.pool_size - pool.l1_pool_amount;
-        let l2_return_amount =  pool.l2_pool_amount - pool.pool_size;
-        // pool.l1_pool_amount = pool.pool_size;
-        // pool.l2_pool_amount = pool.pool_size;
-        pool.virtual_l1_balance = pool.virtual_l1_balance + l1_swap_amount;
-        pool.virtual_l2_balance = pool.virtual_l2_balance + l2_return_amount;
-
-        // 2. change pool size
-        pool.l1_pool_amount = new_pool_size;
-        pool.l2_pool_amount = new_pool_size;
-        pool.pool_size = new_pool_size;
-
-        // 3. swap back
-        let return_amount = get_return_amount(l2_return_amount, pool.l2_pool_amount, pool.l1_pool_amount, pool.pool_size, pool.ann);
-        pool.l2_pool_amount = pool.l2_pool_amount + l2_return_amount;
-        pool.l1_pool_amount = pool.l1_pool_amount - return_amount;
-        pool.virtual_l2_balance = pool.virtual_l2_balance - l2_return_amount;
-
-        if (pool.virtual_l1_balance < return_amount) {
-            let remain = return_amount - pool.virtual_l1_balance;
-            module_store.l1_init_amount = module_store.l1_init_amount + remain;
-            pool.virtual_l1_balance = 0
-        } else {
-            pool.virtual_l1_balance = pool.virtual_l1_balance - return_amount;
-        }
-    }
+    let iter = table::iter(
+        &module_store.pools,
+        option::none(),
+        start_after,
+        2
+    );
+
+    let i = 0;
+    let res: vector<PoolsResponse> = vector[];
+    while (i < limit && table::prepare(iter)) {
+        let (ibc_op_init_metadata, pools) = table::next<Object<Metadata>, Pools>(iter);
+
+        vector::push_back(
+            &mut res,
+            PoolsResponse {
+                ibc_op_init_metadata,
+                ibc_op_init_denom: coin::symbol(ibc_op_init_metadata),
+                op_bridge_id: pools.op_bridge_id,
+                ibc_channel: pools.ibc_channel,
+                virtual_pool: pools.virtual_pool,
+                stableswap_pool: pools.stableswap_pool
+            }
+        );
+    };
+
+    return res
 }
 
-
- - + -## Function `update_module_params` +## Function `get_pools_detail` -
public entry fun update_module_params(chain: &signer, swap_fee_rate: option::Option<decimal128::Decimal128>, max_change_rate: option::Option<decimal128::Decimal128>)
+
#[view]
+public fun get_pools_detail(ibc_op_init_metadata: object::Object<fungible_asset::Metadata>): minitswap::PoolsDetailResponse
 
-
-Implementation +##### Implementation -
public entry fun update_module_params(
-    chain: &signer,
-    swap_fee_rate: Option<Decimal128>,
-    max_change_rate: Option<Decimal128>,
-) acquires ModuleStore {
-    assert_is_chain(chain);
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
+
public fun get_pools_detail(
+    ibc_op_init_metadata: Object<Metadata>
+): PoolsDetailResponse acquires ModuleStore, VirtualPool {
+    let module_store = borrow_global<ModuleStore>(@initia_std);
+    let pools = table::borrow(&module_store.pools, ibc_op_init_metadata);
+    let virtual_pool =
+        if (option::is_some(&pools.virtual_pool)) {
+            let vp =
+                borrow_global<VirtualPool>(
+                    object::object_address(&*option::borrow(&pools.virtual_pool))
+                );
+            option::some(
+                VirtualPoolDetail {
+                    pool_size: vp.pool_size,
+                    recover_velocity: vp.recover_velocity,
+                    max_ratio: vp.max_ratio,
+                    recover_param: vp.recover_param,
+                    init_pool_amount: vp.init_pool_amount,
+                    ibc_op_init_pool_amount: vp.ibc_op_init_pool_amount,
+                    last_recovered_timestamp: vp.last_recovered_timestamp,
+                    virtual_init_balance: vp.virtual_init_balance,
+                    virtual_ibc_op_init_balance: vp.virtual_ibc_op_init_balance,
+                    peg_keeper_owned_ibc_op_init_balance: vp.peg_keeper_owned_ibc_op_init_balance,
+                    ann: vp.ann,
+                    active: vp.active
+                }
+            )
+        } else {
+            option::none()
+        };
 
-    if (option::is_some(&swap_fee_rate)) {
-        module_store.swap_fee_rate = option::extract(&mut swap_fee_rate);
-    };
+    let stableswap_pool =
+        if (option::is_some(&pools.stableswap_pool)) {
+            option::some(
+                stableswap::get_pool(*option::borrow(&pools.stableswap_pool))
+            )
+        } else {
+            option::none()
+        };
 
-    if (option::is_some(&max_change_rate)) {
-        module_store.max_change_rate = option::extract(&mut max_change_rate);
-    };
+    return PoolsDetailResponse {
+        ibc_op_init_metadata,
+        ibc_op_init_denom: coin::symbol(ibc_op_init_metadata),
+        op_bridge_id: pools.op_bridge_id,
+        ibc_channel: pools.ibc_channel,
+        virtual_pool: virtual_pool,
+        stableswap_pool
+    }
 }
 
-
- - + -## Function `update_pool_params` +## Function `get_pools_detail_list` -
public entry fun update_pool_params(chain: &signer, l2_init_metadata: object::Object<fungible_asset::Metadata>, recover_velocity: option::Option<decimal128::Decimal128>, ann: option::Option<u64>, max_ratio: option::Option<decimal128::Decimal128>, recover_param: option::Option<decimal128::Decimal128>)
+
#[view]
+public fun get_pools_detail_list(start_after: option::Option<object::Object<fungible_asset::Metadata>>, limit: u64): vector<minitswap::PoolsDetailResponse>
 
-
-Implementation +##### Implementation -
public entry fun update_pool_params(
-    chain: &signer,
-    l2_init_metadata: Object<Metadata>,
-    recover_velocity: Option<Decimal128>,
-    ann: Option<u64>,
-    max_ratio: Option<Decimal128>,
-    recover_param: Option<Decimal128>,
-) acquires ModuleStore, VirtualPool {
-    assert_is_chain(chain);
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let pool_obj = table::borrow(&mut module_store.pools, l2_init_metadata);
-    let pool = borrow_global_mut<VirtualPool>(object::object_address(*pool_obj));
+
public fun get_pools_detail_list(
+    start_after: Option<Object<Metadata>>, limit: u64
+): vector<PoolsDetailResponse> acquires ModuleStore, VirtualPool {
+    let module_store = borrow_global<ModuleStore>(@initia_std);
 
-    if (option::is_some(&recover_velocity)) {
-        pool.recover_velocity = option::extract(&mut recover_velocity);
+    if (limit > MAX_LIMIT) {
+        limit = MAX_LIMIT
     };
 
-    // It is okay to change ann immediately cause there are no real provider
-    if (option::is_some(&ann)) {
-        pool.ann = option::extract(&mut ann);
-    };
+    let iter = table::iter(
+        &module_store.pools,
+        option::none(),
+        start_after,
+        2
+    );
 
-    if (option::is_some(&max_ratio)) {
-        pool.max_ratio = option::extract(&mut max_ratio);
+    let i = 0;
+    let res: vector<PoolsDetailResponse> = vector[];
+    while (i < limit && table::prepare(iter)) {
+        let (ibc_op_init_metadata, pools) = table::next<Object<Metadata>, Pools>(iter);
+
+        let virtual_pool =
+            if (option::is_some(&pools.virtual_pool)) {
+                let vp =
+                    borrow_global<VirtualPool>(
+                        object::object_address(
+                            &*option::borrow(&pools.virtual_pool)
+                        )
+                    );
+                option::some(
+                    VirtualPoolDetail {
+                        pool_size: vp.pool_size,
+                        recover_velocity: vp.recover_velocity,
+                        max_ratio: vp.max_ratio,
+                        recover_param: vp.recover_param,
+                        init_pool_amount: vp.init_pool_amount,
+                        ibc_op_init_pool_amount: vp.ibc_op_init_pool_amount,
+                        last_recovered_timestamp: vp.last_recovered_timestamp,
+                        virtual_init_balance: vp.virtual_init_balance,
+                        virtual_ibc_op_init_balance: vp.virtual_ibc_op_init_balance,
+                        peg_keeper_owned_ibc_op_init_balance: vp.peg_keeper_owned_ibc_op_init_balance,
+                        ann: vp.ann,
+                        active: vp.active
+                    }
+                )
+            } else {
+                option::none()
+            };
+
+        let stableswap_pool =
+            if (option::is_some(&pools.stableswap_pool)) {
+                option::some(
+                    stableswap::get_pool(*option::borrow(&pools.stableswap_pool))
+                )
+            } else {
+                option::none()
+            };
+
+        vector::push_back(
+            &mut res,
+            PoolsDetailResponse {
+                ibc_op_init_metadata,
+                ibc_op_init_denom: coin::symbol(ibc_op_init_metadata),
+                op_bridge_id: pools.op_bridge_id,
+                ibc_channel: pools.ibc_channel,
+                virtual_pool: virtual_pool,
+                stableswap_pool
+            }
+        )
     };
 
-    if (option::is_some(&recover_param)) {
-        pool.recover_param = option::extract(&mut recover_param);
-    };
+    return res
+
 }
 
-
- - + -## Function `provide` +## Function `unpack_unbond_response` -
public entry fun provide(account: &signer, amount: u64, min_return_amount: option::Option<u64>)
+
public fun unpack_unbond_response(res: minitswap::UnbondResponse): (address, u64, u64, u64)
 
-
-Implementation +##### Implementation -
public entry fun provide(account: &signer, amount: u64, min_return_amount: Option<u64>) acquires ModuleStore {
-    let l1_init = primary_fungible_store::withdraw(account, l1_init_metadata(), amount);
-    let share_token = provide_internal(l1_init);
-    assert_min_amount(&share_token, min_return_amount);
-    primary_fungible_store::deposit(signer::address_of(account), share_token);
+
public fun unpack_unbond_response(res: UnbondResponse): (address, u64, u64, u64) {
+    return (res.account, res.share_amount, res.withdraw_amount, res.release_time)
 }
 
-
- - + -## Function `withdraw` +## Function `unpack_arb_response` -
public entry fun withdraw(account: &signer, amount: u64, min_return_amount: option::Option<u64>)
+
public fun unpack_arb_response(res: minitswap::ArbResponse): (object::Object<fungible_asset::Metadata>, u64, u64, u64, u64, u64)
 
-
-Implementation +##### Implementation -
public entry fun withdraw(account: &signer, amount: u64, min_return_amount: Option<u64>) acquires ModuleStore {
-    let share_token = primary_fungible_store::withdraw(account, share_token_metadata(), amount);
-    let l1_init = withdraw_internal(share_token);
-    assert_min_amount(&l1_init, min_return_amount);
-    primary_fungible_store::deposit(signer::address_of(account), l1_init);
+
public fun unpack_arb_response(res: ArbResponse):
+    (Object<Metadata>, u64, u64, u64, u64, u64) {
+    return (
+        res.ibc_op_init_metadata,
+        res.id,
+        res.executed_time,
+        res.init_used,
+        res.ibc_op_init_sent,
+        res.triggering_fee
+    )
 }
 
-
+ + +## Function `unpack_module_store_response` - -## Function `swap` + +
public fun unpack_module_store_response(res: minitswap::ModuleStoreResponse): (bigdecimal::BigDecimal, bool, address, u64, u64, bigdecimal::BigDecimal, bigdecimal::BigDecimal, u64, u64, u64, u64, u64, u64)
+
-
public entry fun swap(account: &signer, offer_asset_metadata: object::Object<fungible_asset::Metadata>, return_metadata: object::Object<fungible_asset::Metadata>, amount: u64, min_return_amount: option::Option<u64>)
+##### Implementation
+
+
+
public fun unpack_module_store_response(
+    res: ModuleStoreResponse
+): (
+    BigDecimal,
+    bool,
+    address,
+    u64,
+    u64,
+    BigDecimal,
+    BigDecimal,
+    u64,
+    u64,
+    u64,
+    u64,
+    u64,
+    u64
+) {
+    return (
+        res.max_change_rate,
+        res.emergency_state,
+        res.admin,
+        res.depositor_owned_init,
+        res.unbond_period,
+        res.swap_fee_rate,
+        res.arb_fee_rate,
+        res.trigger_fee,
+        res.min_arb_profit,
+        res.ibc_timeout,
+        res.max_arb_batch,
+        res.min_arb_interval,
+        res.arb_batch_index
+    )
+}
 
-
-Implementation + +## Function `unpack_pools_response` -
public entry fun swap(
-    account: &signer,
-    offer_asset_metadata: Object<Metadata>,
-    return_metadata: Object<Metadata>,
-    amount: u64,
-    min_return_amount: Option<u64>
-) acquires ModuleStore, VirtualPool {
-    let offer_asset = primary_fungible_store::withdraw(account, offer_asset_metadata, amount);
-    let return_asset = swap_internal(offer_asset, return_metadata);
-    assert_min_amount(&return_asset, min_return_amount);
-    primary_fungible_store::deposit(signer::address_of(account), return_asset);
+
+
+
public fun unpack_pools_response(res: minitswap::PoolsResponse): (object::Object<fungible_asset::Metadata>, string::String, u64, string::String, option::Option<object::Object<minitswap::VirtualPool>>, option::Option<object::Object<stableswap::Pool>>)
+
+ + + +##### Implementation + + +
public fun unpack_pools_response(
+    res: PoolsResponse
+): (
+    Object<Metadata>,
+    String,
+    u64,
+    String,
+    Option<Object<VirtualPool>>,
+    Option<Object<Pool>>
+) {
+    return (
+        res.ibc_op_init_metadata,
+        res.ibc_op_init_denom,
+        res.op_bridge_id,
+        res.ibc_channel,
+        res.virtual_pool,
+        res.stableswap_pool
+    )
 }
 
-
+ + +## Function `unpack_pools_detail_response` + - -## Function `rebalance` +
public fun unpack_pools_detail_response(res: minitswap::PoolsDetailResponse): (object::Object<fungible_asset::Metadata>, string::String, u64, string::String, option::Option<minitswap::VirtualPoolDetail>, option::Option<stableswap::PoolResponse>)
+
-
public entry fun rebalance(account: &signer, l2_asset_metadata: object::Object<fungible_asset::Metadata>, amount: u64, min_return_amount: option::Option<u64>)
+##### Implementation
+
+
+
public fun unpack_pools_detail_response(
+    res: PoolsDetailResponse
+): (
+    Object<Metadata>,
+    String,
+    u64,
+    String,
+    Option<VirtualPoolDetail>,
+    Option<stableswap::PoolResponse>
+) {
+    let PoolsDetailResponse {
+        ibc_op_init_metadata,
+        ibc_op_init_denom,
+        op_bridge_id,
+        ibc_channel,
+        virtual_pool,
+        stableswap_pool
+    } = res;
+    return (
+        ibc_op_init_metadata,
+        ibc_op_init_denom,
+        op_bridge_id,
+        ibc_channel,
+        virtual_pool,
+        stableswap_pool
+    )
+}
 
-
-Implementation + +## Function `unpack_virtual_pool_detail` -
public entry fun rebalance(
-    account: &signer,
-    l2_asset_metadata: Object<Metadata>,
-    amount: u64,
-    min_return_amount: Option<u64>
-) acquires ModuleStore, VirtualPool {
-    let l1_init = primary_fungible_store::withdraw(account, l1_init_metadata(), amount);
-    let l2_init = rebalance_internal(l1_init, l2_asset_metadata);
-    assert_min_amount(&l2_init, min_return_amount);
-    primary_fungible_store::deposit(signer::address_of(account), l2_init);
-}
+
+
+
public fun unpack_virtual_pool_detail(res: minitswap::VirtualPoolDetail): (u64, bigdecimal::BigDecimal, bigdecimal::BigDecimal, bigdecimal::BigDecimal, u64, u64, u64, u64, u64, u64, u64, bool)
 
-
+##### Implementation - -## Function `provide_internal` +
public fun unpack_virtual_pool_detail(
+    res: VirtualPoolDetail
+): (u64, BigDecimal, BigDecimal, BigDecimal, u64, u64, u64, u64, u64, u64, u64, bool) {
+    return (
+        res.pool_size,
+        res.recover_velocity,
+        res.max_ratio,
+        res.recover_param,
+        res.init_pool_amount,
+        res.ibc_op_init_pool_amount,
+        res.last_recovered_timestamp,
+        res.virtual_init_balance,
+        res.virtual_ibc_op_init_balance,
+        res.peg_keeper_owned_ibc_op_init_balance,
+        res.ann,
+        res.active
+    )
+}
+
+ + + +## Function `create_pool` + -
public fun provide_internal(l1_init: fungible_asset::FungibleAsset): fungible_asset::FungibleAsset
+
+
public entry fun create_pool(chain: &signer, ibc_op_init_metadata: object::Object<fungible_asset::Metadata>, recover_velocity: bigdecimal::BigDecimal, pool_size: u64, ann: u64, max_ratio: bigdecimal::BigDecimal, recover_param: bigdecimal::BigDecimal, vm_type: u8, hook_contract: string::String, op_bridge_id: u64, ibc_channel: string::String)
 
-
-Implementation +##### Implementation + + +
public entry fun create_pool(
+    chain: &signer,
+    ibc_op_init_metadata: Object<Metadata>,
+    recover_velocity: BigDecimal,
+    pool_size: u64,
+    ann: u64,
+    max_ratio: BigDecimal,
+    recover_param: BigDecimal,
+    vm_type: u8,
+    hook_contract: String,
+    op_bridge_id: u64,
+    ibc_channel: String
+) acquires ModuleStore {
+    assert_is_chain(chain, false);
+    assert!(
+        pool_size > 0,
+        error::invalid_argument(EPOOL_SIZE)
+    );
+    let constructor_ref = object::create_object(@initia_std, false);
+    let extend_ref = object::generate_extend_ref(&constructor_ref);
+    let pool_signer = object::generate_signer(&constructor_ref);
+    let (_, timestamp) = block::get_block_info();
+
+    assert!(
+        vm_type == MOVE || vm_type == COSMWASM,
+        error::invalid_argument(EVM_TYPE)
+    );
 
+    check_bridge_info(
+        op_bridge_id,
+        ibc_channel,
+        ibc_op_init_metadata
+    );
 
-
public fun provide_internal(l1_init: FungibleAsset): FungibleAsset acquires ModuleStore {
-    assert!(is_l1_init(&l1_init), error::invalid_argument(ENOT_L1_INIT));
-    let provide_amount = fungible_asset::amount(&l1_init);
+    move_to(
+        &pool_signer,
+        VirtualPool {
+            ibc_op_init_metadata,
+            extend_ref,
+            recover_velocity,
+            pool_size,
+            max_ratio,
+            recover_param,
+            init_pool_amount: pool_size,
+            ibc_op_init_pool_amount: pool_size,
+            last_recovered_timestamp: timestamp,
+            virtual_init_balance: 0,
+            virtual_ibc_op_init_balance: 0,
+            peg_keeper_owned_ibc_op_init_balance: 0,
+            ann,
+            active: true,
+            op_bridge_id,
+            ibc_channel,
+            vm_type,
+            hook_contract,
+            arb_batch_map: table::new()
+        }
+    );
 
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let total_share = total_share();
-    let share_amount = if (total_share == 0) {
-        provide_amount
-    } else {
-        mul_div(provide_amount, (total_share as u64), module_store.l1_init_amount)
-    };
-    module_store.l1_init_amount =  module_store.l1_init_amount + provide_amount;
+    let pools =
+        borrow_pools_with_default(
+            module_store,
+            ibc_op_init_metadata,
+            op_bridge_id,
+            ibc_channel
+        );
 
-    let module_addr = object::address_from_extend_ref(&module_store.extend_ref);
-    primary_fungible_store::deposit(module_addr, l1_init);
-    event::emit<ProvideEvent>(
-        ProvideEvent {
-            provide_amount,
-            share_amount,
-        },
+    assert!(
+        option::is_none(&pools.virtual_pool),
+        error::already_exists(EVIRTUAL_POOL_EXISTS)
     );
-    coin::mint(&module_store.mint_cap, share_amount)
+    pools.virtual_pool = option::some(
+        object::object_from_constructor_ref<VirtualPool>(&constructor_ref)
+    );
+
+    event::emit(
+        CreatePoolEvent {
+            ibc_op_init_metadata,
+            recover_velocity,
+            pool_size,
+            ann,
+            max_ratio,
+            recover_param
+        }
+    )
 }
 
-
+ - +## Function `set_emergency_state` -## Function `withdraw_internal` - -
public fun withdraw_internal(share_token: fungible_asset::FungibleAsset): fungible_asset::FungibleAsset
+
public entry fun set_emergency_state(chain: &signer, state: bool)
 
-
-Implementation +##### Implementation -
public fun withdraw_internal(share_token: FungibleAsset): FungibleAsset acquires ModuleStore {
+
public entry fun set_emergency_state(chain: &signer, state: bool) acquires ModuleStore {
+    assert_is_chain(chain, true);
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let share_token_metadata = fungible_asset::metadata_from_asset(&share_token);
-    assert!(share_token_metadata == share_token_metadata(), error::invalid_argument(ENOT_SHARE_TOKEN));
-    let share_amount = fungible_asset::amount(&share_token);
-    let total_share = total_share();
-    let withdraw_amount = mul_div(share_amount, module_store.l1_init_amount, total_share);
-    module_store.l1_init_amount =  module_store.l1_init_amount - withdraw_amount;
-
-    coin::burn(&module_store.burn_cap, share_token);
-    let module_signer = object::generate_signer_for_extending(&module_store.extend_ref);
-    event::emit<WithdrawEvent>(
-        WithdrawEvent {
-            withdraw_amount,
-            share_amount,
-        },
-    );
-    primary_fungible_store::withdraw(&module_signer, l1_init_metadata(), withdraw_amount)
+    module_store.emergency_state = state
 }
 
-
+ + +## Function `deactivate` - -## Function `swap_internal` +
public entry fun deactivate(chain: &signer, ibc_op_init_metadata: object::Object<fungible_asset::Metadata>)
+
-
public fun swap_internal(offer_asset: fungible_asset::FungibleAsset, return_metadata: object::Object<fungible_asset::Metadata>): fungible_asset::FungibleAsset
+
+##### Implementation
+
+
+
public entry fun deactivate(
+    chain: &signer, ibc_op_init_metadata: Object<Metadata>
+) acquires ModuleStore, VirtualPool {
+    assert_is_chain(chain, true);
+    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
+    let pools = table::borrow(&mut module_store.pools, ibc_op_init_metadata);
+    let pool =
+        borrow_global_mut<VirtualPool>(
+            object::object_address(&*option::borrow(&pools.virtual_pool))
+        );
+    pool.active = false
+}
 
-
-Implementation + +## Function `activate` -
public fun swap_internal(
-    offer_asset: FungibleAsset,
-    return_metadata: Object<Metadata>,
-): FungibleAsset acquires ModuleStore, VirtualPool {
-    let (_, timestamp) = block::get_block_info();
-    let is_l1_init_offered = is_l1_init(&offer_asset);
-    let offer_metadata = fungible_asset::metadata_from_asset(&offer_asset);
-    let (module_store, pool, module_signer, pool_signer) = if(is_l1_init_offered) {
-        borrow_all_mut(return_metadata)
-    } else {
-        borrow_all_mut(offer_metadata)
-    };
-    assert!(pool.active, error::invalid_state(EINACTIVE));
 
-    let (peg_keeper_offer_amount, peg_keeper_return_amount) = calc_peg_keeper_swap(pool);
-    pool.l1_pool_amount = pool.l1_pool_amount + peg_keeper_offer_amount;
-    pool.l2_pool_amount = pool.l2_pool_amount - peg_keeper_return_amount;
-    pool.virtual_l1_balance = pool.virtual_l1_balance + peg_keeper_offer_amount;
-    pool.virtual_l2_balance = pool.virtual_l2_balance + peg_keeper_return_amount;
-    pool.last_recovered_timestamp = timestamp;
 
-    let module_addr = signer::address_of(&module_signer);
-    let pool_addr = signer::address_of(&pool_signer);
+
public entry fun activate(chain: &signer, ibc_op_init_metadata: object::Object<fungible_asset::Metadata>)
+
- // user swap - let offer_amount = fungible_asset::amount(&offer_asset); - let fee_amount = 0; - let return_asset = if (is_l1_init_offered) { - primary_fungible_store::deposit(module_addr, offer_asset); - // 0 fee for L1 > L2 - let return_amount = get_return_amount(offer_amount, pool.l1_pool_amount, pool.l2_pool_amount, pool.pool_size, pool.ann); - pool.l1_pool_amount = pool.l1_pool_amount + offer_amount; - pool.l2_pool_amount = pool.l2_pool_amount - return_amount; - assert!( - pool.l2_pool_amount >= pool.pool_size && pool.l1_pool_amount <= pool.pool_size, - error::invalid_state(EL2_PRICE_TOO_LOW), - ); - primary_fungible_store::withdraw(&pool_signer, return_metadata, return_amount) - } else { - primary_fungible_store::deposit(pool_addr, offer_asset); - let return_amount = get_return_amount(offer_amount, pool.l2_pool_amount, pool.l1_pool_amount, pool.pool_size, pool.ann); - fee_amount = decimal128::mul_u64(&module_store.swap_fee_rate, return_amount); - module_store.l1_init_amount = module_store.l1_init_amount + fee_amount; - pool.l1_pool_amount = pool.l1_pool_amount - return_amount; - pool.l2_pool_amount = pool.l2_pool_amount + offer_amount; - let return_amount = return_amount - fee_amount; - primary_fungible_store::withdraw(&module_signer, return_metadata, return_amount) - }; - event::emit<SwapEvent>( - SwapEvent { - offer_coin: offer_metadata, - return_coin: return_metadata, - peg_keeper_offer_amount, // always l1 init - peg_keeper_return_amount, // always l2 init - offer_amount, - return_amount: fungible_asset::amount(&return_asset), - fee_amount, // always l1 init - }, - ); - return_asset +##### Implementation + + +
public entry fun activate(
+    chain: &signer, ibc_op_init_metadata: Object<Metadata>
+) acquires ModuleStore, VirtualPool {
+    assert_is_chain(chain, true);
+    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
+    let pools = table::borrow(&mut module_store.pools, ibc_op_init_metadata);
+    let pool =
+        borrow_global_mut<VirtualPool>(
+            object::object_address(&*option::borrow(&pools.virtual_pool))
+        );
+    pool.active = true
 }
 
-
- - + -## Function `rebalance_internal` +## Function `change_pool_size` -
public fun rebalance_internal(l1_init: fungible_asset::FungibleAsset, l2_init_metadata: object::Object<fungible_asset::Metadata>): fungible_asset::FungibleAsset
+
public entry fun change_pool_size(chain: &signer, ibc_op_init_metadata: object::Object<fungible_asset::Metadata>, new_pool_size: u64)
 
-
-Implementation +##### Implementation -
public fun rebalance_internal(
-    l1_init: FungibleAsset,
-    l2_init_metadata: Object<Metadata>,
-): FungibleAsset acquires ModuleStore, VirtualPool {
-    assert!(is_l1_init(&l1_init), error::invalid_argument(ENOT_L1_INIT));
-    let (module_store, pool, module_signer, pool_signer) = borrow_all_mut(l2_init_metadata);
-    let amount = fungible_asset::amount(&l1_init);
-    let fee_amount = decimal128::mul_u64(&module_store.swap_fee_rate, amount);
-    module_store.l1_init_amount = module_store.l1_init_amount + fee_amount;
-    let offer_amount = amount - fee_amount;
-    assert!(offer_amount <= pool.virtual_l1_balance, error::invalid_argument(ENOT_ENOUGH_BALANCE));
-    let return_amount = mul_div(offer_amount, pool.virtual_l2_balance, pool.virtual_l1_balance);
-
-    pool.virtual_l1_balance = pool.virtual_l1_balance - offer_amount;
-    pool.virtual_l2_balance = pool.virtual_l2_balance - return_amount;
-    primary_fungible_store::deposit(signer::address_of(&module_signer), l1_init);
-
-    event::emit<RebalanceEvent>(
-        RebalanceEvent {
-            offer_coin: l1_init_metadata(), // always l1 init
-            return_coin: l2_init_metadata, // always l2 init
-            offer_amount: amount,
-            return_amount,
-            fee_amount,
-        },
+
public entry fun change_pool_size(
+    chain: &signer, ibc_op_init_metadata: Object<Metadata>, new_pool_size: u64
+) acquires ModuleStore, VirtualPool {
+    assert_is_chain(chain, false);
+    assert!(
+        new_pool_size > 0,
+        error::invalid_argument(EPOOL_SIZE)
     );
-    primary_fungible_store::withdraw(&pool_signer, l2_init_metadata, return_amount)
+    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
+    let pools = table::borrow(&mut module_store.pools, ibc_op_init_metadata);
+    let pool =
+        borrow_global_mut<VirtualPool>(
+            object::object_address(&*option::borrow(&pools.virtual_pool))
+        );
+
+    let change_rate =
+        if (new_pool_size > pool.pool_size) {
+            bigdecimal::from_ratio_u64(
+                new_pool_size - pool.pool_size,
+                pool.pool_size
+            )
+        } else {
+            bigdecimal::from_ratio_u64(
+                pool.pool_size - new_pool_size,
+                pool.pool_size
+            )
+        };
+
+    assert!(
+        bigdecimal::ge(module_store.max_change_rate, change_rate),
+        error::invalid_argument(EMAX_CHANGE)
+    );
+
+    let depositor_owned_init_increase =
+        if (new_pool_size < pool.pool_size) {
+            /*
+                Decrease size process
+                1. Change pool amount as ratio
+                2. Calculate diff, update peg keeper's balances
+
+                Net Effect
+                This action is same with swap INIT > ibc op INIT until pool ratio to be 5:5,
+                change pool size and sell some portion of ibc op INIT at same price
+                - INIT and ibc op INIT balances of peg keepers -> INIT decrease ibc op INIT increase,
+                    but INIT decreased amount is smaller than ibc op INIT increased amount.
+                - Pool ratio doesn't change (= price not change)
+            */
+            let current_init_delta = pool.pool_size - pool.init_pool_amount;
+            let current_ibc_op_init_delta =
+                pool.ibc_op_init_pool_amount - pool.pool_size;
+
+            let ratio = bigdecimal::from_ratio_u64(new_pool_size, pool.pool_size);
+            pool.init_pool_amount = bigdecimal::mul_by_u64_truncate(
+                ratio, pool.init_pool_amount
+            );
+            pool.ibc_op_init_pool_amount = bigdecimal::mul_by_u64_truncate(
+                ratio,
+                pool.ibc_op_init_pool_amount
+            );
+            pool.pool_size = new_pool_size;
+
+            let init_delta = pool.pool_size - pool.init_pool_amount;
+            let ibc_op_init_delta = pool.ibc_op_init_pool_amount - pool.pool_size;
+
+            let net_init_delta = current_init_delta - init_delta;
+            let net_ibc_op_init_delta = current_ibc_op_init_delta
+                - ibc_op_init_delta;
+
+            pool.virtual_init_balance = pool.virtual_init_balance + net_init_delta;
+            pool.virtual_ibc_op_init_balance = pool.virtual_ibc_op_init_balance
+                + net_ibc_op_init_delta;
+            pool.peg_keeper_owned_ibc_op_init_balance = pool.peg_keeper_owned_ibc_op_init_balance
+                + net_ibc_op_init_delta;
+            0
+        } else {
+            /*
+                Increase size process
+                1. Swap INIT > ibc init INIT to make 5:5
+                2. Change pool size
+                3. Swap back ibc init INIT > INIT
+                    a. If INIT init balance of peg keeper is greater than 0, return it to provider
+
+                Net Effect
+                - INIT and ibc init INIT balances of peg keepers -> + for INIT and even for ibc init INIT
+                - Ratio of pool -> ibc init INIT price decrease
+            */
+
+            // 1. swap to make 5:5
+            let init_swap_amount = pool.pool_size - pool.init_pool_amount;
+            let ibc_op_init_swap_amount = pool.ibc_op_init_pool_amount
+                - pool.pool_size;
+            // pool.init_pool_amount = pool.pool_size;
+            // pool.ibc_op_init_pool_amount = pool.pool_size;
+            pool.virtual_init_balance = pool.virtual_init_balance
+                + init_swap_amount;
+            pool.virtual_ibc_op_init_balance = pool.virtual_ibc_op_init_balance
+                + ibc_op_init_swap_amount;
+            pool.peg_keeper_owned_ibc_op_init_balance = pool.peg_keeper_owned_ibc_op_init_balance
+                + ibc_op_init_swap_amount;
+
+            // 2. change pool size
+            pool.init_pool_amount = new_pool_size;
+            pool.ibc_op_init_pool_amount = new_pool_size;
+            pool.pool_size = new_pool_size;
+
+            // 3. swap back
+            let return_amount =
+                get_return_amount(
+                    ibc_op_init_swap_amount,
+                    pool.ibc_op_init_pool_amount,
+                    pool.init_pool_amount,
+                    pool.pool_size,
+                    pool.ann
+                );
+            pool.ibc_op_init_pool_amount = pool.ibc_op_init_pool_amount
+                + ibc_op_init_swap_amount;
+            pool.init_pool_amount = pool.init_pool_amount - return_amount;
+            pool.virtual_ibc_op_init_balance = pool.virtual_ibc_op_init_balance
+                - ibc_op_init_swap_amount;
+            pool.peg_keeper_owned_ibc_op_init_balance = pool.peg_keeper_owned_ibc_op_init_balance
+                - ibc_op_init_swap_amount;
+
+            if (pool.virtual_init_balance < return_amount) {
+                let remain = return_amount - pool.virtual_init_balance;
+                module_store.depositor_owned_init = module_store.depositor_owned_init
+                    + remain;
+                pool.virtual_init_balance = 0;
+                remain
+            } else {
+                pool.virtual_init_balance = pool.virtual_init_balance
+                    - return_amount;
+                0
+            }
+        };
+
+    event::emit(
+        ChangePoolSizeEvent {
+            ibc_op_init_metadata,
+            pool_size: new_pool_size,
+            depositor_owned_init_increase
+        }
+    )
 }
 
-
- - + -## Function `borrow_all_mut` +## Function `update_module_params` -
fun borrow_all_mut(metadata: object::Object<fungible_asset::Metadata>): (&mut minitswap::ModuleStore, &mut minitswap::VirtualPool, signer, signer)
+
public entry fun update_module_params(chain: &signer, max_change_rate: option::Option<bigdecimal::BigDecimal>, admin: option::Option<address>, unbond_period: option::Option<u64>, swap_fee_rate: option::Option<bigdecimal::BigDecimal>, arb_fee_rate: option::Option<bigdecimal::BigDecimal>, trigger_fee: option::Option<u64>, min_arb_profit: option::Option<u64>, ibc_timeout: option::Option<u64>, max_arb_batch: option::Option<u64>, min_arb_interval: option::Option<u64>)
 
-
-Implementation +##### Implementation -
inline fun borrow_all_mut(metadata: Object<Metadata>): (&mut ModuleStore, &mut VirtualPool, signer, signer) acquires ModuleStore, VirtualPool {
+
public entry fun update_module_params(
+    chain: &signer,
+    max_change_rate: Option<BigDecimal>,
+    admin: Option<address>,
+    unbond_period: Option<u64>,
+    swap_fee_rate: Option<BigDecimal>,
+    arb_fee_rate: Option<BigDecimal>,
+    trigger_fee: Option<u64>,
+    min_arb_profit: Option<u64>,
+    ibc_timeout: Option<u64>,
+    max_arb_batch: Option<u64>,
+    min_arb_interval: Option<u64>
+) acquires ModuleStore {
+    assert_is_chain(chain, false);
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let module_signer = object::generate_signer_for_extending(&module_store.extend_ref);
-    let pool_addr = object::object_address(*table::borrow(&module_store.pools, metadata));
-    let pool = borrow_global_mut<VirtualPool>(pool_addr);
-    let pool_signer = object::generate_signer_for_extending(&pool.extend_ref);
-    (module_store, pool, module_signer, pool_signer)
-}
-
- - -
+ if (option::is_some(&max_change_rate)) { + module_store.max_change_rate = option::extract(&mut max_change_rate); + }; - + if (option::is_some(&admin)) { + module_store.admin = option::extract(&mut admin); + }; -## Function `borrow_all` + if (option::is_some(&unbond_period)) { + module_store.unbond_period = option::extract(&mut unbond_period); + }; + if (option::is_some(&swap_fee_rate)) { + module_store.swap_fee_rate = option::extract(&mut swap_fee_rate); + }; + if (option::is_some(&arb_fee_rate)) { + module_store.arb_fee_rate = option::extract(&mut arb_fee_rate); + }; -
fun borrow_all(metadata: object::Object<fungible_asset::Metadata>): (&minitswap::ModuleStore, &minitswap::VirtualPool)
-
+ if (option::is_some(&trigger_fee)) { + module_store.trigger_fee = option::extract(&mut trigger_fee); + }; + if (option::is_some(&min_arb_profit)) { + module_store.min_arb_profit = option::extract(&mut min_arb_profit); + }; + if (option::is_some(&ibc_timeout)) { + module_store.ibc_timeout = option::extract(&mut ibc_timeout); + }; -
-Implementation + if (option::is_some(&max_arb_batch)) { + module_store.max_arb_batch = option::extract(&mut max_arb_batch); + }; + if (option::is_some(&min_arb_interval)) { + module_store.min_arb_interval = option::extract(&mut min_arb_interval); + }; -
inline fun borrow_all(metadata: Object<Metadata>): (&ModuleStore, &VirtualPool) acquires ModuleStore, VirtualPool {
-    let module_store = borrow_global<ModuleStore>(@initia_std);
-    let pool_addr = object::object_address(*table::borrow(&module_store.pools, metadata));
-    let pool = borrow_global<VirtualPool>(pool_addr);
-    (module_store, pool)
+    assert!(
+        module_store.min_arb_profit > module_store.trigger_fee,
+        error::invalid_argument(ESMALL_ARB_PROFIT)
+    )
 }
 
-
- - + -## Function `calc_peg_keeper_swap` +## Function `update_pool_params` -
fun calc_peg_keeper_swap(pool: &minitswap::VirtualPool): (u64, u64)
+
public entry fun update_pool_params(chain: &signer, ibc_op_init_metadata: object::Object<fungible_asset::Metadata>, recover_velocity: option::Option<bigdecimal::BigDecimal>, ann: option::Option<u64>, max_ratio: option::Option<bigdecimal::BigDecimal>, recover_param: option::Option<bigdecimal::BigDecimal>, hook_contract: option::Option<string::String>)
 
-
-Implementation +##### Implementation + + +
public entry fun update_pool_params(
+    chain: &signer,
+    ibc_op_init_metadata: Object<Metadata>,
+    recover_velocity: Option<BigDecimal>,
+    ann: Option<u64>,
+    max_ratio: Option<BigDecimal>,
+    recover_param: Option<BigDecimal>,
+    hook_contract: Option<String>
+) acquires ModuleStore, VirtualPool {
+    assert_is_chain(chain, false);
+    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
+    let pools = table::borrow(&mut module_store.pools, ibc_op_init_metadata);
+    let pool =
+        borrow_global_mut<VirtualPool>(
+            object::object_address(&*option::borrow(&pools.virtual_pool))
+        );
+
+    if (option::is_some(&recover_velocity)) {
+        pool.recover_velocity = option::extract(&mut recover_velocity);
+    };
 
+    // It is okay to change ann immediately cause there are no real provider
+    if (option::is_some(&ann)) {
+        pool.ann = option::extract(&mut ann);
+    };
 
-
inline fun calc_peg_keeper_swap(pool: &VirtualPool): (u64, u64) acquires ModuleStore, VirtualPool {
-    let (_, timestamp) = block::get_block_info();
+    if (option::is_some(&max_ratio)) {
+        pool.max_ratio = option::extract(&mut max_ratio);
+    };
 
-    let imbalance = decimal128::from_ratio_u64(
-        pool.virtual_l2_balance + pool.l2_pool_amount - pool.pool_size, // same with real l2 balance
-        pool.pool_size,
-    );
-    // Peg keeper swap
-    let r_fr = get_fully_recovered_ratio(&imbalance, &pool.max_ratio, &pool.recover_param);
-    let current_ratio = decimal128::from_ratio_u64(pool.l2_pool_amount, pool.l1_pool_amount + pool.l2_pool_amount);
-    let time_diff = timestamp - pool.last_recovered_timestamp;
-    if (decimal128::val(¤t_ratio) > decimal128::val(&r_fr) && time_diff != 0) {
-        let (x_fr, _) = get_fully_recovered_pool_amounts(pool.pool_size, &r_fr, pool.ann);
-        let max_recover_amount = decimal128::mul_u64(&pool.recover_velocity, time_diff);
-        let swap_amount_to_reach_fr = x_fr - pool.l1_pool_amount;
-        let swap_amount = if (swap_amount_to_reach_fr < max_recover_amount) {
-            swap_amount_to_reach_fr
-        } else {
-            max_recover_amount
-        };
+    if (option::is_some(&recover_param)) {
+        pool.recover_param = option::extract(&mut recover_param);
+    };
 
-        let return_amount = get_return_amount(swap_amount, pool.l1_pool_amount, pool.l2_pool_amount, pool.pool_size, pool.ann);
+    if (option::is_some(&hook_contract)) {
+        pool.hook_contract = option::extract(&mut hook_contract);
+    };
 
-        (swap_amount, return_amount)
-    } else {
-        (0, 0)
-    }
+    event::emit(
+        UpdatePoolParamsEvent {
+            ibc_op_init_metadata,
+            recover_velocity,
+            ann,
+            max_ratio,
+            recover_param,
+            hook_contract
+        }
+    )
 }
 
-
- - + -## Function `l1_init_metadata` +## Function `provide` -
fun l1_init_metadata(): object::Object<fungible_asset::Metadata>
+
public entry fun provide(account: &signer, amount: u64, min_return_amount: option::Option<u64>)
 
-
-Implementation +##### Implementation -
fun l1_init_metadata(): Object<Metadata> {
-    let addr = object::create_object_address(@initia_std, b"uinit");
-    object::address_to_object<Metadata>(addr)
+
public entry fun provide(
+    account: &signer, amount: u64, min_return_amount: Option<u64>
+) acquires ModuleStore {
+    let init = primary_fungible_store::withdraw(account, init_metadata(), amount);
+    let share_token = provide_internal(init);
+    assert_min_amount(&share_token, min_return_amount);
+    primary_fungible_store::deposit(signer::address_of(account), share_token);
 }
 
-
- - + -## Function `share_token_metadata` +## Function `unbond` -
fun share_token_metadata(): object::Object<fungible_asset::Metadata>
+
public entry fun unbond(account: &signer, amount: u64)
 
-
-Implementation +##### Implementation -
fun share_token_metadata(): Object<Metadata> {
-    let addr = object::create_object_address(@initia_std, SYMBOL);
-    object::address_to_object<Metadata>(addr)
+
public entry fun unbond(account: &signer, amount: u64) acquires ModuleStore {
+    let share_token =
+        primary_fungible_store::withdraw(
+            account,
+            share_token_metadata(),
+            amount
+        );
+    unbond_internal(account, share_token);
 }
 
-
- - + -## Function `total_share` +## Function `withdraw_unbond` -
fun total_share(): u64
+
public entry fun withdraw_unbond(account: &signer, release_time: u64)
 
-
-Implementation +##### Implementation -
fun total_share(): u64 {
-    let supply = fungible_asset::supply(share_token_metadata());
-    (*option::borrow(&supply) as u64)
-}
-
- +
public entry fun withdraw_unbond(account: &signer, release_time: u64) acquires ModuleStore {
+    let addr = signer::address_of(account);
+    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
 
+    // check emergency
+    assert!(
+        !module_store.emergency_state,
+        error::invalid_state(EEMERGENCY)
+    );
 
-
+ // remove unbond entity + let key = generate_unbond_key(addr, release_time); + let UnbondEntity { account: _, share_amount, withdraw_amount, release_time } = + table::remove(&mut module_store.unbond_wait_list, key); - + // check release time + let (_, timestamp) = block::get_block_info(); + assert!( + timestamp >= release_time, + error::invalid_state(ERELEASE_TIME) + ); -## Function `assert_is_chain` + // release init + let module_signer = + object::generate_signer_for_extending(&module_store.extend_ref); + primary_fungible_store::transfer( + &module_signer, + init_metadata(), + addr, + withdraw_amount + ); + event::emit( + WithdrawUnbondEvent { + account: addr, + share_amount, + withdraw_amount, + release_time + } + ); +} +
-
fun assert_is_chain(_account: &signer)
-
+ +## Function `swap` -
-Implementation -
fun assert_is_chain(_account: &signer) {
-    // let addr = signer::address_of(account);
-    // assert!(addr == @initia_std, error::permission_denied(ENOT_CHAIN));
-}
+
public entry fun swap(account: &signer, offer_asset_metadata: object::Object<fungible_asset::Metadata>, return_asset_metadata: object::Object<fungible_asset::Metadata>, amount: u64, min_return_amount: option::Option<u64>)
 
-
- - +##### Implementation -## Function `mul_div` +
public entry fun swap(
+    account: &signer,
+    offer_asset_metadata: Object<Metadata>,
+    return_asset_metadata: Object<Metadata>,
+    amount: u64,
+    min_return_amount: Option<u64>
+) acquires ModuleStore, VirtualPool {
+    let offer_asset =
+        primary_fungible_store::withdraw(
+            account,
+            offer_asset_metadata,
+            amount
+        );
 
+    let return_asset = swap_internal(offer_asset, return_asset_metadata);
+    assert_min_amount(&return_asset, min_return_amount);
 
-
fun mul_div(a: u64, b: u64, c: u64): u64
+    primary_fungible_store::deposit(signer::address_of(account), return_asset);
+}
 
-
-Implementation + +## Function `finalize_arb` -
fun mul_div(a: u64, b: u64, c: u64): u64 {
-    let a = (a as u128);
-    let b = (b as u128);
-    let c = (c as u128);
-    (a * b / c as u64)
-}
-
+
public entry fun finalize_arb(account: &signer, arb_index: u64, output_index: u64, withdrawal_proofs: vector<string::String>, sender: address, sequence: u64, version: string::String, state_root: string::String, storage_root: string::String, latest_block_hash: string::String)
+
-
- -## Function `is_l1_init` +##### Implementation +
public entry fun finalize_arb(
+    account: &signer,
+    arb_index: u64,
+    output_index: u64,
+    withdrawal_proofs: vector<String>,
+    sender: address,
+    sequence: u64,
+    version: String,
+    state_root: String,
+    storage_root: String,
+    latest_block_hash: String
+) acquires ModuleStore, VirtualPool {
+    // check arb info
+    let module_store = borrow_global<ModuleStore>(@initia_std);
+    let pool_obj =
+        table::borrow(
+            &module_store.global_arb_batch_map,
+            table_key::encode_u64(arb_index)
+        );
+    let pool = borrow_global<VirtualPool>(object::object_address(&*pool_obj));
+    let arb_info =
+        table::borrow(
+            &pool.arb_batch_map,
+            table_key::encode_u64(arb_index)
+        );
 
-
fun is_l1_init(l1_init: &fungible_asset::FungibleAsset): bool
+    // execute finalize token withdrawal
+    let pool_signer = object::generate_signer_for_extending(&pool.extend_ref);
+    let withdrawal_msg =
+        generate_finalize_token_withdrawal_msg(
+            pool.op_bridge_id,
+            output_index,
+            withdrawal_proofs,
+            sender,
+            signer::address_of(&pool_signer),
+            sequence,
+            string::utf8(b"uinit"),
+            arb_info.ibc_op_init_sent,
+            version,
+            state_root,
+            storage_root,
+            latest_block_hash
+        );
+    cosmos::stargate(&pool_signer, withdrawal_msg);
+
+    // execute hook
+    let module_signer =
+        object::generate_signer_for_extending(&module_store.extend_ref);
+    cosmos::move_execute(
+        &module_signer,
+        @initia_std,
+        string::utf8(b"minitswap"),
+        string::utf8(b"finalize_arb_hook"),
+        vector[],
+        vector[
+            bcs::to_bytes(&arb_index),
+            bcs::to_bytes(&signer::address_of(account))
+        ]
+    );
+}
 
-
-Implementation + +## Function `finalize_arb_hook` -
fun is_l1_init(l1_init: &FungibleAsset): bool {
-    let fa_metadata = fungible_asset::metadata_from_asset(l1_init);
-    is_l1_init_metadata(fa_metadata)
-}
-
+
public entry fun finalize_arb_hook(module_signer: &signer, arb_index: u64, executor: address)
+
-
- -## Function `is_l1_init_metadata` +##### Implementation +
public entry fun finalize_arb_hook(
+    module_signer: &signer, arb_index: u64, executor: address
+) acquires ModuleStore, VirtualPool {
+    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
+    assert!(
+        signer::address_of(module_signer)
+            == object::address_from_extend_ref(&module_store.extend_ref),
+        error::permission_denied(EUNAUTHORIZED)
+    );
 
-
fun is_l1_init_metadata(metadata: object::Object<fungible_asset::Metadata>): bool
-
+ let pool_obj = + table::remove( + &mut module_store.global_arb_batch_map, + table_key::encode_u64(arb_index) + ); + let pool = borrow_global_mut<VirtualPool>(object::object_address(&pool_obj)); + let ArbInfo { executed_time: _, init_used, ibc_op_init_sent, triggering_fee } = + table::remove( + &mut pool.arb_batch_map, + table_key::encode_u64(arb_index) + ); + + assert!(pool.active, error::invalid_state(EINACTIVE)); + let pool_signer = object::generate_signer_for_extending(&pool.extend_ref); + // update pegkeeper owned balance + pool.peg_keeper_owned_ibc_op_init_balance = pool.peg_keeper_owned_ibc_op_init_balance + - ibc_op_init_sent; -
-Implementation + // transfer trigger fee + primary_fungible_store::transfer( + &pool_signer, + init_metadata(), + executor, + triggering_fee + ); + // transfer leftover to module_addr + let leftover_amount = ibc_op_init_sent - triggering_fee; + primary_fungible_store::transfer( + &pool_signer, + init_metadata(), + signer::address_of(module_signer), + leftover_amount + ); -
fun is_l1_init_metadata(metadata: Object<Metadata>): bool {
-    metadata == l1_init_metadata()
+    // update depositor owned init
+    let in_house_arb_profit = leftover_amount - init_used;
+    module_store.depositor_owned_init = module_store.depositor_owned_init
+        + in_house_arb_profit;
+
+    // emit event
+    event::emit(
+        FinalizeArbEvent {
+            arb_index,
+            pool: pool_obj,
+            init_used,
+            ibc_op_init_sent,
+            triggering_fee
+        }
+    );
 }
 
-
+ - +## Function `create_stableswap_pool` -## Function `get_d0` - -
fun get_d0(pool_size: u64, ann: u64): u64
+
public entry fun create_stableswap_pool(account: &signer, op_bridge_id: u64, ibc_channel: string::String, ibc_op_init_metadata: object::Object<fungible_asset::Metadata>, init_amount: u64, ibc_op_init_amount: u64)
 
-
-Implementation +##### Implementation + + +
public entry fun create_stableswap_pool(
+    account: &signer,
+    op_bridge_id: u64,
+    ibc_channel: String,
+    ibc_op_init_metadata: Object<Metadata>,
+    init_amount: u64,
+    ibc_op_init_amount: u64
+) acquires ModuleStore {
+    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
+    let (_, ibc_denom) =
+        check_bridge_info(
+            op_bridge_id,
+            ibc_channel,
+            ibc_op_init_metadata
+        );
 
+    let creator = object::generate_signer_for_extending(&module_store.extend_ref);
+    let symbol = string::utf8(b"INIT - ");
+    string::append(&mut symbol, ibc_denom);
+
+    let coins: vector<FungibleAsset> = vector[
+        coin::withdraw(
+            account,
+            init_metadata(),
+            init_amount
+        ),
+        coin::withdraw(
+            account,
+            ibc_op_init_metadata,
+            ibc_op_init_amount
+        )
+    ];
+
+    let liquidity_token =
+        stableswap::create_pool(
+            &creator,
+            symbol,
+            symbol,
+            module_store.stableswap_swap_fee_rate,
+            coins,
+            module_store.stableswap_ann
+        );
+    let metadata = fungible_asset::metadata_from_asset(&liquidity_token);
+    let pool = object::convert<Metadata, Pool>(metadata);
+
+    let pools =
+        borrow_pools_with_default(
+            module_store,
+            ibc_op_init_metadata,
+            op_bridge_id,
+            ibc_channel
+        );
+    pools.stableswap_pool = option::some(object::convert<Metadata, Pool>(metadata));
 
-
fun get_d0(pool_size: u64, ann: u64): u64 {
-    get_d(pool_size, pool_size, ann)
+    primary_fungible_store::deposit(signer::address_of(account), liquidity_token);
+    event::emit(CreateStableswapPoolEvent { ibc_op_init_metadata, pool });
 }
 
-
- - + -## Function `get_d` +## Function `provide_internal` -
fun get_d(l1_init_amount: u64, l2_init_amount: u64, ann: u64): u64
+
public fun provide_internal(init: fungible_asset::FungibleAsset): fungible_asset::FungibleAsset
 
-
-Implementation +##### Implementation -
fun get_d(l1_init_amount: u64, l2_init_amount: u64, ann: u64): u64 {
-    let l1_init_amount = (l1_init_amount as u256);
-    let l2_init_amount = (l2_init_amount as u256);
-    let ann = (ann as u256);
-
-    let sum = l1_init_amount + l2_init_amount;
-    if (sum == 0) return 0;
-    let d = sum;
+
public fun provide_internal(init: FungibleAsset): FungibleAsset acquires ModuleStore {
+    // check asset metadata
+    assert!(
+        is_init(&init),
+        error::invalid_argument(ENOT_INIT)
+    );
+    let provide_amount = fungible_asset::amount(&init);
 
-    let i = 0;
+    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
 
-    // converge
-    // d = (ann * sum - d_prod) / (ann - 1)
-    while (i < 255) {
-        let d_prev = d;
-        // D ** (n + 1) / (n ** n * prod) in our case, always n = 2
-        let d_prod = d * d * d / 4 / l1_init_amount / l2_init_amount;
+    // check emergency
+    assert!(
+        !module_store.emergency_state,
+        error::invalid_state(EEMERGENCY)
+    );
 
-        d = (ann * sum / A_PRECISION + d_prod * 2) * d / ((ann - A_PRECISION) * d / A_PRECISION + 3 * d_prod);
-        if (d > d_prev) {
-            if (d - d_prev <= 1) break
+    // calculate share amount
+    let total_share = total_share();
+    let share_amount =
+        if (total_share == 0) {
+            provide_amount
         } else {
-            if (d_prev - d <= 1) break
+            mul_div(
+                provide_amount,
+                (total_share as u64),
+                module_store.depositor_owned_init
+            )
         };
-        i = i + 1;
-    };
 
-    return (d as u64)
+    // update depositor owned init
+    module_store.depositor_owned_init = module_store.depositor_owned_init
+        + provide_amount;
+
+    // deposit token to module
+    let module_addr = object::address_from_extend_ref(&module_store.extend_ref);
+    primary_fungible_store::deposit(module_addr, init);
+
+    // emit event
+    event::emit<ProvideEvent>(ProvideEvent { provide_amount, share_amount });
+
+    // mint share token
+    coin::mint(&module_store.mint_cap, share_amount)
 }
 
-
+ - +## Function `unbond_internal` -## Function `get_return_amount` - -
fun get_return_amount(offer_amount: u64, offer_pool_amount: u64, return_pool_amount: u64, pool_size: u64, ann: u64): u64
+
public fun unbond_internal(account: &signer, share_token: fungible_asset::FungibleAsset)
 
-
-Implementation +##### Implementation -
fun get_return_amount(offer_amount: u64, offer_pool_amount: u64, return_pool_amount: u64, pool_size: u64, ann: u64): u64 {
-    let d = get_d0(pool_size, ann);
-    let offer_pool_amount_after = offer_pool_amount + offer_amount;
+
public fun unbond_internal(
+    account: &signer, share_token: FungibleAsset
+) acquires ModuleStore {
+    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
 
-    let y = get_y(d, offer_pool_amount_after, ann);
+    // check emergency
+    assert!(
+        !module_store.emergency_state,
+        error::invalid_state(EEMERGENCY)
+    );
 
-    (return_pool_amount - y as u64)
-}
-
+ // check metdata + let share_token_metadata = fungible_asset::metadata_from_asset(&share_token); + assert!( + share_token_metadata == share_token_metadata(), + error::invalid_argument(ENOT_SHARE_TOKEN) + ); + // calculate withdraw amount + let share_amount = fungible_asset::amount(&share_token); + let total_share = total_share(); + let withdraw_amount = + mul_div( + share_amount, + module_store.depositor_owned_init, + total_share + ); + // decrease depositor owned init + module_store.depositor_owned_init = module_store.depositor_owned_init + - withdraw_amount; -
+ // burn share token + coin::burn(&module_store.burn_cap, share_token); - + // get release time + let (_, timestamp) = block::get_block_info(); + let release_time = timestamp + module_store.unbond_period; -## Function `get_y` + // create and store withdraw entiry + let withdraw_entity = UnbondEntity { + account: signer::address_of(account), + share_amount, + withdraw_amount, + release_time + }; + let key = generate_unbond_key(signer::address_of(account), release_time); + table::add( + &mut module_store.unbond_wait_list, + key, + withdraw_entity + ); -get counterparty's amount + // emit event + event::emit<UnbondEvent>( + UnbondEvent { + account: signer::address_of(account), + share_amount, + withdraw_amount, + release_time + } + ); +} +
-
fun get_y(d: u64, x: u64, ann: u64): u64
-
+ +## Function `swap_internal` -
-Implementation -
fun get_y(d: u64, x: u64, ann: u64): u64 {
-    let d = (d as u256);
-    let x = (x as u256);
-    let ann = (ann as u256);
+
public fun swap_internal(offer_asset: fungible_asset::FungibleAsset, return_metadata: object::Object<fungible_asset::Metadata>): fungible_asset::FungibleAsset
+
- // Done by solving quadratic equation iteratively. - // x_1**2 + x_1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A) - // y**2 + y * (x - (A * 2**2 - 1) * D / (A * 2**2)) = D ** (2 + 1) / (2 ** (2 * 2) * x * A) - // y**2 + b*y = c - // y = (y**2 + c) / (2*y + b) - let c = d * d * d * A_PRECISION / ann / 4 / x; // d ** (2 + 1) / ann / 2 ** 2 / x - let b_plus_d = x + d * A_PRECISION / ann; // need to sub d but sub later due to value must be less than 0 +##### Implementation - let y_prev; - let y = d; - let i = 0; - // converge - while (i < 255) { - y_prev = y; - y = (y * y + c) / (2 * y + b_plus_d - d); // sub d here +
public fun swap_internal(
+    offer_asset: FungibleAsset, return_metadata: Object<Metadata>
+): FungibleAsset acquires ModuleStore, VirtualPool {
+    let is_init_offered = is_init(&offer_asset);
+    let offer_metadata = fungible_asset::metadata_from_asset(&offer_asset);
+    let offer_amount = fungible_asset::amount(&offer_asset);
+    let ibc_op_init_metadata = offer_metadata;
+    let (module_store, pool, module_signer, pool_signer) =
+        if (is_init_offered) {
+            ibc_op_init_metadata = return_metadata;
+            borrow_all_mut(return_metadata)
+        } else {
+            borrow_all_mut(offer_metadata)
+        };
+    assert!(pool.active, error::invalid_state(EINACTIVE));
 
-        if (y > y_prev) {
-            if (y - y_prev <= 1) break
+    // init offered, do user swap first
+    let (
+        peg_keeper_offer_amount,
+        peg_keeper_return_amount,
+        return_asset,
+        init_swap_fee_amount,
+        init_arb_fee_amount,
+        ibc_op_init_swap_fee_amount,
+        ibc_op_init_arb_fee_amount
+    ) =
+        if (is_init_offered) {
+            // user swap
+            let (
+                return_asset, swap_fee_amount, arb_fee_amount, depositor_return_amount
+            ) =
+                user_swap(
+                    offer_asset,
+                    return_metadata,
+                    module_store,
+                    pool,
+                    module_signer,
+                    pool_signer,
+                    is_init_offered
+                );
+
+            // peg keeper swap
+            let (peg_keeper_offer_amount, peg_keeper_return_amount) =
+                peg_keeper_swap(pool);
+
+            // to prevent div by zero
+            let init_arb_fee_amount =
+                if (arb_fee_amount == 0) { 0 }
+                else {
+                    mul_div(
+                        depositor_return_amount,
+                        arb_fee_amount,
+                        arb_fee_amount + swap_fee_amount
+                    )
+                };
+
+            let init_swap_fee_amount = depositor_return_amount
+                - init_arb_fee_amount;
+
+            (
+                peg_keeper_offer_amount,
+                peg_keeper_return_amount,
+                return_asset,
+                init_swap_fee_amount,
+                init_arb_fee_amount,
+                swap_fee_amount,
+                arb_fee_amount
+            )
+            // if ibc op init offered, do peg keeper swap first
         } else {
-            if (y_prev - y <= 1) break
+            // peg keeper swap
+            let (peg_keeper_offer_amount, peg_keeper_return_amount) =
+                peg_keeper_swap(pool);
+
+            // user swap
+            let (return_asset, swap_fee_amount, arb_fee_amount, _) =
+                user_swap(
+                    offer_asset,
+                    return_metadata,
+                    module_store,
+                    pool,
+                    module_signer,
+                    pool_signer,
+                    is_init_offered
+                );
+
+            (
+                peg_keeper_offer_amount,
+                peg_keeper_return_amount,
+                return_asset,
+                swap_fee_amount,
+                arb_fee_amount,
+                0,
+                0
+            )
         };
-        i = i + 1;
-    };
 
-    (y as u64)
+    // check arb
+    check_arb(
+        module_store,
+        pool,
+        ibc_op_init_metadata
+    );
+
+    event::emit<SwapEvent>(
+        SwapEvent {
+            offer_coin: offer_metadata,
+            return_coin: return_metadata,
+            peg_keeper_offer_amount, // always init
+            peg_keeper_return_amount, // always ibc op init
+            offer_amount,
+            return_amount: fungible_asset::amount(&return_asset),
+            init_swap_fee_amount,
+            init_arb_fee_amount,
+            ibc_op_init_swap_fee_amount,
+            ibc_op_init_arb_fee_amount
+        }
+    );
+
+    return_asset
 }
 
-
- - + -## Function `get_fully_recovered_ratio` +## Function `ibc_ack` -
fun get_fully_recovered_ratio(imbalance: &decimal128::Decimal128, max_ratio: &decimal128::Decimal128, recover_param: &decimal128::Decimal128): decimal128::Decimal128
+
public entry fun ibc_ack(pool_signer: &signer, callback_id: u64, success: bool)
 
-
-Implementation +##### Implementation -
fun get_fully_recovered_ratio(imbalance: &Decimal128, max_ratio: &Decimal128, recover_param: &Decimal128): Decimal128 {
-    let fi = decimal128_safe_mul(recover_param, imbalance);
-    let fi3 = decimal128_safe_mul(&fi, &decimal128_safe_mul(&fi, &fi));
-    let half = decimal128::from_ratio(1, 2); // .5
-    let to_sum = decimal128_safe_mul(
-        &decimal128::sub(max_ratio, &half), // R_max - 0.5
-        &decimal128_safe_from_ratio(
-            decimal128::val(&fi3),
-            decimal128::val(&decimal128::add(&decimal128::one(), &fi3)),
-        ) // (f * I) ** 3 / (1 + (f * I) ** 3)
+
public entry fun ibc_ack(
+    pool_signer: &signer, callback_id: u64, success: bool
+) acquires ModuleStore, VirtualPool {
+    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
+    let pool_obj =
+        table::borrow(
+            &mut module_store.global_arb_batch_map,
+            table_key::encode_u64(callback_id)
+        );
+    let pool = borrow_global_mut<VirtualPool>(object::object_address(&*pool_obj));
+    assert!(
+        signer::address_of(pool_signer)
+            == object::address_from_extend_ref(&pool.extend_ref),
+        error::permission_denied(EUNAUTHORIZED)
     );
 
-    decimal128::add(&half, &to_sum)
+    // do nothing
+    if (success) { return };
+
+    revert_arb_state(callback_id);
 }
 
-
+ - +## Function `ibc_timeout` -## Function `get_fully_recovered_pool_amounts` - -
fun get_fully_recovered_pool_amounts(pool_size: u64, fully_recovered_ratio: &decimal128::Decimal128, ann: u64): (u64, u64)
+
public entry fun ibc_timeout(pool_signer: &signer, callback_id: u64)
 
-
-Implementation - +##### Implementation -
fun get_fully_recovered_pool_amounts(pool_size: u64, fully_recovered_ratio: &Decimal128, ann: u64): (u64, u64) {
-    let denominator = decimal128::val(&decimal128::one());
-    let fully_recovered_ratio_val = decimal128::val(fully_recovered_ratio);
-    let grad = decimal128::from_ratio(fully_recovered_ratio_val, denominator - fully_recovered_ratio_val);
-    let grad_val = decimal128::val(&grad);
 
-    // Increase the value if you want more accurate values, or decrease the value if you want less calculations.
-    let sim_size = 100000000u128;
-    let sim_size_val = sim_size * denominator;
-
-    // Get first point
-    let d0 = get_d0((sim_size as u64), ann);
-    let x = 2 * sim_size_val / (grad_val + denominator); // x = 2z / (g + 1)
-    if (x == sim_size) { // fully_recovered_ratio = 0.5
-        return (pool_size, pool_size)
-    };
-    let y = (get_y(d0, (x as u64), ann) as u128);
-
-    let i = 0;
-    let x_prev;
-    // get the cross point of y = grad * x and [(sim_size, sim_size), (x_prev), (y_prev)]
-    // the point is (temp_x, y), get x from y
-    while (i < 255) {
-        x_prev = x;
-        // x = z * (x' - y') / (g * (x'- z) - (y' - z))
-        // x = z * (y' - x') / (g * (z - x') + (y' - z))
-        let temp_x = sim_size * (y - x) * denominator / (grad_val * (sim_size - x) + (y - sim_size) * denominator);
-        let y = decimal128::mul_u128(&grad, temp_x);
-        x = (get_y(d0, (y as u64), ann) as u128);
-
-        // when fully recovered rate is too close to 0.5 y can be same with sim_size
-        if (y == sim_size) break;
-
-        // when fully recovered rate is too close to 0.5 x can be slightly higher than sim_size
-        if (x > sim_size) {
-            x = sim_size;
-            break
-        };
-
-        if (x > x_prev) {
-            if (x - x_prev <= 1) break
-        } else {
-            if (x_prev - x <= 1) break
-        };
-        i = i + 1;
-    };
+
public entry fun ibc_timeout(
+    pool_signer: &signer, callback_id: u64
+) acquires ModuleStore, VirtualPool {
+    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
+    let pool_obj =
+        table::borrow(
+            &mut module_store.global_arb_batch_map,
+            table_key::encode_u64(callback_id)
+        );
+    let pool = borrow_global_mut<VirtualPool>(object::object_address(&*pool_obj));
+    assert!(
+        signer::address_of(pool_signer)
+            == object::address_from_extend_ref(&pool.extend_ref),
+        error::permission_denied(EUNAUTHORIZED)
+    );
 
-    // scale up/down to real pool size
-    (
-        (x * (pool_size as u128) / sim_size as u64),
-        (y * (pool_size as u128) / sim_size as u64)
-    )
+    revert_arb_state(callback_id);
 }
 
-
+ - +## Function `safe_swap_simulation` -## Function `decimal128_safe_mul` - -
fun decimal128_safe_mul(a: &decimal128::Decimal128, b: &decimal128::Decimal128): decimal128::Decimal128
+
public fun safe_swap_simulation(offer_metadata: object::Object<fungible_asset::Metadata>, return_metadata: object::Object<fungible_asset::Metadata>, offer_amount: u64): (u64, u64)
 
-
-Implementation - - -
fun decimal128_safe_mul(a: &Decimal128, b: &Decimal128): Decimal128 {
-    let a_val = (decimal128::val(a) as u256);
-    let b_val = (decimal128::val(b) as u256);
-    let one = (decimal128::val(&decimal128::one()) as u256);
-    let val = (a_val * b_val / one as u128);
-    decimal128::new(val)
-}
-
- +##### Implementation -
+
public fun safe_swap_simulation(
+    offer_metadata: Object<Metadata>,
+    return_metadata: Object<Metadata>,
+    offer_amount: u64
+): (u64, u64) acquires ModuleStore, VirtualPool {
+    let is_init_offered = is_init_metadata(offer_metadata);
+    let ibc_op_init_metadata =
+        if (is_init_offered) {
+            return_metadata
+        } else {
+            offer_metadata
+        };
 
-
+    let virtual_pool_exists = virtual_pool_exists(ibc_op_init_metadata);
 
-## Function `decimal128_safe_from_ratio`
+    assert!(
+        virtual_pool_exists,
+        error::invalid_argument(EPOOL_NOT_FOUND)
+    );
 
+    let (init_pool_amount, ibc_op_init_pool_amount) =
+        get_pool_amount(ibc_op_init_metadata, !is_init_offered);
+    let (module_store, pool) = borrow_all(ibc_op_init_metadata);
+    let (pool_size, ann) = (pool.pool_size, pool.ann);
+    let (return_amount, fee_amount) =
+        if (is_init_offered) {
+            let return_amount =
+                get_return_amount(
+                    offer_amount,
+                    init_pool_amount,
+                    ibc_op_init_pool_amount,
+                    pool_size,
+                    ann
+                );
+
+            if (ibc_op_init_pool_amount - return_amount < pool_size) {
+                return (0, 0)
+            };
+
+            // take swap fee
+            let swap_fee_amount =
+                bigdecimal::mul_by_u64_ceil(
+                    module_store.swap_fee_rate,
+                    return_amount
+                );
+
+            // take arb fee
+            let arb_profit =
+                if (return_amount > offer_amount + swap_fee_amount) {
+                    return_amount - swap_fee_amount - offer_amount
+                } else { 0 };
+            let arb_fee_amount =
+                bigdecimal::mul_by_u64_ceil(
+                    module_store.arb_fee_rate,
+                    arb_profit
+                );
+            let fee_amount = swap_fee_amount + arb_fee_amount;
+
+            (return_amount, fee_amount)
+        } else {
+            let return_amount =
+                get_return_amount(
+                    offer_amount,
+                    ibc_op_init_pool_amount,
+                    init_pool_amount,
+                    pool_size,
+                    ann
+                );
+            let fee_amount =
+                bigdecimal::mul_by_u64_ceil(
+                    module_store.swap_fee_rate,
+                    return_amount
+                );
+
+            (return_amount, fee_amount)
+        };
 
+    return_amount = return_amount - fee_amount;
 
-
fun decimal128_safe_from_ratio(a: u128, b: u128): decimal128::Decimal128
+    (return_amount, fee_amount)
+}
 
-
-Implementation - - -
fun decimal128_safe_from_ratio(a: u128, b: u128): Decimal128 {
-    let a = (a as u256);
-    let b = (b as u256);
-    let one = (decimal128::val(&decimal128::one()) as u256);
-    let val = (a * one / b as u128);
-    decimal128::new(val)
-}
-
+ +## Function `safe_swap_simulation_given_out` -
- +
public fun safe_swap_simulation_given_out(offer_metadata: object::Object<fungible_asset::Metadata>, return_metadata: object::Object<fungible_asset::Metadata>, return_amount: u64): (u64, u64)
+
-## Function `assert_min_amount` +##### Implementation -
fun assert_min_amount(fa: &fungible_asset::FungibleAsset, min_return: option::Option<u64>)
-
+
public fun safe_swap_simulation_given_out(
+    offer_metadata: Object<Metadata>,
+    return_metadata: Object<Metadata>,
+    return_amount: u64
+): (u64, u64) acquires ModuleStore, VirtualPool {
+    let is_init_offered = is_init_metadata(offer_metadata);
+    let ibc_op_init_metadata =
+        if (is_init_offered) {
+            return_metadata
+        } else {
+            offer_metadata
+        };
 
+    let virtual_pool_exists = virtual_pool_exists(ibc_op_init_metadata);
 
-
-Implementation + assert!( + virtual_pool_exists, + error::invalid_argument(EPOOL_NOT_FOUND) + ); + let (init_pool_amount, ibc_op_init_pool_amount) = + get_pool_amount(ibc_op_init_metadata, !is_init_offered); + let (module_store, pool) = borrow_all(ibc_op_init_metadata); + let (pool_size, ann) = (pool.pool_size, pool.ann); + let (offer_amount, fee_amount) = + if (is_init_offered) { + // first assume there are no arb fee and calculate offer amount + // and then calculate arb fee and get actual return amount which is same with return_amount_before_swap_fee - swap_fee_amount - arb_fee_amount + // to make actual return amount to return amount, set return_amount_before_swap_fee = return_amount_before_swap_fee + return_diff + // where return_diff = target return amount - actual return amount + // and recalculate offer amount repeatly until return amount <= actual return amount + // note that actual return is always small or equal with target return amount + + // adjust fee. return amount before swap fee = return amount * 1 / (1 - f) + let return_amount_before_swap_fee = + bigdecimal::truncate_u64( + bigdecimal::div( + bigdecimal::from_u64(return_amount), + bigdecimal::sub(bigdecimal::one(), module_store.swap_fee_rate) + ) + ); + if (ibc_op_init_pool_amount - return_amount_before_swap_fee < pool_size) { + return ((U64_MAX as u64), (U64_MAX as u64)) + }; + + let swap_fee_amount = return_amount_before_swap_fee - return_amount; + + let offer_amount = + get_offer_amount( + return_amount_before_swap_fee, + init_pool_amount, + ibc_op_init_pool_amount, + pool_size, + ann + ); + + // calculate arb fee + let arb_profit = + if (return_amount > offer_amount) { + return_amount - offer_amount + } else { 0 }; + let arb_fee_amount = + bigdecimal::mul_by_u64_ceil( + module_store.arb_fee_rate, + arb_profit + ); + + // actual return amount is return amount - arb fee + let actual_return_amount = return_amount - arb_fee_amount; + let return_diff = arb_fee_amount; + + // retry while actual return amount is equal to return amount + let i = 0; + while (return_amount > actual_return_amount && i < 255) { + return_amount_before_swap_fee = return_amount_before_swap_fee + + return_diff; + + if (ibc_op_init_pool_amount - return_amount_before_swap_fee + < pool_size) { + return ((U64_MAX as u64), (U64_MAX as u64)) + }; + + swap_fee_amount = bigdecimal::mul_by_u64_ceil( + module_store.swap_fee_rate, + return_amount_before_swap_fee + ); + + offer_amount = get_offer_amount( + return_amount_before_swap_fee, + init_pool_amount, + ibc_op_init_pool_amount, + pool_size, + ann + ); + + // calculate arb fee + arb_profit = if (return_amount > offer_amount) { + return_amount_before_swap_fee - swap_fee_amount - offer_amount + } else { 0 }; + arb_fee_amount = bigdecimal::mul_by_u64_ceil( + module_store.arb_fee_rate, + arb_profit + ); + actual_return_amount = return_amount_before_swap_fee + - swap_fee_amount - arb_fee_amount; + if (actual_return_amount >= return_amount) break; + + return_diff = return_amount - actual_return_amount; + i = i + 1; + }; + + (offer_amount, swap_fee_amount + arb_fee_amount) + } else { + // adjust fee. amount = amount * 1 / (1 - f) + let return_amount_ = + bigdecimal::truncate_u64( + bigdecimal::div( + bigdecimal::from_u64(return_amount), + bigdecimal::sub(bigdecimal::one(), module_store.swap_fee_rate) + ) + ); + let fee_amount = return_amount_ - return_amount; + + let offer_amount = + get_offer_amount( + return_amount_, + ibc_op_init_pool_amount, + init_pool_amount, + pool_size, + ann + ); + + (offer_amount, fee_amount) + }; -
fun assert_min_amount(fa: &FungibleAsset, min_return: Option<u64>) {
-    if (option::is_some(&min_return)) {
-        let amount = fungible_asset::amount(fa);
-        assert!(amount >= option::extract(&mut min_return), error::invalid_state(EMIN_RETURN))
-    }
+    (offer_amount, fee_amount)
 }
 
- - - -
diff --git a/initia_stdlib/doc/multisig.md b/initia_stdlib/doc/multisig.md index 6e11339..0a881a7 100644 --- a/initia_stdlib/doc/multisig.md +++ b/initia_stdlib/doc/multisig.md @@ -21,16 +21,10 @@ - [Function `get_config`](#0x1_multisig_get_config) - [Function `create_multisig_account`](#0x1_multisig_create_multisig_account) - [Function `create_proposal`](#0x1_multisig_create_proposal) +- [Function `create_proposal_with_json`](#0x1_multisig_create_proposal_with_json) - [Function `vote_proposal`](#0x1_multisig_vote_proposal) - [Function `execute_proposal`](#0x1_multisig_execute_proposal) - [Function `update_config`](#0x1_multisig_update_config) -- [Function `is_proposal_expired`](#0x1_multisig_is_proposal_expired) -- [Function `vote`](#0x1_multisig_vote) -- [Function `yes_vote_count`](#0x1_multisig_yes_vote_count) -- [Function `proposal_to_proposal_response`](#0x1_multisig_proposal_to_proposal_response) -- [Function `assert_member`](#0x1_multisig_assert_member) -- [Function `assert_config_version`](#0x1_multisig_assert_config_version) -- [Function `assert_proposal`](#0x1_multisig_assert_proposal)
use 0x1::block;
@@ -53,8 +47,8 @@
 ## Struct `Period`
 
 Period represents a time period with optional expiry conditions.
-If both height and timestamp are None, the period is considered to never expire.
-If both height and timestamp are set, and only one of them has expired, the period is considered expired.
+If both height and timestamp are None, the period is considered to never expire.
+If both height and timestamp are set, and only one of them has expired, the period is considered expired.
 
 
 
struct Period has copy, drop, store
@@ -62,8 +56,7 @@ If both height and timestamp are set, and only one of
 
 
 
-
-Fields +##### Fields
@@ -74,7 +67,7 @@ If both height and timestamp are set, and only one of
-timestamp: option::Option<u64> +timestamp: option::Option<u64>
@@ -82,8 +75,6 @@ If both height and timestamp are set, and only one of
-
- ## Resource `MultisigWallet` @@ -95,8 +86,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -139,8 +129,6 @@ If both height and timestamp are set, and only one of
-
- ## Struct `Proposal` @@ -152,8 +140,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -217,10 +204,20 @@ If both height and timestamp are set, and only one of
-
+
+is_json: bool +
+
+
+
+json_args: vector<string::String> +
+
+ +
+
- @@ -234,8 +231,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -266,8 +262,6 @@ If both height and timestamp are set, and only one of
-
- ## Struct `CreateProposalEvent` @@ -280,8 +274,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -336,8 +329,6 @@ If both height and timestamp are set, and only one of
-
- ## Struct `VoteProposalEvent` @@ -350,8 +341,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -382,8 +372,6 @@ If both height and timestamp are set, and only one of
-
- ## Struct `ExecuteProposalEvent` @@ -396,8 +384,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -422,8 +409,6 @@ If both height and timestamp are set, and only one of
-
- ## Struct `UpdateConfigEvent` @@ -436,8 +421,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -468,8 +452,6 @@ If both height and timestamp are set, and only one of
-
- ## Struct `ProposalResponse` @@ -481,8 +463,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -558,10 +539,20 @@ If both height and timestamp are set, and only one of
-
+
+is_json: bool +
+
+
+
+json_args: vector<string::String> +
+
+ +
+ -
@@ -574,8 +565,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -612,8 +602,6 @@ If both height and timestamp are set, and only one of
-
- ## Constants @@ -695,7 +683,7 @@ If both height and timestamp are set, and only one of -
const EPROPOSAL_NOT_FOUND: u64 = 8;
+
const EPROPOSAL_NOT_FOUND: u64 = 9;
 
@@ -730,21 +718,25 @@ If both height and timestamp are set, and only one of -
-Implementation +##### Implementation -
public fun get_proposal(multisig_addr: address, proposal_id: u64): ProposalResponse acquires MultisigWallet {
+
public fun get_proposal(
+    multisig_addr: address, proposal_id: u64
+): ProposalResponse acquires MultisigWallet {
     let multisig_wallet = borrow_global<MultisigWallet>(multisig_addr);
     let proposal = table::borrow(&multisig_wallet.proposals, proposal_id);
-    proposal_to_proposal_response(multisig_wallet, multisig_addr, proposal_id, proposal)
+    proposal_to_proposal_response(
+        multisig_wallet,
+        multisig_addr,
+        proposal_id,
+        proposal
+    )
 }
 
-
- ## Function `get_proposals` @@ -757,19 +749,36 @@ If both height and timestamp are set, and only one of -
-Implementation +##### Implementation -
public fun get_proposals(multisig_addr: address, start_after: Option<u64>, limit: u8): vector<ProposalResponse> acquires MultisigWallet {
-    if (limit > MAX_LIMIT) { limit = MAX_LIMIT };
+
public fun get_proposals(
+    multisig_addr: address, start_after: Option<u64>, limit: u8
+): vector<ProposalResponse> acquires MultisigWallet {
+    if (limit > MAX_LIMIT) {
+        limit = MAX_LIMIT
+    };
     let res: vector<ProposalResponse> = vector[];
     let multisig_wallet = borrow_global<MultisigWallet>(multisig_addr);
-    let iter = table::iter(&multisig_wallet.proposals, option::none(), start_after, 2);
+    let iter = table::iter(
+        &multisig_wallet.proposals,
+        option::none(),
+        start_after,
+        2
+    );
 
-    while (vector::length(&res) < (limit as u64) && table::prepare<u64, Proposal>(&mut iter)) {
-        let (proposal_id, proposal) = table::next<u64, Proposal>(&mut iter);
-        vector::push_back(&mut res, proposal_to_proposal_response(multisig_wallet, multisig_addr, proposal_id, proposal));
+    while (vector::length(&res) < (limit as u64)
+        && table::prepare<u64, Proposal>(iter)) {
+        let (proposal_id, proposal) = table::next<u64, Proposal>(iter);
+        vector::push_back(
+            &mut res,
+            proposal_to_proposal_response(
+                multisig_wallet,
+                multisig_addr,
+                proposal_id,
+                proposal
+            )
+        );
     };
 
     res
@@ -778,8 +787,6 @@ If both height and timestamp are set, and only one of
 
 
 
-
- ## Function `get_config` @@ -792,8 +799,7 @@ If both height and timestamp are set, and only one of -
-Implementation +##### Implementation
public fun get_config(multisig_addr: address): ConfigResponse acquires MultisigWallet {
@@ -804,15 +810,13 @@ If both height and timestamp are set, and only one of
         config_version: multisig_wallet.config_version,
         members: multisig_wallet.members,
         threshold: multisig_wallet.threshold,
-        max_voting_period: multisig_wallet.max_voting_period,
+        max_voting_period: multisig_wallet.max_voting_period
     }
 }
 
-
- ## Function `create_multisig_account` @@ -825,8 +829,7 @@ Create new multisig account -
-Implementation +##### Implementation
public entry fun create_multisig_account(
@@ -835,36 +838,47 @@ Create new multisig account
     members: vector<address>,
     threshold: u64,
     max_voting_period_height: Option<u64>,
-    max_voting_period_timestamp: Option<u64>,
+    max_voting_period_timestamp: Option<u64>
 ) {
     assert_member(&members, &signer::address_of(account));
-    assert!(vector::length(&members) >= threshold, error::invalid_argument(EINVALID_THRESHOLD));
-    let constructor_ref = object::create_named_object(account, *string::bytes(&name), false);
+    assert!(
+        vector::length(&members) >= threshold,
+        error::invalid_argument(EINVALID_THRESHOLD)
+    );
+    let constructor_ref = object::create_named_object(
+        account, *string::bytes(&name)
+    );
     let extend_ref = object::generate_extend_ref(&constructor_ref);
     let multisig_signer = object::generate_signer(&constructor_ref);
     let multisig_addr = signer::address_of(&multisig_signer);
     let max_voting_period = Period {
         height: max_voting_period_height,
-        timestamp: max_voting_period_timestamp,
+        timestamp: max_voting_period_timestamp
     };
     let members_map = simple_map::create<address, bool>();
-    vector::for_each(members, |member| simple_map::add(&mut members_map, member, true)); // just for check uniqueness
-
-    move_to(&multisig_signer, MultisigWallet {
-        extend_ref,
-        config_version: 1,
+    vector::for_each(
         members,
-        threshold,
-        max_voting_period,
-        proposals: table::new(),
-    });
+        |member| simple_map::add(&mut members_map, member, true)
+    ); // just for check uniqueness
+
+    move_to(
+        &multisig_signer,
+        MultisigWallet {
+            extend_ref,
+            config_version: 1,
+            members,
+            threshold,
+            max_voting_period,
+            proposals: table::new()
+        }
+    );
 
     event::emit<CreateMultisigAccountEvent>(
         CreateMultisigAccountEvent {
             multisig_addr,
             members,
             threshold,
-            max_voting_period,
+            max_voting_period
         }
     )
 }
@@ -872,8 +886,6 @@ Create new multisig account
 
 
 
-
- ## Function `create_proposal` @@ -886,8 +898,7 @@ Create new proposal -
-Implementation +##### Implementation
public entry fun create_proposal(
@@ -897,50 +908,64 @@ Create new proposal
     module_name: String,
     function_name: String,
     type_args: vector<String>,
-    args: vector<vector<u8>>,
+    args: vector<vector<u8>>
 ) acquires MultisigWallet {
-    let addr = signer::address_of(account);
-    let multisig_wallet = borrow_global_mut<MultisigWallet>(multisig_addr);
-    assert_member(&multisig_wallet.members, &addr);
-
-    let (height, timestamp) = get_block_info();
-    let config_version = multisig_wallet.config_version;
-
-    let proposal = Proposal {
+    create_proposal_internal(
+        account,
+        multisig_addr,
         module_address,
         module_name,
         function_name,
         type_args,
         args,
-        config_version,
-        proposal_height: height,
-        proposal_timestamp: timestamp,
-        votes: simple_map::create(),
-        status: 0, // in voting period
-    };
+        false,
+        vector[]
+    )
+}
+
- let proposal_id = table::length(&multisig_wallet.proposals) + 1; - table::add(&mut multisig_wallet.proposals, proposal_id, proposal); - event::emit<CreateProposalEvent>( - CreateProposalEvent { - multisig_addr, - proposal_id, - module_address, - module_name, - function_name, - type_args, - args, - config_version, - } + + + +## Function `create_proposal_with_json` + +Create new proposal + + +
public entry fun create_proposal_with_json(account: &signer, multisig_addr: address, module_address: address, module_name: string::String, function_name: string::String, type_args: vector<string::String>, args: vector<string::String>)
+
+ + + +##### Implementation + + +
public entry fun create_proposal_with_json(
+    account: &signer,
+    multisig_addr: address,
+    module_address: address,
+    module_name: String,
+    function_name: String,
+    type_args: vector<String>,
+    args: vector<String>
+) acquires MultisigWallet {
+    create_proposal_internal(
+        account,
+        multisig_addr,
+        module_address,
+        module_name,
+        function_name,
+        type_args,
+        vector[],
+        true,
+        args
     )
 }
 
-
- ## Function `vote_proposal` @@ -953,21 +978,26 @@ Vote proposal -
-Implementation +##### Implementation
public entry fun vote_proposal(
     account: &signer,
     multisig_addr: address,
     proposal_id: u64,
-    vote_yes: bool,
+    vote_yes: bool
 ) acquires MultisigWallet {
     let voter = signer::address_of(account);
     let multisig_wallet = borrow_global_mut<MultisigWallet>(multisig_addr);
     assert_member(&multisig_wallet.members, &voter);
 
-    assert!(table::contains(&multisig_wallet.proposals, proposal_id), error::invalid_argument(EPROPOSAL_NOT_FOUND));
+    assert!(
+        table::contains(
+            &multisig_wallet.proposals,
+            proposal_id
+        ),
+        error::invalid_argument(EPROPOSAL_NOT_FOUND)
+    );
     let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id);
 
     assert_config_version(multisig_wallet.config_version, proposal);
@@ -976,20 +1006,13 @@ Vote proposal
     vote(&mut proposal.votes, voter, vote_yes);
 
     event::emit<VoteProposalEvent>(
-        VoteProposalEvent {
-            multisig_addr,
-            proposal_id,
-            voter,
-            vote_yes,
-        }
+        VoteProposalEvent { multisig_addr, proposal_id, voter, vote_yes }
     )
 }
 
-
- ## Function `execute_proposal` @@ -1002,20 +1025,23 @@ Execute proposal -
-Implementation +##### Implementation
public entry fun execute_proposal(
-    account: &signer,
-    multisig_addr: address,
-    proposal_id: u64,
+    account: &signer, multisig_addr: address, proposal_id: u64
 ) acquires MultisigWallet {
     let executor = signer::address_of(account);
     let multisig_wallet = borrow_global_mut<MultisigWallet>(multisig_addr);
     assert_member(&multisig_wallet.members, &executor);
 
-    assert!(table::contains(&multisig_wallet.proposals, proposal_id), error::invalid_argument(EPROPOSAL_NOT_FOUND));
+    assert!(
+        table::contains(
+            &multisig_wallet.proposals,
+            proposal_id
+        ),
+        error::invalid_argument(EPROPOSAL_NOT_FOUND)
+    );
     let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id);
 
     assert_config_version(multisig_wallet.config_version, proposal);
@@ -1023,36 +1049,46 @@ Execute proposal
 
     // check passed
     assert!(
-        yes_vote_count(&proposal.votes, &multisig_wallet.members) >= multisig_wallet.threshold,
-        error::invalid_state(ENOT_PASS),
+        yes_vote_count(
+            &proposal.votes,
+            &multisig_wallet.members
+        ) >= multisig_wallet.threshold,
+        error::invalid_state(ENOT_PASS)
     );
 
-    let multisig_signer = &object::generate_signer_for_extending(&multisig_wallet.extend_ref);
-    move_execute(
-        multisig_signer,
-        proposal.module_address,
-        proposal.module_name,
-        proposal.function_name,
-        proposal.type_args,
-        proposal.args,
-    );
+    let multisig_signer =
+        &object::generate_signer_for_extending(&multisig_wallet.extend_ref);
+
+    if (!proposal.is_json) {
+        move_execute(
+            multisig_signer,
+            proposal.module_address,
+            proposal.module_name,
+            proposal.function_name,
+            proposal.type_args,
+            proposal.args
+        )
+    } else {
+        move_execute_with_json(
+            multisig_signer,
+            proposal.module_address,
+            proposal.module_name,
+            proposal.function_name,
+            proposal.type_args,
+            proposal.json_args
+        )
+    };
 
     proposal.status = 1; // executed
 
     event::emit<ExecuteProposalEvent>(
-        ExecuteProposalEvent {
-            multisig_addr,
-            proposal_id,
-            executor,
-        }
+        ExecuteProposalEvent { multisig_addr, proposal_id, executor }
     )
 }
 
-
- ## Function `update_config` @@ -1065,8 +1101,7 @@ Update config. Only execute by multisig wallet itself -
-Implementation +##### Implementation
public entry fun update_config(
@@ -1074,17 +1109,23 @@ Update config. Only execute by multisig wallet itself
     new_members: vector<address>,
     new_threshold: u64,
     new_max_voting_period_height: Option<u64>,
-    new_max_voting_period_timestamp: Option<u64>,
+    new_max_voting_period_timestamp: Option<u64>
 ) acquires MultisigWallet {
     let multisig_addr = signer::address_of(account);
     let multisig_wallet = borrow_global_mut<MultisigWallet>(multisig_addr);
 
-    assert!(vector::length(&new_members) >= new_threshold, error::invalid_argument(EINVALID_THRESHOLD));
+    assert!(
+        vector::length(&new_members) >= new_threshold,
+        error::invalid_argument(EINVALID_THRESHOLD)
+    );
     let new_members_map = simple_map::create<address, bool>();
-    vector::for_each(new_members, |member| simple_map::add(&mut new_members_map, member, true)); // just for check uniqueness
+    vector::for_each(
+        new_members,
+        |member| simple_map::add(&mut new_members_map, member, true)
+    ); // just for check uniqueness
     let new_max_voting_period = Period {
         height: new_max_voting_period_height,
-        timestamp: new_max_voting_period_timestamp,
+        timestamp: new_max_voting_period_timestamp
     };
 
     multisig_wallet.config_version = multisig_wallet.config_version + 1;
@@ -1097,240 +1138,8 @@ Update config. Only execute by multisig wallet itself
             multisig_addr,
             members: new_members,
             threshold: new_threshold,
-            max_voting_period: new_max_voting_period,
+            max_voting_period: new_max_voting_period
         }
     )
 }
 
- - - -
- - - -## Function `is_proposal_expired` - - - -
fun is_proposal_expired(max_period: &multisig::Period, proposal_height: u64, proposal_timestamp: u64): bool
-
- - - -
-Implementation - - -
fun is_proposal_expired(max_period: &Period, proposal_height: u64, proposal_timestamp: u64): bool {
-    let (height, timestamp) = get_block_info();
-    let expired_height = if (option::is_some(&max_period.height)) {
-        let max_voting_period_height = *option::borrow(&max_period.height);
-        (max_voting_period_height + proposal_height) >= height
-    } else {
-        false
-    };
-
-    let expired_timestamp = if (option::is_some(&max_period.timestamp)) {
-        let max_voting_period_timestamp = *option::borrow(&max_period.timestamp);
-        (max_voting_period_timestamp + proposal_timestamp) >= timestamp
-    } else {
-        false
-    };
-
-    expired_height || expired_timestamp
-}
-
- - - -
- - - -## Function `vote` - - - -
fun vote(votes: &mut simple_map::SimpleMap<address, bool>, voter: address, vote_yes: bool)
-
- - - -
-Implementation - - -
fun vote(votes: &mut SimpleMap<address, bool>, voter: address, vote_yes: bool) {
-    if (simple_map::contains_key(votes, &voter)) {
-        let vote = simple_map::borrow_mut(votes, &voter);
-        *vote = vote_yes;
-    } else {
-        simple_map::add(votes, voter, vote_yes);
-    };
-}
-
- - - -
- - - -## Function `yes_vote_count` - - - -
fun yes_vote_count(votes: &simple_map::SimpleMap<address, bool>, members: &vector<address>): u64
-
- - - -
-Implementation - - -
fun yes_vote_count(votes: &SimpleMap<address, bool>, members: &vector<address>): u64 {
-    let yes_count = 0;
-    vector::for_each_ref(members, |member| {
-        if (simple_map::contains_key(votes, member) && *simple_map::borrow(votes, member)) {
-            yes_count = yes_count + 1;
-        }
-    });
-
-    yes_count
-}
-
- - - -
- - - -## Function `proposal_to_proposal_response` - - - -
fun proposal_to_proposal_response(multisig_wallet: &multisig::MultisigWallet, multisig_addr: address, proposal_id: u64, proposal: &multisig::Proposal): multisig::ProposalResponse
-
- - - -
-Implementation - - -
fun proposal_to_proposal_response(
-    multisig_wallet: &MultisigWallet,
-    multisig_addr: address,
-    proposal_id: u64,
-    proposal: &Proposal,
-): ProposalResponse {
-    let status_index = proposal.status;
-    let is_expired = is_proposal_expired(&multisig_wallet.max_voting_period, proposal.proposal_height, proposal.proposal_timestamp);
-    let yes_vote_count = yes_vote_count(&proposal.votes, &multisig_wallet.members);
-    if (status_index == 0 && is_expired) {
-        status_index = 2
-    };
-
-    ProposalResponse {
-        multisig_addr,
-        proposal_id,
-        module_address: proposal.module_address,
-        module_name: proposal.module_name,
-        function_name: proposal.function_name,
-        type_args: proposal.type_args,
-        args: proposal.args,
-        proposal_height: proposal.proposal_height,
-        proposal_timestamp: proposal.proposal_timestamp,
-        config_version: proposal.config_version,
-        yes_vote_count,
-        status: string::utf8(*vector::borrow(&STATUS, (status_index as u64))),
-    }
-}
-
- - - -
- - - -## Function `assert_member` - - - -
fun assert_member(members: &vector<address>, member: &address)
-
- - - -
-Implementation - - -
inline fun assert_member(members: &vector<address>, member: &address) {
-    assert!(vector::contains(members, member), error::permission_denied(ENOT_MEMBER))
-}
-
- - - -
- - - -## Function `assert_config_version` - - - -
fun assert_config_version(multisig_wallet_config_version: u64, execute_proposal: &multisig::Proposal)
-
- - - -
-Implementation - - -
inline fun assert_config_version(multisig_wallet_config_version: u64, execute_proposal: &Proposal) {
-    assert!(multisig_wallet_config_version == execute_proposal.config_version, error::invalid_state(EOLD_CONFIG_VERSION))
-}
-
- - - -
- - - -## Function `assert_proposal` - - - -
fun assert_proposal(max_voting_period: &multisig::Period, proposal: &multisig::Proposal)
-
- - - -
-Implementation - - -
inline fun assert_proposal(max_voting_period: &Period, proposal: &Proposal) {
-    assert!(proposal.status == 0, error::invalid_state(EINVALID_PROPOSAL_STATUS));
-    assert!(
-        !is_proposal_expired(
-            max_voting_period,
-            proposal.proposal_height,
-            proposal.proposal_timestamp,
-        ),
-        error::invalid_state(EPROPOSAL_EXPIRED),
-    );
-}
-
- - - -
diff --git a/initia_stdlib/doc/nft.md b/initia_stdlib/doc/nft.md index d64051e..0216b6b 100644 --- a/initia_stdlib/doc/nft.md +++ b/initia_stdlib/doc/nft.md @@ -16,14 +16,12 @@ nft are: - [Struct `MutationEvent`](#0x1_nft_MutationEvent) - [Struct `NftInfoResponse`](#0x1_nft_NftInfoResponse) - [Constants](#@Constants_0) -- [Function `create_common`](#0x1_nft_create_common) - [Function `create`](#0x1_nft_create) - [Function `create_nft_address`](#0x1_nft_create_nft_address) - [Function `create_nft_seed`](#0x1_nft_create_nft_seed) - [Function `generate_mutator_ref`](#0x1_nft_generate_mutator_ref) - [Function `generate_burn_ref`](#0x1_nft_generate_burn_ref) - [Function `address_from_burn_ref`](#0x1_nft_address_from_burn_ref) -- [Function `borrow`](#0x1_nft_borrow) - [Function `is_nft`](#0x1_nft_is_nft) - [Function `creator`](#0x1_nft_creator) - [Function `collection_name`](#0x1_nft_collection_name) @@ -34,7 +32,6 @@ nft are: - [Function `royalty`](#0x1_nft_royalty) - [Function `nft_info`](#0x1_nft_nft_info) - [Function `nft_infos`](#0x1_nft_nft_infos) -- [Function `borrow_mut`](#0x1_nft_borrow_mut) - [Function `burn`](#0x1_nft_burn) - [Function `set_description`](#0x1_nft_set_description) - [Function `set_uri`](#0x1_nft_set_uri) @@ -65,8 +62,7 @@ Represents the common fields to all nfts. -
-Fields +##### Fields
@@ -99,8 +95,6 @@ Represents the common fields to all nfts.
-
- ## Struct `BurnRef` @@ -115,8 +109,7 @@ a small optimization to support either and take a fixed amount of 34-bytes. -
-Fields +##### Fields
@@ -129,8 +122,6 @@ a small optimization to support either and take a fixed amount of 34-bytes.
-
- ## Struct `MutatorRef` @@ -143,8 +134,7 @@ This enables mutating descritpion and URI by higher level services. -
-Fields +##### Fields
@@ -157,8 +147,6 @@ This enables mutating descritpion and URI by higher level services.
-
- ## Struct `MutationEvent` @@ -173,8 +161,7 @@ directly understand the behavior in a writeset. -
-Fields +##### Fields
@@ -205,8 +192,6 @@ directly understand the behavior in a writeset.
-
- ## Struct `NftInfoResponse` @@ -219,8 +204,7 @@ Struct for nft info query response -
-Fields +##### Fields
@@ -251,8 +235,6 @@ Struct for nft info query response
-
- ## Constants @@ -306,6 +288,16 @@ The field being changed is not mutable + + +The provided token id is invalid + + +
const EINVALID_TOKEN_ID: u64 = 9;
+
+ + + The nft does not exist @@ -364,58 +356,6 @@ The query length is over the maximum length - - -## Function `create_common` - - - -
fun create_common(constructor_ref: &object::ConstructorRef, creator_address: address, collection_name: string::String, description: string::String, token_id: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String)
-
- - - -
-Implementation - - -
inline fun create_common(
-    constructor_ref: &ConstructorRef,
-    creator_address: address,
-    collection_name: String,
-    description: String,
-    token_id: String,
-    royalty: Option<Royalty>,
-    uri: String,
-) {
-    assert!(string::length(&token_id) <= MAX_NFT_TOKEN_ID_LENGTH, error::out_of_range(ENFT_TOKEN_ID_TOO_LONG));
-    assert!(string::length(&description) <= MAX_DESCRIPTION_LENGTH, error::out_of_range(EDESCRIPTION_TOO_LONG));
-    assert!(string::length(&uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
-
-    let object_signer = object::generate_signer(constructor_ref);
-
-    let collection_addr = collection::create_collection_address(creator_address, &collection_name);
-    let collection = object::address_to_object<Collection>(collection_addr);
-    collection::increment_supply(collection, token_id, signer::address_of(&object_signer));
-
-    let nft = Nft {
-        collection,
-        description,
-        token_id,
-        uri,
-    };
-    move_to(&object_signer, nft);
-
-    if (option::is_some(&royalty)) {
-        royalty::init(constructor_ref, option::extract(&mut royalty))
-    };
-}
-
- - - -
- ## Function `create` @@ -429,8 +369,7 @@ additional specialization. -
-Implementation +##### Implementation
public fun create(
@@ -439,21 +378,27 @@ additional specialization.
     description: String,
     token_id: String,
     royalty: Option<Royalty>,
-    uri: String,
+    uri: String
 ): ConstructorRef {
     let creator_address = signer::address_of(creator);
     let seed = create_nft_seed(&collection_name, &token_id);
 
-    let constructor_ref = object::create_named_object(creator, seed, true);
-    create_common(&constructor_ref, creator_address, collection_name, description, token_id, royalty, uri);
+    let constructor_ref = object::create_deletable_named_object(creator, seed);
+    create_common(
+        &constructor_ref,
+        creator_address,
+        collection_name,
+        description,
+        token_id,
+        royalty,
+        uri
+    );
     constructor_ref
 }
 
-
- ## Function `create_nft_address` @@ -466,19 +411,21 @@ Generates the nft's address based upon the creator's address, the collection's n -
-Implementation +##### Implementation -
public fun create_nft_address(creator: address, collection: &String, token_id: &String): address {
-    object::create_object_address(creator, create_nft_seed(collection, token_id))
+
public fun create_nft_address(
+    creator: address, collection: &String, token_id: &String
+): address {
+    object::create_object_address(
+        &creator,
+        create_nft_seed(collection, token_id)
+    )
 }
 
-
- ## Function `create_nft_seed` @@ -491,12 +438,14 @@ Named objects are derived from a seed, the nft's seed is its token_id appended t -
-Implementation +##### Implementation
public fun create_nft_seed(collection: &String, token_id: &String): vector<u8> {
-    assert!(string::length(token_id) <= MAX_NFT_TOKEN_ID_LENGTH, error::out_of_range(ENFT_TOKEN_ID_TOO_LONG));
+    assert!(
+        string::length(token_id) <= MAX_NFT_TOKEN_ID_LENGTH,
+        error::out_of_range(ENFT_TOKEN_ID_TOO_LONG)
+    );
     let seed = *string::bytes(collection);
     vector::append(&mut seed, b"::");
     vector::append(&mut seed, *string::bytes(token_id));
@@ -506,8 +455,6 @@ Named objects are derived from a seed, the nft's seed is its token_id appended t
 
 
 
-
- ## Function `generate_mutator_ref` @@ -520,20 +467,17 @@ Creates a MutatorRef, which gates the ability to mutate any fields that support -
-Implementation +##### Implementation
public fun generate_mutator_ref(ref: &ConstructorRef): MutatorRef {
     let object = object::object_from_constructor_ref<Nft>(ref);
-    MutatorRef { self: object::object_address(object) }
+    MutatorRef { self: object::object_address(&object) }
 }
 
-
- ## Function `generate_burn_ref` @@ -546,8 +490,7 @@ Creates a BurnRef, which gates the ability to burn the given nft. -
-Implementation +##### Implementation
public fun generate_burn_ref(ref: &ConstructorRef): BurnRef {
@@ -558,8 +501,6 @@ Creates a BurnRef, which gates the ability to burn the given nft.
 
 
 
-
- ## Function `address_from_burn_ref` @@ -572,8 +513,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun address_from_burn_ref(ref: &BurnRef): address {
@@ -583,37 +523,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- - - -## Function `borrow` - - - -
fun borrow<T: key>(nft: object::Object<T>): &nft::Nft
-
- - - -
-Implementation - - -
inline fun borrow<T: key>(nft: Object<T>): &Nft acquires Nft {
-    let nft_address = object::object_address(nft);
-    assert!(
-        exists<Nft>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-    borrow_global<Nft>(nft_address)
-}
-
- - - -
- ## Function `is_nft` @@ -626,8 +535,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun is_nft(object_address: address): bool {
@@ -637,8 +545,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `creator` @@ -651,8 +557,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun creator<T: key>(nft: Object<T>): address acquires Nft {
@@ -662,8 +567,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `collection_name` @@ -676,8 +579,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun collection_name<T: key>(nft: Object<T>): String acquires Nft {
@@ -687,8 +589,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `collection_object` @@ -701,8 +601,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun collection_object<T: key>(nft: Object<T>): Object<Collection> acquires Nft {
@@ -712,8 +611,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `description` @@ -726,8 +623,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun description<T: key>(nft: Object<T>): String acquires Nft {
@@ -737,8 +633,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `token_id` @@ -751,8 +645,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun token_id<T: key>(nft: Object<T>): String acquires Nft {
@@ -762,8 +655,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `uri` @@ -776,8 +667,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun uri<T: key>(nft: Object<T>): String acquires Nft {
@@ -787,8 +677,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `royalty` @@ -801,8 +689,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun royalty<T: key>(nft: Object<T>): Option<Royalty> acquires Nft {
@@ -813,8 +700,10 @@ Extracts the nfts address from a BurnRef.
     } else {
         let creator = creator(nft);
         let collection_name = collection_name(nft);
-        let collection_address = collection::create_collection_address(creator, &collection_name);
-        let collection = object::address_to_object<collection::Collection>(collection_address);
+        let collection_address =
+            collection::create_collection_address(creator, &collection_name);
+        let collection =
+            object::address_to_object<collection::Collection>(collection_address);
         royalty::get(collection)
     }
 }
@@ -822,8 +711,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `nft_info` @@ -836,8 +723,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun nft_info(nft: Object<Nft>): NftInfoResponse acquires Nft {
@@ -846,15 +732,13 @@ Extracts the nfts address from a BurnRef.
         collection: nft.collection,
         description: nft.description,
         token_id: nft.token_id,
-        uri: nft.uri,
+        uri: nft.uri
     }
 }
 
-
- ## Function `nft_infos` @@ -867,13 +751,15 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun nft_infos(nfts: vector<Object<Nft>>): vector<NftInfoResponse> acquires Nft {
     let len = vector::length(&nfts);
-    assert!(len <= MAX_QUERY_LENGTH, error::invalid_argument(EQUERY_LENGTH_TOO_LONG));
+    assert!(
+        len <= MAX_QUERY_LENGTH,
+        error::invalid_argument(EQUERY_LENGTH_TOO_LONG)
+    );
     let index = 0;
     let res: vector<NftInfoResponse> = vector[];
     while (index < len) {
@@ -888,36 +774,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- - - -## Function `borrow_mut` - - - -
fun borrow_mut(mutator_ref: &nft::MutatorRef): &mut nft::Nft
-
- - - -
-Implementation - - -
inline fun borrow_mut(mutator_ref: &MutatorRef): &mut Nft acquires Nft {
-    assert!(
-        exists<Nft>(mutator_ref.self),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-    borrow_global_mut<Nft>(mutator_ref.self)
-}
-
- - - -
- ## Function `burn` @@ -929,8 +785,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun burn(burn_ref: BurnRef) acquires Nft {
@@ -942,12 +797,7 @@ Extracts the nfts address from a BurnRef.
         royalty::delete(addr)
     };
 
-    let Nft {
-        collection,
-        description: _,
-        token_id,
-        uri: _,
-    } = move_from<Nft>(addr);
+    let Nft { collection, description: _, token_id, uri: _ } = move_from<Nft>(addr);
 
     collection::decrement_supply(collection, token_id, addr);
 }
@@ -955,8 +805,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `set_description` @@ -968,12 +816,16 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation -
public fun set_description(mutator_ref: &MutatorRef, description: String) acquires Nft {
-    assert!(string::length(&description) <= MAX_DESCRIPTION_LENGTH, error::out_of_range(EDESCRIPTION_TOO_LONG));
+
public fun set_description(
+    mutator_ref: &MutatorRef, description: String
+) acquires Nft {
+    assert!(
+        string::length(&description) <= MAX_DESCRIPTION_LENGTH,
+        error::out_of_range(EDESCRIPTION_TOO_LONG)
+    );
     let nft = borrow_mut(mutator_ref);
     event::emit(
         MutationEvent {
@@ -981,7 +833,7 @@ Extracts the nfts address from a BurnRef.
             mutated_field_name: string::utf8(b"description"),
             old_value: nft.description,
             new_value: description
-        },
+        }
     );
     nft.description = description;
 }
@@ -989,8 +841,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `set_uri` @@ -1002,25 +852,23 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun set_uri(mutator_ref: &MutatorRef, uri: String) acquires Nft {
-    assert!(string::length(&uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
+    assert!(
+        string::length(&uri) <= MAX_URI_LENGTH,
+        error::out_of_range(EURI_TOO_LONG)
+    );
     let nft = borrow_mut(mutator_ref);
     event::emit(
         MutationEvent {
             nft: mutator_ref.self,
             mutated_field_name: string::utf8(b"uri"),
             old_value: nft.uri,
-            new_value: uri,
-        },
+            new_value: uri
+        }
     );
     nft.uri = uri;
 }
 
- - - -
diff --git a/initia_stdlib/doc/object.md b/initia_stdlib/doc/object.md index c5598a5..94710a9 100644 --- a/initia_stdlib/doc/object.md +++ b/initia_stdlib/doc/object.md @@ -35,16 +35,16 @@ make it so that a reference to a global object can be returned from a function. - [Constants](#@Constants_0) - [Function `address_to_object`](#0x1_object_address_to_object) - [Function `is_object`](#0x1_object_is_object) +- [Function `object_exists`](#0x1_object_object_exists) - [Function `create_object_address`](#0x1_object_create_object_address) - [Function `create_user_derived_object_address`](#0x1_object_create_user_derived_object_address) - [Function `create_guid_object_address`](#0x1_object_create_guid_object_address) -- [Function `exists_at`](#0x1_object_exists_at) - [Function `object_address`](#0x1_object_object_address) - [Function `convert`](#0x1_object_convert) - [Function `create_named_object`](#0x1_object_create_named_object) +- [Function `create_deletable_named_object`](#0x1_object_create_deletable_named_object) - [Function `create_user_derived_object`](#0x1_object_create_user_derived_object) - [Function `create_object`](#0x1_object_create_object) -- [Function `create_object_internal`](#0x1_object_create_object_internal) - [Function `generate_delete_ref`](#0x1_object_generate_delete_ref) - [Function `generate_extend_ref`](#0x1_object_generate_extend_ref) - [Function `generate_transfer_ref`](#0x1_object_generate_transfer_ref) @@ -66,7 +66,6 @@ make it so that a reference to a global object can be returned from a function. - [Function `transfer`](#0x1_object_transfer) - [Function `transfer_raw`](#0x1_object_transfer_raw) - [Function `transfer_to_object`](#0x1_object_transfer_to_object) -- [Function `verify_ungated_and_descendant`](#0x1_object_verify_ungated_and_descendant) - [Function `ungated_transfer_allowed`](#0x1_object_ungated_transfer_allowed) - [Function `owner`](#0x1_object_owner) - [Function `is_owner`](#0x1_object_is_owner) @@ -99,8 +98,7 @@ Tombstone is version store for deleted objects with version -
-Fields +##### Fields
@@ -113,8 +111,6 @@ Tombstone is version store for deleted objects with version
-
- ## Resource `ObjectCore` @@ -127,8 +123,7 @@ The core of the object model that defines ownership, transferability, and events -
-Fields +##### Fields
@@ -154,8 +149,6 @@ The core of the object model that defines ownership, transferability, and events
-
- ## Struct `Object` @@ -171,8 +164,7 @@ can remove it from storage at any point in time. -
-Fields +##### Fields
@@ -185,8 +177,6 @@ can remove it from storage at any point in time.
-
- ## Struct `ConstructorRef` @@ -199,8 +189,7 @@ This is a one time ability given to the creator to configure the object as neces -
-Fields +##### Fields
@@ -214,7 +203,7 @@ This is a one time ability given to the creator to configure the object as neces can_delete: bool
- True if the object can be deleted. Named objects are not deletable. + True if the object can be deleted.
version: u64 @@ -225,8 +214,6 @@ This is a one time ability given to the creator to configure the object as neces
-
- ## Struct `DeleteRef` @@ -239,8 +226,7 @@ Used to remove an object from storage. -
-Fields +##### Fields
@@ -259,8 +245,6 @@ Used to remove an object from storage.
-
- ## Struct `ExtendRef` @@ -273,8 +257,7 @@ Used to create events or move additional resources into object storage. -
-Fields +##### Fields
@@ -293,8 +276,6 @@ Used to create events or move additional resources into object storage.
-
- ## Struct `TransferRef` @@ -307,8 +288,7 @@ Used to create LinearTransferRef, hence ownership transfer. -
-Fields +##### Fields
@@ -327,8 +307,6 @@ Used to create LinearTransferRef, hence ownership transfer.
-
- ## Struct `LinearTransferRef` @@ -342,8 +320,7 @@ the current owner. -
-Fields +##### Fields
@@ -368,8 +345,6 @@ the current owner.
-
- ## Struct `DeriveRef` @@ -382,8 +357,7 @@ Used to create derived objects from a given objects. -
-Fields +##### Fields
@@ -402,8 +376,6 @@ Used to create derived objects from a given objects.
-
- ## Struct `CreateEvent` @@ -417,8 +389,7 @@ Emitted at the object creation. -
-Fields +##### Fields
@@ -443,8 +414,6 @@ Emitted at the object creation.
-
- ## Struct `TransferEvent` @@ -458,8 +427,7 @@ Emitted whenever the object's owner field is changed. -
-Fields +##### Fields
@@ -484,8 +452,6 @@ Emitted whenever the object's owner field is changed.
-
- ## Constants @@ -653,21 +619,24 @@ Produces an ObjectId from the given address. This is not verified. -
-Implementation +##### Implementation
public fun address_to_object<T: key>(object: address): Object<T> {
-    assert!(exists<ObjectCore>(object), error::not_found(EOBJECT_DOES_NOT_EXIST));
-    assert!(exists_at<T>(object), error::not_found(ERESOURCE_DOES_NOT_EXIST));
+    assert!(
+        exists<ObjectCore>(object),
+        error::not_found(EOBJECT_DOES_NOT_EXIST)
+    );
+    assert!(
+        exists_at<T>(object),
+        error::not_found(ERESOURCE_DOES_NOT_EXIST)
+    );
     Object<T> { inner: object }
 }
 
-
- ## Function `is_object` @@ -680,8 +649,7 @@ Returns true if there exists an object or the remnants of an object. -
-Implementation +##### Implementation
public fun is_object(object: address): bool {
@@ -691,7 +659,27 @@ Returns true if there exists an object or the remnants of an object.
 
 
 
-
+ + +## Function `object_exists` + +Returns true if there exists an object with resource T. + + +
public fun object_exists<T: key>(object: address): bool
+
+ + + +##### Implementation + + +
public fun object_exists<T: key>(object: address): bool {
+    exists<ObjectCore>(object) && exists_at<T>(object)
+}
+
+ + @@ -700,17 +688,16 @@ Returns true if there exists an object or the remnants of an object. Derives an object address from source material: sha3_256([creator address | seed | 0xFE]). -
public fun create_object_address(source: address, seed: vector<u8>): address
+
public fun create_object_address(source: &address, seed: vector<u8>): address
 
-
-Implementation +##### Implementation -
public fun create_object_address(source: address, seed: vector<u8>): address {
-    let bytes = bcs::to_bytes(&source);
+
public fun create_object_address(source: &address, seed: vector<u8>): address {
+    let bytes = bcs::to_bytes(source);
     vector::append(&mut bytes, seed);
     vector::push_back(&mut bytes, OBJECT_FROM_SEED_ADDRESS_SCHEME);
     from_bcs::to_address(hash::sha3_256(bytes))
@@ -719,8 +706,6 @@ Derives an object address from source material: sha3_256([creator address | seed
 
 
 
-
- ## Function `create_user_derived_object_address` @@ -733,11 +718,12 @@ Derives an object address from the source address and an object: sha3_256([sourc -
-Implementation +##### Implementation -
public fun create_user_derived_object_address(source: address, derive_from: address): address {
+
public fun create_user_derived_object_address(
+    source: address, derive_from: address
+): address {
     let bytes = bcs::to_bytes(&source);
     vector::append(&mut bytes, bcs::to_bytes(&derive_from));
     vector::push_back(&mut bytes, OBJECT_DERIVED_SCHEME);
@@ -747,8 +733,6 @@ Derives an object address from the source address and an object: sha3_256([sourc
 
 
 
-
- ## Function `create_guid_object_address` @@ -761,11 +745,12 @@ Derives an object from an Account GUID. -
-Implementation +##### Implementation -
public fun create_guid_object_address(source: address, creation_num: u64): address {
+
public fun create_guid_object_address(
+    source: address, creation_num: u64
+): address {
     let id = guid::create_id(source, creation_num);
     let bytes = bcs::to_bytes(&id);
     vector::push_back(&mut bytes, OBJECT_FROM_GUID_ADDRESS_SCHEME);
@@ -775,30 +760,6 @@ Derives an object from an Account GUID.
 
 
 
-
- - - -## Function `exists_at` - - - -
fun exists_at<T: key>(object: address): bool
-
- - - -
-Implementation - - -
native fun exists_at<T: key>(object: address): bool;
-
- - - -
- ## Function `object_address` @@ -806,24 +767,21 @@ Derives an object from an Account GUID. Returns the address of within an ObjectId. -
public fun object_address<T: key>(object: object::Object<T>): address
+
public fun object_address<T: key>(object: &object::Object<T>): address
 
-
-Implementation +##### Implementation -
public fun object_address<T: key>(object: Object<T>): address {
+
public fun object_address<T: key>(object: &Object<T>): address {
     object.inner
 }
 
-
- ## Function `convert` @@ -836,8 +794,7 @@ Convert Object to Object. -
-Implementation +##### Implementation
public fun convert<X: key, Y: key>(object: Object<X>): Object<Y> {
@@ -847,147 +804,121 @@ Convert Object to Object.
 
 
 
-
- ## Function `create_named_object` -Create a new named object and return the ConstructorRef. Named objects can be queried globally -by knowing the user generated seed used to create them. Named objects cannot be deleted. +Create a new named object and return the ConstructorRef. +Named objects can be queried globally by knowing the user generated seed used to create them. -
public fun create_named_object(creator: &signer, seed: vector<u8>, can_delete: bool): object::ConstructorRef
+
public fun create_named_object(creator: &signer, seed: vector<u8>): object::ConstructorRef
 
-
-Implementation +##### Implementation -
public fun create_named_object(creator: &signer, seed: vector<u8>, can_delete: bool): ConstructorRef acquires Tombstone {
+
public fun create_named_object(
+    creator: &signer, seed: vector<u8>
+): ConstructorRef acquires Tombstone {
     let creator_address = signer::address_of(creator);
-    let obj_addr = create_object_address(creator_address, seed);
-    create_object_internal(creator_address, obj_addr, can_delete)
+    let obj_addr = create_object_address(&creator_address, seed);
+    create_object_internal(creator_address, obj_addr, false)
 }
 
-
+ - - -## Function `create_user_derived_object` +## Function `create_deletable_named_object` -Create a new object whose address is derived based on the creator account address and another object. -Derivde objects, similar to named objects, cannot be deleted. +Create a new object that can be deleted and return the ConstructorRef. +Named objects can be queried globally by knowing the user generated seed used to create them. -
public(friend) fun create_user_derived_object(creator_address: address, derive_ref: &object::DeriveRef, can_delete: bool): object::ConstructorRef
+
public fun create_deletable_named_object(creator: &signer, seed: vector<u8>): object::ConstructorRef
 
-
-Implementation +##### Implementation -
public(friend) fun create_user_derived_object(creator_address: address, derive_ref: &DeriveRef, can_delete: bool): ConstructorRef acquires Tombstone {
-    let obj_addr = create_user_derived_object_address(creator_address, derive_ref.self);
-    create_object_internal(creator_address, obj_addr, can_delete)
+
public fun create_deletable_named_object(
+    creator: &signer, seed: vector<u8>
+): ConstructorRef acquires Tombstone {
+    let creator_address = signer::address_of(creator);
+    let obj_addr = create_object_address(&creator_address, seed);
+    create_object_internal(creator_address, obj_addr, true)
 }
 
-
- - + -## Function `create_object` +## Function `create_user_derived_object` -Create a new object by generating a random unique address based on transaction hash. -The unique address is computed sha3_256([transaction hash | auid counter | 0xFB]). +Create a new object whose address is derived based on the creator account address and another object. +Derivde objects, similar to named objects, cannot be deleted. -
public fun create_object(owner_address: address, can_delete: bool): object::ConstructorRef
+
public(friend) fun create_user_derived_object(creator_address: address, derive_ref: &object::DeriveRef, can_delete: bool): object::ConstructorRef
 
-
-Implementation +##### Implementation -
public fun create_object(owner_address: address, can_delete: bool): ConstructorRef acquires Tombstone {
-    let unique_address = transaction_context::generate_unique_address();
-    create_object_internal(owner_address, unique_address, can_delete)
+
public(friend) fun create_user_derived_object(
+    creator_address: address, derive_ref: &DeriveRef, can_delete: bool
+): ConstructorRef acquires Tombstone {
+    let obj_addr =
+        create_user_derived_object_address(creator_address, derive_ref.self);
+    create_object_internal(
+        creator_address,
+        obj_addr,
+        can_delete
+    )
 }
 
-
- - + -## Function `create_object_internal` +## Function `create_object` +Create a new object by generating a random unique address based on transaction hash. +The unique address is computed sha3_256([transaction hash | auid counter | 0xFB]). -
fun create_object_internal(creator_address: address, object: address, can_delete: bool): object::ConstructorRef
+
public fun create_object(owner_address: address, can_delete: bool): object::ConstructorRef
 
-
-Implementation +##### Implementation -
fun create_object_internal(
-    creator_address: address,
-    object: address,
-    can_delete: bool,
+
public fun create_object(
+    owner_address: address, can_delete: bool
 ): ConstructorRef acquires Tombstone {
-    // create resource account to prevent address overapping.
-    account::create_object_account(object);
-
-    assert!(!exists<ObjectCore>(object), error::already_exists(EOBJECT_EXISTS));
-    let object_signer = account::create_signer(object);
-    let version = if (exists<Tombstone>(object)) {
-        let Tombstone { version } = move_from<Tombstone>(object);
-        (version+1)
-    } else {
-        1
-    };
-
-    move_to(
-        &object_signer,
-        ObjectCore {
-            owner: creator_address,
-            allow_ungated_transfer: true,
-            version,
-        },
-    );
-
-    event::emit (
-        CreateEvent {
-            owner: creator_address,
-            object,
-            version,
-        }
-    );
-
-    ConstructorRef { self: object, version, can_delete }
+    let unique_address = transaction_context::generate_unique_address();
+    create_object_internal(
+        owner_address,
+        unique_address,
+        can_delete
+    )
 }
 
-
- ## Function `generate_delete_ref` @@ -1000,20 +931,20 @@ Generates the DeleteRef, which can be used to remove ObjectCore from global stor -
-Implementation +##### Implementation
public fun generate_delete_ref(ref: &ConstructorRef): DeleteRef {
-    assert!(ref.can_delete, error::permission_denied(ECANNOT_DELETE));
+    assert!(
+        ref.can_delete,
+        error::permission_denied(ECANNOT_DELETE)
+    );
     DeleteRef { self: ref.self, version: ref.version }
 }
 
-
- ## Function `generate_extend_ref` @@ -1026,8 +957,7 @@ Generates the ExtendRef, which can be used to add new events and resources to th -
-Implementation +##### Implementation
public fun generate_extend_ref(ref: &ConstructorRef): ExtendRef {
@@ -1037,8 +967,6 @@ Generates the ExtendRef, which can be used to add new events and resources to th
 
 
 
-
- ## Function `generate_transfer_ref` @@ -1051,8 +979,7 @@ Generates the TransferRef, which can be used to manage object transfers. -
-Implementation +##### Implementation
public fun generate_transfer_ref(ref: &ConstructorRef): TransferRef {
@@ -1062,8 +989,6 @@ Generates the TransferRef, which can be used to manage object transfers.
 
 
 
-
- ## Function `generate_derive_ref` @@ -1076,8 +1001,7 @@ Generates the DeriveRef, which can be used to create determnistic derived object -
-Implementation +##### Implementation
public fun generate_derive_ref(ref: &ConstructorRef): DeriveRef {
@@ -1087,8 +1011,6 @@ Generates the DeriveRef, which can be used to create determnistic derived object
 
 
 
-
- ## Function `generate_signer` @@ -1101,8 +1023,7 @@ Create a signer for the ConstructorRef -
-Implementation +##### Implementation
public fun generate_signer(ref: &ConstructorRef): signer {
@@ -1112,8 +1033,6 @@ Create a signer for the ConstructorRef
 
 
 
-
- ## Function `address_from_constructor_ref` @@ -1126,8 +1045,7 @@ Returns the address associated with the constructor -
-Implementation +##### Implementation
public fun address_from_constructor_ref(ref: &ConstructorRef): address {
@@ -1137,8 +1055,6 @@ Returns the address associated with the constructor
 
 
 
-
- ## Function `object_from_constructor_ref` @@ -1151,8 +1067,7 @@ Returns an Object from within a ConstructorRef -
-Implementation +##### Implementation
public fun object_from_constructor_ref<T: key>(ref: &ConstructorRef): Object<T> {
@@ -1162,8 +1077,6 @@ Returns an Object from within a ConstructorRef
 
 
 
-
- ## Function `can_generate_delete_ref` @@ -1176,8 +1089,7 @@ Returns whether or not the ConstructorRef can be used to create DeleteRef -
-Implementation +##### Implementation
public fun can_generate_delete_ref(ref: &ConstructorRef): bool {
@@ -1187,8 +1099,6 @@ Returns whether or not the ConstructorRef can be used to create DeleteRef
 
 
 
-
- ## Function `address_from_delete_ref` @@ -1201,8 +1111,7 @@ Returns the address associated with the constructor -
-Implementation +##### Implementation
public fun address_from_delete_ref(ref: &DeleteRef): address {
@@ -1212,8 +1121,6 @@ Returns the address associated with the constructor
 
 
 
-
- ## Function `object_from_delete_ref` @@ -1226,8 +1133,7 @@ Returns an Object from within a DeleteRef. -
-Implementation +##### Implementation
public fun object_from_delete_ref<T: key>(ref: &DeleteRef): Object<T> {
@@ -1237,8 +1143,6 @@ Returns an Object from within a DeleteRef.
 
 
 
-
- ## Function `delete` @@ -1251,31 +1155,28 @@ Removes from the specified Object from global storage. -
-Implementation +##### Implementation
public fun delete(ref: DeleteRef) acquires ObjectCore {
     let object_core = move_from<ObjectCore>(ref.self);
-    assert!(ref.version == object_core.version, error::permission_denied(EVERSION_MISMATCH));
+    assert!(
+        ref.version == object_core.version,
+        error::permission_denied(EVERSION_MISMATCH)
+    );
 
-    let ObjectCore {
-        owner: _,
-        allow_ungated_transfer: _,
-        version,
-    } = object_core;
+    let ObjectCore { owner: _, allow_ungated_transfer: _, version } = object_core;
 
     // set tombstone
-    move_to<Tombstone>(&account::create_signer(ref.self), Tombstone {
-        version,
-    });
+    move_to<Tombstone>(
+        &account::create_signer(ref.self),
+        Tombstone { version }
+    );
 }
 
-
- ## Function `generate_signer_for_extending` @@ -1288,13 +1189,15 @@ Create a signer for the ExtendRef -
-Implementation +##### Implementation
public fun generate_signer_for_extending(ref: &ExtendRef): signer acquires ObjectCore {
     let object_core = borrow_global<ObjectCore>(ref.self);
-    assert!(ref.version == object_core.version, error::permission_denied(EVERSION_MISMATCH));
+    assert!(
+        ref.version == object_core.version,
+        error::permission_denied(EVERSION_MISMATCH)
+    );
 
     account::create_signer(ref.self)
 }
@@ -1302,8 +1205,6 @@ Create a signer for the ExtendRef
 
 
 
-
- ## Function `address_from_extend_ref` @@ -1316,8 +1217,7 @@ Returns an address from within a ExtendRef. -
-Implementation +##### Implementation
public fun address_from_extend_ref(ref: &ExtendRef): address {
@@ -1327,8 +1227,6 @@ Returns an address from within a ExtendRef.
 
 
 
-
- ## Function `disable_ungated_transfer` @@ -1341,13 +1239,15 @@ Disable direct transfer, transfers can only be triggered via a TransferRef -
-Implementation +##### Implementation
public fun disable_ungated_transfer(ref: &TransferRef) acquires ObjectCore {
     let object_core = borrow_global_mut<ObjectCore>(ref.self);
-    assert!(ref.version == object_core.version, error::permission_denied(EVERSION_MISMATCH));
+    assert!(
+        ref.version == object_core.version,
+        error::permission_denied(EVERSION_MISMATCH)
+    );
 
     object_core.allow_ungated_transfer = false;
 }
@@ -1355,8 +1255,6 @@ Disable direct transfer, transfers can only be triggered via a TransferRef
 
 
 
-
- ## Function `enable_ungated_transfer` @@ -1369,13 +1267,15 @@ Enable direct transfer. -
-Implementation +##### Implementation
public fun enable_ungated_transfer(ref: &TransferRef) acquires ObjectCore {
     let object_core = borrow_global_mut<ObjectCore>(ref.self);
-    assert!(ref.version == object_core.version, error::permission_denied(EVERSION_MISMATCH));
+    assert!(
+        ref.version == object_core.version,
+        error::permission_denied(EVERSION_MISMATCH)
+    );
 
     object_core.allow_ungated_transfer = true;
 }
@@ -1383,8 +1283,6 @@ Enable direct transfer.
 
 
 
-
- ## Function `generate_linear_transfer_ref` @@ -1398,26 +1296,28 @@ time of generation is the owner at the time of transferring. -
-Implementation +##### Implementation -
public fun generate_linear_transfer_ref(ref: &TransferRef): LinearTransferRef acquires ObjectCore {
+
public fun generate_linear_transfer_ref(
+    ref: &TransferRef
+): LinearTransferRef acquires ObjectCore {
     let object_core = borrow_global<ObjectCore>(ref.self);
-    assert!(ref.version == object_core.version, error::permission_denied(EVERSION_MISMATCH));
+    assert!(
+        ref.version == object_core.version,
+        error::permission_denied(EVERSION_MISMATCH)
+    );
 
     LinearTransferRef {
         self: ref.self,
         owner: object_core.owner,
-        version: object_core.version,
+        version: object_core.version
     }
 }
 
-
- ## Function `transfer_with_ref` @@ -1430,22 +1330,21 @@ Transfer to the destination address using a LinearTransferRef. -
-Implementation +##### Implementation
public fun transfer_with_ref(ref: LinearTransferRef, to: address) acquires ObjectCore {
     let object_core = borrow_global_mut<ObjectCore>(ref.self);
-    assert!(ref.version == object_core.version, error::permission_denied(EVERSION_MISMATCH));
-    assert!(object_core.owner == ref.owner, error::permission_denied(ENOT_OBJECT_OWNER));
-
-    event::emit(
-        TransferEvent {
-            object: ref.self,
-            from: object_core.owner,
-            to,
-        },
+    assert!(
+        ref.version == object_core.version,
+        error::permission_denied(EVERSION_MISMATCH)
     );
+    assert!(
+        object_core.owner == ref.owner,
+        error::permission_denied(ENOT_OBJECT_OWNER)
+    );
+
+    event::emit(TransferEvent { object: ref.self, from: object_core.owner, to });
 
     object_core.owner = to;
 }
@@ -1453,8 +1352,6 @@ Transfer to the destination address using a LinearTransferRef.
 
 
 
-
- ## Function `transfer_call` @@ -1467,14 +1364,11 @@ Entry function that can be used to transfer, if allow_ungated_transfer is set tr -
-Implementation +##### Implementation
public entry fun transfer_call(
-    owner: &signer,
-    object: address,
-    to: address,
+    owner: &signer, object: address, to: address
 ) acquires ObjectCore {
     transfer_raw(owner, object, to)
 }
@@ -1482,8 +1376,6 @@ Entry function that can be used to transfer, if allow_ungated_transfer is set tr
 
 
 
-
- ## Function `transfer` @@ -1497,14 +1389,11 @@ for Object to the "to" address. -
-Implementation +##### Implementation
public entry fun transfer<T: key>(
-    owner: &signer,
-    object: Object<T>,
-    to: address,
+    owner: &signer, object: Object<T>, to: address
 ) acquires ObjectCore {
     transfer_raw(owner, object.inner, to)
 }
@@ -1512,8 +1401,6 @@ for Object to the "to" address.
 
 
 
-
- ## Function `transfer_raw` @@ -1529,38 +1416,23 @@ hierarchy. -
-Implementation +##### Implementation -
public fun transfer_raw(
-    owner: &signer,
-    object: address,
-    to: address,
-) acquires ObjectCore {
+
public fun transfer_raw(owner: &signer, object: address, to: address) acquires ObjectCore {
     let owner_address = signer::address_of(owner);
     verify_ungated_and_descendant(owner_address, object);
 
     let object_core = borrow_global_mut<ObjectCore>(object);
-    if (object_core.owner == to) {
-        return
-    };
+    if (object_core.owner == to) { return };
 
-    event::emit(
-        TransferEvent {
-            object: object,
-            from: object_core.owner,
-            to,
-        },
-    );
+    event::emit(TransferEvent { object: object, from: object_core.owner, to });
     object_core.owner = to;
 }
 
-
- ## Function `transfer_to_object` @@ -1573,14 +1445,11 @@ Transfer the given object to another object. See transfer for more -
-Implementation +##### Implementation
public entry fun transfer_to_object<O: key, T: key>(
-    owner: &signer,
-    object: Object<O>,
-    to: Object<T>,
+    owner: &signer, object: Object<O>, to: Object<T>
 ) acquires ObjectCore {
     transfer(owner, object, to.inner)
 }
@@ -1588,67 +1457,6 @@ Transfer the given object to another object. See transfer for more
 
 
 
-
- - - -## Function `verify_ungated_and_descendant` - -This checks that the destination address is eventually owned by the owner and that each -object between the two allows for ungated transfers. Note, this is limited to a depth of 8 -objects may have cyclic dependencies. - - -
fun verify_ungated_and_descendant(owner: address, destination: address)
-
- - - -
-Implementation - - -
fun verify_ungated_and_descendant(owner: address, destination: address) acquires ObjectCore {
-    let current_address = destination;
-    assert!(
-        exists<ObjectCore>(current_address),
-        error::not_found(EOBJECT_DOES_NOT_EXIST),
-    );
-
-    let object = borrow_global<ObjectCore>(current_address);
-    assert!(
-        object.allow_ungated_transfer,
-        error::permission_denied(ENO_UNGATED_TRANSFERS),
-    );
-
-    let current_address = object.owner;
-
-    let count = 0;
-    while (owner != current_address) {
-        let count = count + 1;
-        assert!(count < MAXIMUM_OBJECT_NESTING, error::out_of_range(EMAXIMUM_NESTING));
-
-        // At this point, the first object exists and so the more likely case is that the
-        // object's owner is not an object. So we return a more sensible error.
-        assert!(
-            exists<ObjectCore>(current_address),
-            error::permission_denied(ENOT_OBJECT_OWNER),
-        );
-        let object = borrow_global<ObjectCore>(current_address);
-        assert!(
-            object.allow_ungated_transfer,
-            error::permission_denied(ENO_UNGATED_TRANSFERS),
-        );
-
-        current_address = object.owner;
-    };
-}
-
- - - -
- ## Function `ungated_transfer_allowed` @@ -1662,14 +1470,13 @@ Return true if ungated transfer is allowed. -
-Implementation +##### Implementation
public fun ungated_transfer_allowed<T: key>(object: Object<T>): bool acquires ObjectCore {
     assert!(
         exists<ObjectCore>(object.inner),
-        error::not_found(EOBJECT_DOES_NOT_EXIST),
+        error::not_found(EOBJECT_DOES_NOT_EXIST)
     );
     borrow_global<ObjectCore>(object.inner).allow_ungated_transfer
 }
@@ -1677,8 +1484,6 @@ Return true if ungated transfer is allowed.
 
 
 
-
- ## Function `owner` @@ -1692,14 +1497,13 @@ Return the current owner. -
-Implementation +##### Implementation
public fun owner<T: key>(object: Object<T>): address acquires ObjectCore {
     assert!(
         exists<ObjectCore>(object.inner),
-        error::not_found(EOBJECT_DOES_NOT_EXIST),
+        error::not_found(EOBJECT_DOES_NOT_EXIST)
     );
     borrow_global<ObjectCore>(object.inner).owner
 }
@@ -1707,8 +1511,6 @@ Return the current owner.
 
 
 
-
- ## Function `is_owner` @@ -1722,8 +1524,7 @@ Return true if the provided address is the current owner. -
-Implementation +##### Implementation
public fun is_owner<T: key>(object: Object<T>, owner: address): bool acquires ObjectCore {
@@ -1733,8 +1534,6 @@ Return true if the provided address is the current owner.
 
 
 
-
- ## Function `owns` @@ -1748,19 +1547,18 @@ Return true if the provided address has indirect or direct ownership of the prov -
-Implementation +##### Implementation
public fun owns<T: key>(object: Object<T>, owner: address): bool acquires ObjectCore {
-    let current_address = object_address(object);
+    let current_address = object_address(&object);
     if (current_address == owner) {
         return true
     };
 
     assert!(
         exists<ObjectCore>(current_address),
-        error::not_found(EOBJECT_DOES_NOT_EXIST),
+        error::not_found(EOBJECT_DOES_NOT_EXIST)
     );
 
     let object = borrow_global<ObjectCore>(current_address);
@@ -1768,8 +1566,11 @@ Return true if the provided address has indirect or direct ownership of the prov
 
     let count = 0;
     while (owner != current_address) {
-        let count = count + 1;
-        assert!(count < MAXIMUM_OBJECT_NESTING, error::out_of_range(EMAXIMUM_NESTING));
+        count = count + 1;
+        assert!(
+            count < MAXIMUM_OBJECT_NESTING,
+            error::out_of_range(EMAXIMUM_NESTING)
+        );
         if (!exists<ObjectCore>(current_address)) {
             return false
         };
@@ -1780,7 +1581,3 @@ Return true if the provided address has indirect or direct ownership of the prov
     true
 }
 
- - - -
diff --git a/initia_stdlib/doc/object_code_deployment.md b/initia_stdlib/doc/object_code_deployment.md new file mode 100644 index 0000000..8e0d276 --- /dev/null +++ b/initia_stdlib/doc/object_code_deployment.md @@ -0,0 +1,316 @@ + + + +# Module `0x1::object_code_deployment` + +This module allows users to deploy, upgrade and freeze modules deployed to objects on-chain. +This enables users to deploy modules to an object with a unique address each time they are published. +This modules provides an alternative method to publish code on-chain, where code is deployed to objects rather than accounts. +This is encouraged as it abstracts the necessary resources needed for deploying modules, +along with the required authorization to upgrade and freeze modules. + +The functionalities of this module are as follows. + +Publishing modules flow: +1. Create a new object with the address derived from the publisher address and the object seed. +2. Publish the module passed in the function via metadata_serialized and code to the newly created object. +3. Emits 'Publish' event with the address of the newly created object. +4. Create a ManagingRefs which stores the extend ref of the newly created object. +Note: This is needed to upgrade the code as the signer must be generated to upgrade the existing code in an object. + +Upgrading modules flow: +1. Assert the code_object passed in the function is owned by the publisher. +2. Assert the code_object passed in the function exists in global storage. +2. Retrieve the ExtendRef from the code_object and generate the signer from this. +3. Upgrade the module with the metadata_serialized and code passed in the function. +4. Emits 'Upgrade' event with the address of the object with the upgraded code. +Note: If the modules were deployed as immutable when calling publish, the upgrade will fail. + +Freezing modules flow: +1. Assert the code_object passed in the function exists in global storage. +2. Assert the code_object passed in the function is owned by the publisher. +3. Mark all the modules in the code_object as immutable. +4. Emits 'Freeze' event with the address of the object with the frozen code. +Note: There is no unfreeze function as this gives no benefit if the user can freeze/unfreeze modules at will. +Once modules are marked as immutable, they cannot be made mutable again. + + +- [Resource `ManagingRefs`](#0x1_object_code_deployment_ManagingRefs) +- [Struct `Publish`](#0x1_object_code_deployment_Publish) +- [Struct `Upgrade`](#0x1_object_code_deployment_Upgrade) +- [Struct `Freeze`](#0x1_object_code_deployment_Freeze) +- [Constants](#@Constants_0) +- [Function `publish`](#0x1_object_code_deployment_publish) +- [Function `upgrade`](#0x1_object_code_deployment_upgrade) +- [Function `freeze_code_object`](#0x1_object_code_deployment_freeze_code_object) + + +
use 0x1::account;
+use 0x1::bcs;
+use 0x1::code;
+use 0x1::error;
+use 0x1::event;
+use 0x1::object;
+use 0x1::signer;
+use 0x1::string;
+use 0x1::vector;
+
+ + + + + +## Resource `ManagingRefs` + +Internal struct, attached to the object, that holds Refs we need to manage the code deployment (i.e. upgrades). + + +
struct ManagingRefs has key
+
+ + + +##### Fields + + +
+
+extend_ref: object::ExtendRef +
+
+ We need to keep the extend ref to be able to generate the signer to upgrade existing code. +
+
+ + + + +## Struct `Publish` + +Event emitted when code is published to an object. + + +
#[event]
+struct Publish has drop, store
+
+ + + +##### Fields + + +
+
+object_address: address +
+
+ +
+
+ + + + +## Struct `Upgrade` + +Event emitted when code in an existing object is upgraded. + + +
#[event]
+struct Upgrade has drop, store
+
+ + + +##### Fields + + +
+
+object_address: address +
+
+ +
+
+ + + + +## Struct `Freeze` + +Event emitted when code in an existing object is made immutable. + + +
#[event]
+struct Freeze has drop, store
+
+ + + +##### Fields + + +
+
+object_address: address +
+
+ +
+
+ + + + +## Constants + + + + +code_object does not exist. + + +
const ECODE_OBJECT_DOES_NOT_EXIST: u64 = 3;
+
+ + + + + +Not the owner of the code_object + + +
const ENOT_CODE_OBJECT_OWNER: u64 = 2;
+
+ + + + + +Object code deployment feature not supported. + + +
const EOBJECT_CODE_DEPLOYMENT_NOT_SUPPORTED: u64 = 1;
+
+ + + + + + + +
const OBJECT_CODE_DEPLOYMENT_DOMAIN_SEPARATOR: vector<u8> = [105, 110, 105, 116, 105, 97, 95, 115, 116, 100, 58, 58, 111, 98, 106, 101, 99, 116, 95, 99, 111, 100, 101, 95, 100, 101, 112, 108, 111, 121, 109, 101, 110, 116];
+
+ + + + + +## Function `publish` + +Creates a new object with a unique address derived from the publisher address and the object seed. +Publishes the code passed in the function to the newly created object. +The caller must provide package metadata describing the package via metadata_serialized and +the code to be published via code. This contains a vector of modules to be deployed on-chain. + + +
public entry fun publish(publisher: &signer, module_ids: vector<string::String>, code: vector<vector<u8>>)
+
+ + + +##### Implementation + + +
public entry fun publish(
+    publisher: &signer, module_ids: vector<String>, code: vector<vector<u8>>
+) {
+    let publisher_address = signer::address_of(publisher);
+    let object_seed = object_seed(publisher_address);
+    let constructor_ref = &object::create_named_object(publisher, object_seed);
+    let code_signer = &object::generate_signer(constructor_ref);
+    code::publish(code_signer, module_ids, code, 1);
+
+    event::emit(Publish { object_address: signer::address_of(code_signer) });
+
+    move_to(
+        code_signer,
+        ManagingRefs { extend_ref: object::generate_extend_ref(constructor_ref) }
+    );
+}
+
+ + + + + +## Function `upgrade` + +Upgrades the existing modules at the code_object address with the new modules passed in code, +along with the metadata metadata_serialized. +Note: If the modules were deployed as immutable when calling publish, the upgrade will fail. +Requires the publisher to be the owner of the code_object. + + +
public entry fun upgrade(publisher: &signer, module_ids: vector<string::String>, code: vector<vector<u8>>, code_object: object::Object<code::MetadataStore>)
+
+ + + +##### Implementation + + +
public entry fun upgrade(
+    publisher: &signer,
+    module_ids: vector<String>,
+    code: vector<vector<u8>>,
+    code_object: Object<MetadataStore>
+) acquires ManagingRefs {
+    let publisher_address = signer::address_of(publisher);
+    assert!(
+        object::is_owner(code_object, publisher_address),
+        error::permission_denied(ENOT_CODE_OBJECT_OWNER)
+    );
+
+    let code_object_address = object::object_address(&code_object);
+    assert!(
+        exists<ManagingRefs>(code_object_address),
+        error::not_found(ECODE_OBJECT_DOES_NOT_EXIST)
+    );
+
+    let extend_ref = &borrow_global<ManagingRefs>(code_object_address).extend_ref;
+    let code_signer = &object::generate_signer_for_extending(extend_ref);
+    code::publish(code_signer, module_ids, code, 1);
+
+    event::emit(Upgrade { object_address: signer::address_of(code_signer) });
+}
+
+ + + + + +## Function `freeze_code_object` + +Make an existing upgradable package immutable. Once this is called, the package cannot be made upgradable again. +Each code_object should only have one package, as one package is deployed per object in this module. +Requires the publisher to be the owner of the code_object. + + +
public entry fun freeze_code_object(publisher: &signer, code_object: object::Object<code::MetadataStore>)
+
+ + + +##### Implementation + + +
public entry fun freeze_code_object(
+    publisher: &signer, code_object: Object<MetadataStore>
+) {
+    code::freeze_code_object(publisher, code_object);
+
+    event::emit(Freeze { object_address: object::object_address(&code_object) });
+}
+
diff --git a/initia_stdlib/doc/operator.md b/initia_stdlib/doc/operator.md deleted file mode 100644 index ba97666..0000000 --- a/initia_stdlib/doc/operator.md +++ /dev/null @@ -1,612 +0,0 @@ - - - -# Module `0x1::vip_operator` - - - -- [Resource `OperatorStore`](#0x1_vip_operator_OperatorStore) -- [Struct `OperatorStoreResponse`](#0x1_vip_operator_OperatorStoreResponse) -- [Struct `UpdateCommissionEvent`](#0x1_vip_operator_UpdateCommissionEvent) -- [Constants](#@Constants_0) -- [Function `check_chain_permission`](#0x1_vip_operator_check_chain_permission) -- [Function `check_valid_rate`](#0x1_vip_operator_check_valid_rate) -- [Function `is_valid_commission_rates`](#0x1_vip_operator_is_valid_commission_rates) -- [Function `register_operator_store`](#0x1_vip_operator_register_operator_store) -- [Function `update_operator_commission`](#0x1_vip_operator_update_operator_commission) -- [Function `generate_operator_store_seed`](#0x1_vip_operator_generate_operator_store_seed) -- [Function `create_operator_store_address`](#0x1_vip_operator_create_operator_store_address) -- [Function `is_operator_store_registered`](#0x1_vip_operator_is_operator_store_registered) -- [Function `get_operator_store_address`](#0x1_vip_operator_get_operator_store_address) -- [Function `get_operator_store`](#0x1_vip_operator_get_operator_store) -- [Function `get_operator_commission`](#0x1_vip_operator_get_operator_commission) - - -
use 0x1::bcs;
-use 0x1::decimal256;
-use 0x1::error;
-use 0x1::event;
-use 0x1::object;
-use 0x1::signer;
-use 0x1::vector;
-
- - - - - -## Resource `OperatorStore` - - - -
struct OperatorStore has key
-
- - - -
-Fields - - -
-
-last_changed_stage: u64 -
-
- -
-
-commission_max_rate: decimal256::Decimal256 -
-
- -
-
-commission_max_change_rate: decimal256::Decimal256 -
-
- -
-
-commission_rate: decimal256::Decimal256 -
-
- -
-
- - -
- - - -## Struct `OperatorStoreResponse` - - - -
struct OperatorStoreResponse has drop
-
- - - -
-Fields - - -
-
-last_changed_stage: u64 -
-
- -
-
-commission_max_rate: decimal256::Decimal256 -
-
- -
-
-commission_max_change_rate: decimal256::Decimal256 -
-
- -
-
-commission_rate: decimal256::Decimal256 -
-
- -
-
- - -
- - - -## Struct `UpdateCommissionEvent` - - - -
#[event]
-struct UpdateCommissionEvent has drop, store
-
- - - -
-Fields - - -
-
-operator: address -
-
- -
-
-bridge_id: u64 -
-
- -
-
-stage: u64 -
-
- -
-
-commission_rate: decimal256::Decimal256 -
-
- -
-
- - -
- - - -## Constants - - - - - - -
const EUNAUTHORIZED: u64 = 7;
-
- - - - - - - -
const EINVALID_STAGE: u64 = 5;
-
- - - - - - - -
const EINVALID_COMMISSION_CHANGE_RATE: u64 = 3;
-
- - - - - - - -
const EINVALID_COMMISSION_RATE: u64 = 6;
-
- - - - - - - -
const EOPERATOR_STORE_ALREADY_EXISTS: u64 = 1;
-
- - - - - - - -
const EOPERATOR_STORE_NOT_FOUND: u64 = 2;
-
- - - - - - - -
const EOVER_MAX_COMMISSION_RATE: u64 = 4;
-
- - - - - - - -
const OPERATOR_STORE_PREFIX: u8 = 246;
-
- - - - - -## Function `check_chain_permission` - - - -
fun check_chain_permission(chain: &signer)
-
- - - -
-Implementation - - -
fun check_chain_permission(chain: &signer) {
-    assert!(signer::address_of(chain) == @initia_std, error::permission_denied(EUNAUTHORIZED));
-}
-
- - - -
- - - -## Function `check_valid_rate` - - - -
fun check_valid_rate(rate: &decimal256::Decimal256)
-
- - - -
-Implementation - - -
fun check_valid_rate(rate: &Decimal256) {
-    assert!(
-        decimal256::val(rate) <= decimal256::val(&decimal256::one()),
-        error::invalid_argument(EINVALID_COMMISSION_RATE)
-    );
-}
-
- - - -
- - - -## Function `is_valid_commission_rates` - - - -
fun is_valid_commission_rates(commission_max_rate: &decimal256::Decimal256, commission_max_change_rate: &decimal256::Decimal256, commission_rate: &decimal256::Decimal256)
-
- - - -
-Implementation - - -
fun is_valid_commission_rates(
-    commission_max_rate: &Decimal256,
-    commission_max_change_rate: &Decimal256,
-    commission_rate: &Decimal256
-) {
-    check_valid_rate(commission_max_rate);
-    check_valid_rate(commission_max_change_rate);
-    check_valid_rate(commission_rate);
-    assert!(
-        decimal256::val(commission_rate) <= decimal256::val(commission_max_rate),
-        error::invalid_argument(EOVER_MAX_COMMISSION_RATE)
-    );
-}
-
- - - -
- - - -## Function `register_operator_store` - - - -
public(friend) fun register_operator_store(chain: &signer, operator: address, bridge_id: u64, stage: u64, commission_max_rate: decimal256::Decimal256, commission_max_change_rate: decimal256::Decimal256, commission_rate: decimal256::Decimal256)
-
- - - -
-Implementation - - -
public(friend) fun register_operator_store(
-    chain: &signer,
-    operator: address,
-    bridge_id: u64,
-    stage: u64,
-    commission_max_rate: Decimal256,
-    commission_max_change_rate: Decimal256,
-    commission_rate: Decimal256
-) {
-    check_chain_permission(chain);
-    let seed = generate_operator_store_seed(operator, bridge_id);
-    let operator_addr = object::create_object_address(signer::address_of(chain), seed);
-    assert!(!exists<OperatorStore>(operator_addr), error::already_exists(EOPERATOR_STORE_ALREADY_EXISTS));
-
-    is_valid_commission_rates(&commission_max_rate, &commission_max_change_rate, &commission_rate);
-
-    let constructor_ref = object::create_named_object(chain, seed, false);
-    let transfer_ref = object::generate_transfer_ref(&constructor_ref);
-    object::disable_ungated_transfer(&transfer_ref);
-    let object = object::generate_signer(&constructor_ref);
-
-    let operator_store = OperatorStore {
-        last_changed_stage: stage,
-        commission_max_rate,
-        commission_max_change_rate,
-        commission_rate,
-    };
-    move_to(&object, operator_store);
-}
-
- - - -
- - - -## Function `update_operator_commission` - - - -
public(friend) fun update_operator_commission(operator: &signer, bridge_id: u64, stage: u64, commission_rate: decimal256::Decimal256)
-
- - - -
-Implementation - - -
public(friend) fun update_operator_commission(
-    operator: &signer,
-    bridge_id: u64,
-    stage: u64,
-    commission_rate: Decimal256
-) acquires OperatorStore {
-    let operator_addr = signer::address_of(operator);
-    let operator_store_addr = get_operator_store_address(operator_addr, bridge_id);
-    let operator_store = borrow_global_mut<OperatorStore>(operator_store_addr);
-
-    // commission can be updated once per a stage.
-    assert!(stage > operator_store.last_changed_stage, error::invalid_argument(EINVALID_STAGE));
-
-    let old_commission_rate = decimal256::val(&operator_store.commission_rate);
-    let new_commission_rate = decimal256::val(&commission_rate);
-    let max_commission_change_rate = decimal256::val(&operator_store.commission_max_change_rate);
-    let max_commission_rate = decimal256::val(&operator_store.commission_max_rate);
-
-    assert!(new_commission_rate <= max_commission_rate, error::invalid_argument(EOVER_MAX_COMMISSION_RATE));
-
-    if (old_commission_rate > new_commission_rate) {
-        let change = old_commission_rate - new_commission_rate;
-        assert!(change <= max_commission_change_rate, error::invalid_argument(EINVALID_COMMISSION_CHANGE_RATE));
-    } else {
-        let change = new_commission_rate - old_commission_rate;
-        assert!(change <= max_commission_change_rate, error::invalid_argument(EINVALID_COMMISSION_CHANGE_RATE));
-    };
-
-    operator_store.commission_rate = commission_rate;
-    operator_store.last_changed_stage = stage;
-
-    event::emit(
-        UpdateCommissionEvent {
-            operator: operator_addr,
-            bridge_id: bridge_id,
-            stage: operator_store.last_changed_stage,
-            commission_rate
-        }
-    );
-}
-
- - - -
- - - -## Function `generate_operator_store_seed` - - - -
fun generate_operator_store_seed(operator: address, bridge_id: u64): vector<u8>
-
- - - -
-Implementation - - -
fun generate_operator_store_seed(operator:address, bridge_id: u64) : vector<u8> {
-    let seed = vector[OPERATOR_STORE_PREFIX];
-    vector::append(&mut seed, bcs::to_bytes(&operator));
-    vector::append(&mut seed, bcs::to_bytes(&bridge_id));
-    return seed
-}
-
- - - -
- - - -## Function `create_operator_store_address` - - - -
fun create_operator_store_address(operator_addr: address, bridge_id: u64): address
-
- - - -
-Implementation - - -
fun create_operator_store_address(operator_addr: address, bridge_id: u64): address {
-    let seed = generate_operator_store_seed(operator_addr, bridge_id);
-    object::create_object_address(@initia_std, seed)
-}
-
- - - -
- - - -## Function `is_operator_store_registered` - - - -
#[view]
-public fun is_operator_store_registered(operator_addr: address, bridge_id: u64): bool
-
- - - -
-Implementation - - -
public fun is_operator_store_registered(operator_addr: address, bridge_id: u64): bool {
-    exists<OperatorStore>(create_operator_store_address(operator_addr, bridge_id))
-}
-
- - - -
- - - -## Function `get_operator_store_address` - - - -
#[view]
-public fun get_operator_store_address(operator_addr: address, bridge_id: u64): address
-
- - - -
-Implementation - - -
public fun get_operator_store_address(operator_addr: address, bridge_id: u64): address {
-    let operator_store_addr = create_operator_store_address(operator_addr, bridge_id);
-    assert!(exists<OperatorStore>(operator_store_addr), error::not_found(EOPERATOR_STORE_NOT_FOUND));
-    operator_store_addr
-}
-
- - - -
- - - -## Function `get_operator_store` - - - -
#[view]
-public fun get_operator_store(operator: address, bridge_id: u64): vip_operator::OperatorStoreResponse
-
- - - -
-Implementation - - -
public fun get_operator_store(
-    operator: address,
-    bridge_id: u64
-): OperatorStoreResponse acquires OperatorStore {
-    let operator_store_addr = get_operator_store_address(operator, bridge_id);
-    let operator_store = borrow_global<OperatorStore>(operator_store_addr);
-    OperatorStoreResponse {
-        last_changed_stage: operator_store.last_changed_stage,
-        commission_max_rate: operator_store.commission_max_rate,
-        commission_max_change_rate: operator_store.commission_max_change_rate,
-        commission_rate: operator_store.commission_rate,
-    }
-}
-
- - - -
- - - -## Function `get_operator_commission` - - - -
#[view]
-public fun get_operator_commission(operator: address, bridge_id: u64): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun get_operator_commission(
-    operator: address,
-    bridge_id: u64
-): Decimal256 acquires OperatorStore {
-    let operator_store_addr = get_operator_store_address(operator, bridge_id);
-    let operator_store = borrow_global<OperatorStore>(operator_store_addr);
-    operator_store.commission_rate
-}
-
- - - -
diff --git a/initia_stdlib/doc/oracle.md b/initia_stdlib/doc/oracle.md index 1631bd1..00f23d3 100644 --- a/initia_stdlib/doc/oracle.md +++ b/initia_stdlib/doc/oracle.md @@ -6,7 +6,6 @@ - [Function `get_price`](#0x1_oracle_get_price) -- [Function `get_price_internal`](#0x1_oracle_get_price_internal)
use 0x1::string;
@@ -26,37 +25,10 @@
 
 
 
-
-Implementation +##### Implementation
public fun get_price(pair_id: String): (u256, u64, u64) {
     get_price_internal(*string::bytes(&pair_id))
 }
 
- - - -
- - - -## Function `get_price_internal` - - - -
fun get_price_internal(pair_id: vector<u8>): (u256, u64, u64)
-
- - - -
-Implementation - - -
native fun get_price_internal(pair_id: vector<u8>): (u256, u64, u64);
-
- - - -
diff --git a/initia_stdlib/doc/primary_fungible_store.md b/initia_stdlib/doc/primary_fungible_store.md index f59873d..a28e034 100644 --- a/initia_stdlib/doc/primary_fungible_store.md +++ b/initia_stdlib/doc/primary_fungible_store.md @@ -21,7 +21,6 @@ fungible asset to it. This emits an deposit event. - [Resource `DeriveRefPod`](#0x1_primary_fungible_store_DeriveRefPod) - [Resource `ModuleStore`](#0x1_primary_fungible_store_ModuleStore) - [Struct `PrimaryStoreCreatedEvent`](#0x1_primary_fungible_store_PrimaryStoreCreatedEvent) -- [Function `init_module`](#0x1_primary_fungible_store_init_module) - [Function `create_primary_store_enabled_fungible_asset`](#0x1_primary_fungible_store_create_primary_store_enabled_fungible_asset) - [Function `ensure_primary_store_exists`](#0x1_primary_fungible_store_ensure_primary_store_exists) - [Function `create_primary_store`](#0x1_primary_fungible_store_create_primary_store) @@ -32,9 +31,12 @@ fungible asset to it. This emits an deposit event. - [Function `is_frozen`](#0x1_primary_fungible_store_is_frozen) - [Function `balance`](#0x1_primary_fungible_store_balance) - [Function `balances`](#0x1_primary_fungible_store_balances) +- [Function `sudo_deposit`](#0x1_primary_fungible_store_sudo_deposit) +- [Function `sudo_transfer`](#0x1_primary_fungible_store_sudo_transfer) - [Function `withdraw`](#0x1_primary_fungible_store_withdraw) - [Function `deposit`](#0x1_primary_fungible_store_deposit) - [Function `transfer`](#0x1_primary_fungible_store_transfer) +- [Function `transfer_assert_minimum_deposit`](#0x1_primary_fungible_store_transfer_assert_minimum_deposit) - [Function `mint`](#0x1_primary_fungible_store_mint) - [Function `burn`](#0x1_primary_fungible_store_burn) - [Function `set_frozen_flag`](#0x1_primary_fungible_store_set_frozen_flag) @@ -44,6 +46,7 @@ fungible asset to it. This emits an deposit event.
use 0x1::account;
+use 0x1::dispatchable_fungible_asset;
 use 0x1::event;
 use 0x1::fungible_asset;
 use 0x1::object;
@@ -69,8 +72,7 @@ assets.
 
 
 
-
-Fields +##### Fields
@@ -83,8 +85,6 @@ assets.
-
- ## Resource `ModuleStore` @@ -96,8 +96,7 @@ assets. -
-Fields +##### Fields
@@ -116,8 +115,6 @@ assets.
-
- ## Struct `PrimaryStoreCreatedEvent` @@ -130,8 +127,7 @@ assets. -
-Fields +##### Fields
@@ -156,35 +152,6 @@ assets.
-
- - - -## Function `init_module` - - - -
fun init_module(chain: &signer)
-
- - - -
-Implementation - - -
fun init_module (chain: &signer) {
-    move_to(chain, ModuleStore {
-        issuers: table::new(),
-        user_stores: table::new(),
-    })
-}
-
- - - -
- ## Function `create_primary_store_enabled_fungible_asset` @@ -199,8 +166,7 @@ so that users can easily deposit/withdraw/transfer fungible assets. -
-Implementation +##### Implementation
public fun create_primary_store_enabled_fungible_asset(
@@ -210,7 +176,7 @@ so that users can easily deposit/withdraw/transfer fungible assets.
     symbol: String,
     decimals: u8,
     icon_uri: String,
-    project_uri: String,
+    project_uri: String
 ) acquires ModuleStore {
     fungible_asset::add_fungibility(
         constructor_ref,
@@ -219,28 +185,32 @@ so that users can easily deposit/withdraw/transfer fungible assets.
         symbol,
         decimals,
         icon_uri,
-        project_uri,
+        project_uri
     );
 
     let metadata = object::object_from_constructor_ref<Metadata>(constructor_ref);
     let metadata_signer = &object::generate_signer(constructor_ref);
-    move_to(metadata_signer, DeriveRefPod {
-        metadata_derive_ref: object::generate_derive_ref(constructor_ref),
-    });
-
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    table::add(
-        &mut module_store.issuers,
-        object::object_address(metadata),
-        object::owner(metadata),
+    move_to(
+        metadata_signer,
+        DeriveRefPod {
+            metadata_derive_ref: object::generate_derive_ref(constructor_ref)
+        }
     );
+
+    // record issuers for cosmos side query
+    if (exists<ModuleStore>(@initia_std)) {
+        let module_store = borrow_global_mut<ModuleStore>(@initia_std);
+        table::add(
+            &mut module_store.issuers,
+            object::object_address(&metadata),
+            object::owner(metadata)
+        );
+    }
 }
 
-
- ## Function `ensure_primary_store_exists` @@ -253,13 +223,11 @@ Ensure that the primary store object for the given address exists. If it doesn't -
-Implementation +##### Implementation
public fun ensure_primary_store_exists<T: key>(
-    owner: address,
-    metadata: Object<T>,
+    owner: address, metadata: Object<T>
 ): Object<FungibleStore> acquires DeriveRefPod, ModuleStore {
     if (!primary_store_exists(owner, metadata)) {
         create_primary_store(owner, metadata)
@@ -271,8 +239,6 @@ Ensure that the primary store object for the given address exists. If it doesn't
 
 
 
-
- ## Function `create_primary_store` @@ -285,55 +251,62 @@ Create a primary store object to hold fungible asset for the given address. -
-Implementation +##### Implementation
public fun create_primary_store<T: key>(
-    owner_addr: address,
-    metadata: Object<T>,
+    owner_addr: address, metadata: Object<T>
 ): Object<FungibleStore> acquires DeriveRefPod, ModuleStore {
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
     object::address_to_object<Metadata>(metadata_addr);
 
     let derive_ref = &borrow_global<DeriveRefPod>(metadata_addr).metadata_derive_ref;
-    let constructor_ref = &object::create_user_derived_object(owner_addr, derive_ref, false);
+    let constructor_ref =
+        &object::create_user_derived_object(owner_addr, derive_ref, false);
 
     // Disable ungated transfer as deterministic stores shouldn't be transferrable.
     let transfer_ref = &object::generate_transfer_ref(constructor_ref);
     object::disable_ungated_transfer(transfer_ref);
 
     let store = fungible_asset::create_store(constructor_ref, metadata);
+    let store_addr = object::address_from_constructor_ref(constructor_ref);
 
-    // add owner store to table for balances query
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    if (!table::contains(&module_store.user_stores, owner_addr)) {
-        table::add(&mut module_store.user_stores, owner_addr, table::new());
+    // record owner store to table for cosmos side query
+    if (exists<ModuleStore>(@initia_std)) {
+        let module_store = borrow_global_mut<ModuleStore>(@initia_std);
+        if (!table::contains(
+            &module_store.user_stores,
+            owner_addr
+        )) {
+            table::add(
+                &mut module_store.user_stores,
+                owner_addr,
+                table::new()
+            );
+        };
+
+        let user_stores = table::borrow_mut(&mut module_store.user_stores, owner_addr);
+
+        table::add(
+            user_stores,
+            metadata_addr,
+            store_addr
+        );
     };
 
-    let user_stores = table::borrow_mut(&mut module_store.user_stores, owner_addr);
-    let store_addr = object::address_from_constructor_ref(constructor_ref);
-    table::add(user_stores, metadata_addr, store_addr);
-
     // emit store created event
-    event::emit(PrimaryStoreCreatedEvent {
-        owner_addr,
-        store_addr,
-        metadata_addr,
-    });
-
+    event::emit(PrimaryStoreCreatedEvent { owner_addr, store_addr, metadata_addr });
     store
 }
 
-
- ## Function `issuer` +Get the address of the issuer for the given metadata object.
#[view]
@@ -342,20 +315,20 @@ Create a primary store object to hold fungible asset for the given address.
 
 
 
-
-Implementation +##### Implementation
public fun issuer<T: key>(metadata: Object<T>): address acquires ModuleStore {
     let module_store = borrow_global<ModuleStore>(@initia_std);
-    *table::borrow(&module_store.issuers, object::object_address(metadata))
+    *table::borrow(
+        &module_store.issuers,
+        object::object_address(&metadata)
+    )
 }
 
-
- ## Function `primary_store_address` @@ -369,20 +342,19 @@ Get the address of the primary store for the given account. -
-Implementation +##### Implementation -
public fun primary_store_address<T: key>(owner: address, metadata: Object<T>): address {
-    let metadata_addr = object::object_address(metadata);
+
public fun primary_store_address<T: key>(
+    owner: address, metadata: Object<T>
+): address {
+    let metadata_addr = object::object_address(&metadata);
     object::create_user_derived_object_address(owner, metadata_addr)
 }
 
-
- ## Function `primary_store` @@ -396,11 +368,11 @@ Get the primary store object for the given account. -
-Implementation +##### Implementation -
public fun primary_store<T: key>(owner: address, metadata: Object<T>): Object<FungibleStore> {
+
public fun primary_store<T: key>(owner: address, metadata: Object<T>):
+    Object<FungibleStore> {
     let store = primary_store_address(owner, metadata);
     object::address_to_object<FungibleStore>(store)
 }
@@ -408,8 +380,6 @@ Get the primary store object for the given account.
 
 
 
-
- ## Function `primary_store_exists` @@ -423,19 +393,18 @@ Return whether the given account's primary store exists. -
-Implementation +##### Implementation -
public fun primary_store_exists<T: key>(account: address, metadata: Object<T>): bool {
+
public fun primary_store_exists<T: key>(
+    account: address, metadata: Object<T>
+): bool {
     fungible_asset::store_exists(primary_store_address(account, metadata))
 }
 
-
- ## Function `is_frozen` @@ -449,23 +418,18 @@ Return whether the given account's primary store is frozen. -
-Implementation +##### Implementation
public fun is_frozen<T: key>(account: address, metadata: Object<T>): bool {
     if (primary_store_exists(account, metadata)) {
         fungible_asset::is_frozen(primary_store(account, metadata))
-    } else {
-        false
-    }
+    } else { false }
 }
 
-
- ## Function `balance` @@ -479,27 +443,23 @@ Get the balance of account's p -
-Implementation +##### Implementation
public fun balance<T: key>(account: address, metadata: Object<T>): u64 {
     if (primary_store_exists(account, metadata)) {
         fungible_asset::balance(primary_store(account, metadata))
-    } else {
-        0
-    }
+    } else { 0 }
 }
 
-
- ## Function `balances` +Get the balances of account's primary store of all fungible assets.
#[view]
@@ -508,34 +468,35 @@ Get the balance of account's p
 
 
 
-
-Implementation +##### Implementation
public fun balances(
-    account: address,
-    start_after: Option<address>,
-    limit: u8,
-): (vector<Object<Metadata>>, vector<u64>)  acquires ModuleStore {
+    account: address, start_after: Option<address>, limit: u8
+): (vector<Object<Metadata>>, vector<u64>) acquires ModuleStore {
     let module_store = borrow_global<ModuleStore>(@initia_std);
     let account_stores = table::borrow(&module_store.user_stores, account);
     let iter = table::iter(
         account_stores,
         option::none(),
         start_after,
-        2,
+        2
     );
 
     let metadata_vec: vector<Object<Metadata>> = vector[];
     let balance_vec: vector<u64> = vector[];
 
-    while (table::prepare<address, address>(&mut iter) && vector::length(&balance_vec) < (limit as u64)) {
-        let (metadata_addr, store_addr) = table::next<address, address>(&mut iter);
+    while (table::prepare<address, address>(iter)
+        && vector::length(&balance_vec) < (limit as u64)) {
+        let (metadata_addr, store_addr) = table::next<address, address>(iter);
         let metadata = object::address_to_object<Metadata>(metadata_addr);
         let store = object::address_to_object<FungibleStore>(*store_addr);
 
         vector::push_back(&mut metadata_vec, metadata);
-        vector::push_back(&mut balance_vec, fungible_asset::balance(store));
+        vector::push_back(
+            &mut balance_vec,
+            fungible_asset::balance(store)
+        );
     };
 
     (metadata_vec, balance_vec)
@@ -544,7 +505,75 @@ Get the balance of account's p
 
 
 
-
+ + +## Function `sudo_deposit` + +Deposit fungible asset fa to the given account's primary store. + +This function is only callable by the chain. + + +
public(friend) fun sudo_deposit(owner: address, fa: fungible_asset::FungibleAsset)
+
+ + + +##### Implementation + + +
public(friend) fun sudo_deposit(
+    owner: address, fa: FungibleAsset
+) acquires DeriveRefPod, ModuleStore {
+    let metadata = fungible_asset::asset_metadata(&fa);
+    let store = ensure_primary_store_exists(owner, metadata);
+    fungible_asset::sudo_deposit(store, fa);
+
+    // create cosmos side account
+    if (!account::exists_at(owner)) {
+        let _acc_num = account::create_account(owner);
+    };
+}
+
+ + + + + +## Function `sudo_transfer` + +Transfer amount of fungible asset from sender's primary store to receiver's primary store. + +This function is only callable by the chain. + + +
public(friend) fun sudo_transfer<T: key>(sender: &signer, metadata: object::Object<T>, recipient: address, amount: u64)
+
+ + + +##### Implementation + + +
public(friend) fun sudo_transfer<T: key>(
+    sender: &signer,
+    metadata: Object<T>,
+    recipient: address,
+    amount: u64
+) acquires DeriveRefPod, ModuleStore {
+    let sender_store =
+        ensure_primary_store_exists(signer::address_of(sender), metadata);
+    let recipient_store = ensure_primary_store_exists(recipient, metadata);
+    fungible_asset::sudo_transfer(
+        sender,
+        sender_store,
+        recipient_store,
+        amount
+    );
+}
+
+ + @@ -558,20 +587,23 @@ Withdraw amount of fungible asset from the given account's primary -
-Implementation +##### Implementation -
public fun withdraw<T: key>(owner: &signer, metadata: Object<T>, amount: u64): FungibleAsset {
+
public fun withdraw<T: key>(
+    owner: &signer, metadata: Object<T>, amount: u64
+): FungibleAsset {
+    if (amount == 0) {
+        return fungible_asset::zero(metadata)
+    };
+
     let store = primary_store(signer::address_of(owner), metadata);
-    fungible_asset::withdraw(owner, store, amount)
+    dispatchable_fungible_asset::withdraw(owner, store, amount)
 }
 
-
- ## Function `deposit` @@ -584,14 +616,13 @@ Deposit fungible asset fa to the given account's primary store. -
-Implementation +##### Implementation
public fun deposit(owner: address, fa: FungibleAsset) acquires DeriveRefPod, ModuleStore {
     let metadata = fungible_asset::asset_metadata(&fa);
     let store = ensure_primary_store_exists(owner, metadata);
-    fungible_asset::deposit(store, fa);
+    dispatchable_fungible_asset::deposit(store, fa);
 
     // create cosmos side account
     if (!account::exists_at(owner)) {
@@ -602,8 +633,6 @@ Deposit fungible asset fa to the given account's primary store.
 
 
 
-
- ## Function `transfer` @@ -616,25 +645,68 @@ Transfer amount of fungible asset from sender's primary store to re -
-Implementation +##### Implementation
public entry fun transfer<T: key>(
     sender: &signer,
     metadata: Object<T>,
     recipient: address,
-    amount: u64,
+    amount: u64
 ) acquires DeriveRefPod, ModuleStore {
-    let sender_store = ensure_primary_store_exists(signer::address_of(sender), metadata);
+    let sender_store =
+        ensure_primary_store_exists(signer::address_of(sender), metadata);
     let recipient_store = ensure_primary_store_exists(recipient, metadata);
-    fungible_asset::transfer(sender, sender_store, recipient_store, amount);
+    dispatchable_fungible_asset::transfer(
+        sender, sender_store, recipient_store, amount
+    );
+
+    // create cosmos side account
+    if (!account::exists_at(recipient)) {
+        let _acc_num = account::create_account(recipient);
+    };
 }
 
-
+ + +## Function `transfer_assert_minimum_deposit` + +Transfer amount of fungible asset from sender's primary store to receiver's primary store. +Use the minimum deposit assertion api to make sure receipient will receive a minimum amount of fund. + + +
public entry fun transfer_assert_minimum_deposit<T: key>(sender: &signer, metadata: object::Object<T>, recipient: address, amount: u64, expected: u64)
+
+ + + +##### Implementation + + +
public entry fun transfer_assert_minimum_deposit<T: key>(
+    sender: &signer,
+    metadata: Object<T>,
+    recipient: address,
+    amount: u64,
+    expected: u64
+) acquires DeriveRefPod, ModuleStore {
+    let sender_store =
+        ensure_primary_store_exists(signer::address_of(sender), metadata);
+    let recipient_store = ensure_primary_store_exists(recipient, metadata);
+    dispatchable_fungible_asset::transfer_assert_minimum_deposit(
+        sender,
+        sender_store,
+        recipient_store,
+        amount,
+        expected
+    );
+}
+
+ + @@ -648,20 +720,27 @@ Mint to the primary store of owner. -
-Implementation +##### Implementation
public fun mint(mint_ref: &MintRef, owner: address, amount: u64) acquires DeriveRefPod, ModuleStore {
-    let primary_store = ensure_primary_store_exists(owner, fungible_asset::mint_ref_metadata(mint_ref));
+    let primary_store =
+        ensure_primary_store_exists(
+            owner,
+            fungible_asset::mint_ref_metadata(mint_ref)
+        );
+
     fungible_asset::mint_to(mint_ref, primary_store, amount);
+
+    // create cosmos side account
+    if (!account::exists_at(owner)) {
+        let _acc_num = account::create_account(owner);
+    };
 }
 
-
- ## Function `burn` @@ -674,20 +753,21 @@ Burn from the primary store of owner. -
-Implementation +##### Implementation
public fun burn(burn_ref: &BurnRef, owner: address, amount: u64) {
-    let primary_store = primary_store(owner, fungible_asset::burn_ref_metadata(burn_ref));
+    let primary_store =
+        primary_store(
+            owner,
+            fungible_asset::burn_ref_metadata(burn_ref)
+        );
     fungible_asset::burn_from(burn_ref, primary_store, amount);
 }
 
-
- ## Function `set_frozen_flag` @@ -700,20 +780,23 @@ Freeze/Unfreeze the primary store of owner. -
-Implementation +##### Implementation -
public fun set_frozen_flag(transfer_ref: &TransferRef, owner: address, frozen: bool) acquires DeriveRefPod, ModuleStore {
-    let primary_store = ensure_primary_store_exists(owner, fungible_asset::transfer_ref_metadata(transfer_ref));
+
public fun set_frozen_flag(
+    transfer_ref: &TransferRef, owner: address, frozen: bool
+) acquires DeriveRefPod, ModuleStore {
+    let primary_store =
+        ensure_primary_store_exists(
+            owner,
+            fungible_asset::transfer_ref_metadata(transfer_ref)
+        );
     fungible_asset::set_frozen_flag(transfer_ref, primary_store, frozen);
 }
 
-
- ## Function `withdraw_with_ref` @@ -726,20 +809,27 @@ Withdraw from the primary store of owner ignoring frozen flag. -
-Implementation +##### Implementation -
public fun withdraw_with_ref(transfer_ref: &TransferRef, owner: address, amount: u64): FungibleAsset {
-    let from_primary_store = primary_store(owner, fungible_asset::transfer_ref_metadata(transfer_ref));
-    fungible_asset::withdraw_with_ref(transfer_ref, from_primary_store, amount)
+
public fun withdraw_with_ref(
+    transfer_ref: &TransferRef, owner: address, amount: u64
+): FungibleAsset {
+    let from_primary_store =
+        primary_store(
+            owner,
+            fungible_asset::transfer_ref_metadata(transfer_ref)
+        );
+    fungible_asset::withdraw_with_ref(
+        transfer_ref,
+        from_primary_store,
+        amount
+    )
 }
 
-
- ## Function `deposit_with_ref` @@ -752,23 +842,28 @@ Deposit from the primary store of owner ignoring frozen flag. -
-Implementation +##### Implementation -
public fun deposit_with_ref(transfer_ref: &TransferRef, owner: address, fa: FungibleAsset) acquires DeriveRefPod, ModuleStore {
-    let from_primary_store = ensure_primary_store_exists(
-        owner,
-        fungible_asset::transfer_ref_metadata(transfer_ref)
-    );
+
public fun deposit_with_ref(
+    transfer_ref: &TransferRef, owner: address, fa: FungibleAsset
+) acquires DeriveRefPod, ModuleStore {
+    let from_primary_store =
+        ensure_primary_store_exists(
+            owner,
+            fungible_asset::transfer_ref_metadata(transfer_ref)
+        );
     fungible_asset::deposit_with_ref(transfer_ref, from_primary_store, fa);
+
+    // create cosmos side account
+    if (!account::exists_at(owner)) {
+        let _acc_num = account::create_account(owner);
+    };
 }
 
-
- ## Function `transfer_with_ref` @@ -781,8 +876,7 @@ Transfer amount of FA from the primary store of from t -
-Implementation +##### Implementation
public fun transfer_with_ref(
@@ -791,12 +885,26 @@ Transfer amount of FA from the primary store of from t
     to: address,
     amount: u64
 ) acquires DeriveRefPod, ModuleStore {
-    let from_primary_store = primary_store(from, fungible_asset::transfer_ref_metadata(transfer_ref));
-    let to_primary_store = ensure_primary_store_exists(to, fungible_asset::transfer_ref_metadata(transfer_ref));
-    fungible_asset::transfer_with_ref(transfer_ref, from_primary_store, to_primary_store, amount);
+    let from_primary_store =
+        primary_store(
+            from,
+            fungible_asset::transfer_ref_metadata(transfer_ref)
+        );
+    let to_primary_store =
+        ensure_primary_store_exists(
+            to,
+            fungible_asset::transfer_ref_metadata(transfer_ref)
+        );
+    fungible_asset::transfer_with_ref(
+        transfer_ref,
+        from_primary_store,
+        to_primary_store,
+        amount
+    );
+
+    // create cosmos side account
+    if (!account::exists_at(to)) {
+        let _acc_num = account::create_account(to);
+    };
 }
 
- - - -
diff --git a/initia_stdlib/doc/property_map.md b/initia_stdlib/doc/property_map.md index 1ae505e..cb7a15f 100644 --- a/initia_stdlib/doc/property_map.md +++ b/initia_stdlib/doc/property_map.md @@ -15,16 +15,10 @@ represent types and storing values in bcs format. - [Function `init`](#0x1_property_map_init) - [Function `burn`](#0x1_property_map_burn) - [Function `prepare_input`](#0x1_property_map_prepare_input) -- [Function `to_external_type`](#0x1_property_map_to_external_type) -- [Function `to_internal_type`](#0x1_property_map_to_internal_type) -- [Function `type_info_to_internal_type`](#0x1_property_map_type_info_to_internal_type) -- [Function `validate_type`](#0x1_property_map_validate_type) - [Function `generate_mutator_ref`](#0x1_property_map_generate_mutator_ref) - [Function `contains_key`](#0x1_property_map_contains_key) - [Function `length`](#0x1_property_map_length) - [Function `read`](#0x1_property_map_read) -- [Function `assert_exists`](#0x1_property_map_assert_exists) -- [Function `read_typed`](#0x1_property_map_read_typed) - [Function `read_bool`](#0x1_property_map_read_bool) - [Function `read_u8`](#0x1_property_map_read_u8) - [Function `read_u16`](#0x1_property_map_read_u16) @@ -37,10 +31,8 @@ represent types and storing values in bcs format. - [Function `read_string`](#0x1_property_map_read_string) - [Function `add`](#0x1_property_map_add) - [Function `add_typed`](#0x1_property_map_add_typed) -- [Function `add_internal`](#0x1_property_map_add_internal) - [Function `update`](#0x1_property_map_update) - [Function `update_typed`](#0x1_property_map_update_typed) -- [Function `update_internal`](#0x1_property_map_update_internal) - [Function `remove`](#0x1_property_map_remove) @@ -70,8 +62,7 @@ should keep track of what keys are what types, and parse them accordingly. -
-Fields +##### Fields
@@ -84,8 +75,6 @@ should keep track of what keys are what types, and parse them accordingly.
-
- ## Struct `PropertyValue` @@ -98,8 +87,7 @@ A typed value for the - - ## Struct `MutatorRef` @@ -132,8 +118,7 @@ A mutator ref that allows for mutation of the property map -
-Fields +##### Fields
@@ -146,8 +131,6 @@ A mutator ref that allows for mutation of the property map
-
- ## Constants @@ -354,8 +337,7 @@ Maximum number of characters in a property name -
-Implementation +##### Implementation
public fun init(s: &signer, container: PropertyMap) {
@@ -365,8 +347,6 @@ Maximum number of characters in a property name
 
 
 
-
- ## Function `burn` @@ -380,8 +360,7 @@ TODO: hanlde when table is not empty -
-Implementation +##### Implementation
public fun burn(ref: MutatorRef) acquires PropertyMap {
@@ -391,8 +370,6 @@ TODO: hanlde when table is not empty
 
 
 
-
- ## Function `prepare_input` @@ -405,26 +382,34 @@ Helper for external entry functions to produce a valid container for property va -
-Implementation +##### Implementation
public fun prepare_input(
     keys: vector<String>,
     types: vector<String>,
-    values: vector<vector<u8>>,
+    values: vector<vector<u8>>
 ): PropertyMap {
     let length = vector::length(&keys);
-    assert!(length <= MAX_PROPERTY_MAP_SIZE, error::invalid_argument(ETOO_MANY_PROPERTIES));
-    assert!(length == vector::length(&values), error::invalid_argument(EKEY_VALUE_COUNT_MISMATCH));
-    assert!(length == vector::length(&types), error::invalid_argument(EKEY_TYPE_COUNT_MISMATCH));
+    assert!(
+        length <= MAX_PROPERTY_MAP_SIZE,
+        error::invalid_argument(ETOO_MANY_PROPERTIES)
+    );
+    assert!(
+        length == vector::length(&values),
+        error::invalid_argument(EKEY_VALUE_COUNT_MISMATCH)
+    );
+    assert!(
+        length == vector::length(&types),
+        error::invalid_argument(EKEY_TYPE_COUNT_MISMATCH)
+    );
 
     let container = simple_map::create<String, PropertyValue>();
     while (!vector::is_empty(&keys)) {
         let key = vector::pop_back(&mut keys);
         assert!(
             string::length(&key) <= MAX_PROPERTY_NAME_LENGTH,
-            error::invalid_argument(EPROPERTY_MAP_KEY_TOO_LONG),
+            error::invalid_argument(EPROPERTY_MAP_KEY_TOO_LONG)
         );
 
         let value = vector::pop_back(&mut values);
@@ -433,7 +418,11 @@ Helper for external entry functions to produce a valid container for property va
         let new_type = to_internal_type(type);
         validate_type(new_type, value);
 
-        simple_map::add(&mut container, key, PropertyValue { value, type: new_type });
+        simple_map::add(
+            &mut container,
+            key,
+            PropertyValue { value, type: new_type }
+        );
     };
 
     PropertyMap { inner: container }
@@ -442,175 +431,6 @@ Helper for external entry functions to produce a valid container for property va
 
 
 
-
- - - -## Function `to_external_type` - -Maps String representation of types from their u8 representation - - -
fun to_external_type(type: u8): string::String
-
- - - -
-Implementation - - -
inline fun to_external_type(type: u8): String {
-    if (type == BOOL) {
-        string::utf8(b"bool")
-    } else if (type == U8) {
-        string::utf8(b"u8")
-    } else if (type == U16) {
-        string::utf8(b"u16")
-    } else if (type == U32) {
-        string::utf8(b"u32")
-    } else if (type == U64) {
-        string::utf8(b"u64")
-    } else if (type == U128) {
-        string::utf8(b"u128")
-    } else if (type == U256) {
-        string::utf8(b"u256")
-    } else if (type == ADDRESS) {
-        string::utf8(b"address")
-    } else if (type == BYTE_VECTOR) {
-        string::utf8(b"vector<u8>")
-    } else if (type == STRING) {
-        string::utf8(b"0x1::string::String")
-    } else {
-        abort (error::invalid_argument(ETYPE_INVALID))
-    }
-}
-
- - - -
- - - -## Function `to_internal_type` - -Maps the String representation of types to u8 - - -
fun to_internal_type(type: string::String): u8
-
- - - -
-Implementation - - -
inline fun to_internal_type(type: String): u8 {
-    if (type == string::utf8(b"bool")) {
-        BOOL
-    } else if (type == string::utf8(b"u8")) {
-        U8
-    } else if (type == string::utf8(b"u16")) {
-        U16
-    } else if (type == string::utf8(b"u32")) {
-        U32
-    } else if (type == string::utf8(b"u64")) {
-        U64
-    } else if (type == string::utf8(b"u128")) {
-        U128
-    } else if (type == string::utf8(b"u256")) {
-        U256
-    } else if (type == string::utf8(b"address")) {
-        ADDRESS
-    } else if (type == string::utf8(b"vector<u8>")) {
-        BYTE_VECTOR
-    } else if (type == string::utf8(b"0x1::string::String")) {
-        STRING
-    } else {
-        abort (error::invalid_argument(ETYPE_INVALID))
-    }
-}
-
- - - -
- - - -## Function `type_info_to_internal_type` - -Maps Move type to u8 representation - - -
fun type_info_to_internal_type<T>(): u8
-
- - - -
-Implementation - - -
inline fun type_info_to_internal_type<T>(): u8 {
-    let type = type_info::type_name<T>();
-    to_internal_type(type)
-}
-
- - - -
- - - -## Function `validate_type` - -Validates property value type against its expected type - - -
fun validate_type(type: u8, value: vector<u8>)
-
- - - -
-Implementation - - -
inline fun validate_type(type: u8, value: vector<u8>) {
-    if (type == BOOL) {
-        from_bcs::to_bool(value);
-    } else if (type == U8) {
-        from_bcs::to_u8(value);
-    } else if (type == U16) {
-        from_bcs::to_u16(value);
-    } else if (type == U32) {
-        from_bcs::to_u32(value);
-    } else if (type == U64) {
-        from_bcs::to_u64(value);
-    } else if (type == U128) {
-        from_bcs::to_u128(value);
-    } else if (type == U256) {
-        from_bcs::to_u256(value);
-    } else if (type == ADDRESS) {
-        from_bcs::to_address(value);
-    } else if (type == BYTE_VECTOR) {
-        // nothing to validate...
-    } else if (type == STRING) {
-        from_bcs::to_string(value);
-    } else {
-        abort (error::invalid_argument(ETYPE_MISMATCH))
-    };
-}
-
- - - -
- ## Function `generate_mutator_ref` @@ -622,8 +442,7 @@ Validates property value type against its expected type -
-Implementation +##### Implementation
public fun generate_mutator_ref(s: &signer): MutatorRef {
@@ -633,8 +452,6 @@ Validates property value type against its expected type
 
 
 
-
- ## Function `contains_key` @@ -646,21 +463,18 @@ Validates property value type against its expected type -
-Implementation +##### Implementation
public fun contains_key<T: key>(object: Object<T>, key: &String): bool acquires PropertyMap {
-    assert_exists(object::object_address(object));
-    let property_map = borrow_global<PropertyMap>(object::object_address(object));
+    assert_exists(object::object_address(&object));
+    let property_map = borrow_global<PropertyMap>(object::object_address(&object));
     simple_map::contains_key(&property_map.inner, key)
 }
 
-
- ## Function `length` @@ -672,21 +486,18 @@ Validates property value type against its expected type -
-Implementation +##### Implementation
public fun length<T: key>(object: Object<T>): u64 acquires PropertyMap {
-    assert_exists(object::object_address(object));
-    let property_map = borrow_global<PropertyMap>(object::object_address(object));
+    assert_exists(object::object_address(&object));
+    let property_map = borrow_global<PropertyMap>(object::object_address(&object));
     simple_map::length(&property_map.inner)
 }
 
-
- ## Function `read` @@ -701,13 +512,12 @@ The preferred method is to use read_<type> where the type is -
-Implementation +##### Implementation
public fun read<T: key>(object: Object<T>, key: &String): (String, vector<u8>) acquires PropertyMap {
-    assert_exists(object::object_address(object));
-    let property_map = borrow_global<PropertyMap>(object::object_address(object));
+    assert_exists(object::object_address(&object));
+    let property_map = borrow_global<PropertyMap>(object::object_address(&object));
     let property_value = simple_map::borrow(&property_map.inner, key);
     let new_type = to_external_type(property_value.type);
     (new_type, property_value.value)
@@ -716,65 +526,6 @@ The preferred method is to use read_<type> where the type is
 
 
 
-
- - - -## Function `assert_exists` - - - -
fun assert_exists(object: address)
-
- - - -
-Implementation - - -
inline fun assert_exists(object: address) {
-    assert!(
-        exists<PropertyMap>(object),
-        error::not_found(EPROPERTY_MAP_DOES_NOT_EXIST),
-    );
-}
-
- - - -
- - - -## Function `read_typed` - -Read a type and verify that the type is correct - - -
fun read_typed<T: key, V>(object: object::Object<T>, key: &string::String): vector<u8>
-
- - - -
-Implementation - - -
inline fun read_typed<T: key, V>(object: Object<T>, key: &String): vector<u8> acquires PropertyMap {
-    let (type, value) = read(object, key);
-    assert!(
-        type == type_info::type_name<V>(),
-        error::invalid_argument(ETYPE_MISMATCH),
-    );
-    value
-}
-
- - - -
- ## Function `read_bool` @@ -786,8 +537,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_bool<T: key>(object: Object<T>, key: &String): bool acquires PropertyMap {
@@ -798,8 +548,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_u8` @@ -811,8 +559,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_u8<T: key>(object: Object<T>, key: &String): u8 acquires PropertyMap {
@@ -823,8 +570,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_u16` @@ -836,8 +581,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_u16<T: key>(object: Object<T>, key: &String): u16 acquires PropertyMap {
@@ -848,8 +592,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_u32` @@ -861,8 +603,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_u32<T: key>(object: Object<T>, key: &String): u32 acquires PropertyMap {
@@ -873,8 +614,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_u64` @@ -886,8 +625,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_u64<T: key>(object: Object<T>, key: &String): u64 acquires PropertyMap {
@@ -898,8 +636,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_u128` @@ -911,8 +647,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_u128<T: key>(object: Object<T>, key: &String): u128 acquires PropertyMap {
@@ -923,8 +658,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_u256` @@ -936,8 +669,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_u256<T: key>(object: Object<T>, key: &String): u256 acquires PropertyMap {
@@ -948,8 +680,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_address` @@ -961,8 +691,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_address<T: key>(object: Object<T>, key: &String): address acquires PropertyMap {
@@ -973,8 +702,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_bytes` @@ -986,8 +713,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_bytes<T: key>(object: Object<T>, key: &String): vector<u8> acquires PropertyMap {
@@ -998,8 +724,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_string` @@ -1011,8 +735,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_string<T: key>(object: Object<T>, key: &String): String acquires PropertyMap {
@@ -1023,8 +746,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `add` @@ -1037,11 +758,15 @@ Add a property, already bcs encoded as a add(ref: &MutatorRef, key: String, type: String, value: vector<u8>) acquires PropertyMap { +
public fun add(
+    ref: &MutatorRef,
+    key: String,
+    type: String,
+    value: vector<u8>
+) acquires PropertyMap {
     let new_type = to_internal_type(type);
     validate_type(new_type, value);
     add_internal(ref, key, new_type, value);
@@ -1050,8 +775,6 @@ Add a property, already bcs encoded as a 
 
 ## Function `add_typed`
@@ -1064,8 +787,7 @@ Add a property that isn't already encoded as a add_typed<T: drop>(ref: &MutatorRef, key: String, value: T) acquires PropertyMap {
@@ -1076,34 +798,6 @@ Add a property that isn't already encoded as a 
-
-## Function `add_internal`
-
-
-
-
fun add_internal(ref: &property_map::MutatorRef, key: string::String, type: u8, value: vector<u8>)
-
- - - -
-Implementation - - -
inline fun add_internal(ref: &MutatorRef, key: String, type: u8, value: vector<u8>) acquires PropertyMap {
-    assert_exists(ref.self);
-    let property_map = borrow_global_mut<PropertyMap>(ref.self);
-    simple_map::add(&mut property_map.inner, key, PropertyValue { type, value });
-}
-
- - - -
- ## Function `update` @@ -1116,11 +810,15 @@ Updates a property in place already bcs encoded -
-Implementation +##### Implementation -
public fun update(ref: &MutatorRef, key: &String, type: String, value: vector<u8>) acquires PropertyMap {
+
public fun update(
+    ref: &MutatorRef,
+    key: &String,
+    type: String,
+    value: vector<u8>
+) acquires PropertyMap {
     let new_type = to_internal_type(type);
     validate_type(new_type, value);
     update_internal(ref, key, new_type, value);
@@ -1129,8 +827,6 @@ Updates a property in place already bcs encoded
 
 
 
-
- ## Function `update_typed` @@ -1143,11 +839,12 @@ Updates a property in place that is not already bcs encoded -
-Implementation +##### Implementation -
public fun update_typed<T: drop>(ref: &MutatorRef, key: &String, value: T) acquires PropertyMap {
+
public fun update_typed<T: drop>(
+    ref: &MutatorRef, key: &String, value: T
+) acquires PropertyMap {
     let type = type_info_to_internal_type<T>();
     update_internal(ref, key, type, bcs::to_bytes(&value));
 }
@@ -1155,35 +852,6 @@ Updates a property in place that is not already bcs encoded
 
 
 
-
- - - -## Function `update_internal` - - - -
fun update_internal(ref: &property_map::MutatorRef, key: &string::String, type: u8, value: vector<u8>)
-
- - - -
-Implementation - - -
inline fun update_internal(ref: &MutatorRef, key: &String, type: u8, value: vector<u8>) acquires PropertyMap {
-    assert_exists(ref.self);
-    let property_map = borrow_global_mut<PropertyMap>(ref.self);
-    let old_value = simple_map::borrow_mut(&mut property_map.inner, key);
-    *old_value = PropertyValue { type, value };
-}
-
- - - -
- ## Function `remove` @@ -1196,8 +864,7 @@ Removes a property from the map, ensuring that it does in fact exist -
-Implementation +##### Implementation
public fun remove(ref: &MutatorRef, key: &String) acquires PropertyMap {
@@ -1206,7 +873,3 @@ Removes a property from the map, ensuring that it does in fact exist
     simple_map::remove(&mut property_map.inner, key);
 }
 
- - - -
diff --git a/initia_stdlib/doc/query.md b/initia_stdlib/doc/query.md index c040ef4..31fb327 100644 --- a/initia_stdlib/doc/query.md +++ b/initia_stdlib/doc/query.md @@ -5,6 +5,8 @@ +- [Struct `ProposalRequest`](#0x1_query_ProposalRequest) +- [Struct `ProposalResponse`](#0x1_query_ProposalResponse) - [Function `get_proposal`](#0x1_query_get_proposal) - [Function `get_proposal_status`](#0x1_query_get_proposal_status) - [Function `query_custom`](#0x1_query_query_custom) @@ -12,13 +14,89 @@
use 0x1::json;
-use 0x1::option;
-use 0x1::simple_json;
 use 0x1::string;
 
+ + +## Struct `ProposalRequest` + + + +
struct ProposalRequest has copy, drop
+
+ + + +##### Fields + + +
+
+proposal_id: u64 +
+
+ +
+
+ + + + +## Struct `ProposalResponse` + + + +
struct ProposalResponse has copy, drop
+
+ + + +##### Fields + + +
+
+id: u64 +
+
+ +
+
+title: string::String +
+
+ +
+
+summary: string::String +
+
+ +
+
+status: string::String +
+
+ +
+
+submit_time: string::String +
+
+ +
+
+emergency: bool +
+
+ +
+
+ + ## Function `get_proposal` @@ -31,40 +109,22 @@ -
-Implementation +##### Implementation
public fun get_proposal(proposal_id: u64): (u64, String, String, String) {
-    let obj = json::empty();
-    let index = json::start_index();
-    json::set_object(&mut obj, index, option::none<String>(), 1);
-    json::set_int_raw(&mut obj, json::get_next_index(&index, 0), option::some(string::utf8(b"proposal_id")), true, (proposal_id as u256));
-
-    let req = json::stringify(&obj);
-    let response = query_stargate(b"/initia.gov.v1.Query/Proposal", *string::bytes(&req));
-    let res = json::parse(string::utf8(response));
-    let index = json::get_next_index(&index, 0);
-
-    let cindex = json::find(&res, &index, &string::utf8(b"id"));
-    let (_, data) = json::unpack_elem(json::borrow(&res, &cindex));
-    let (_, id) = json::as_int(data);
-
-    let cindex = json::find(&res, &index, &string::utf8(b"title"));
-    let (_, data) = json::unpack_elem(json::borrow(&res, &cindex));
-    let title = json::as_string(data);
-
-    let cindex = json::find(&res, &index, &string::utf8(b"summary"));
-    let (_, data) = json::unpack_elem(json::borrow(&res, &cindex));
-    let summary = json::as_string(data);
-    ((id as u64), title, summary, string::utf8(response))
+    let response =
+        query_stargate(
+            b"/initia.gov.v1.Query/Proposal",
+            json::marshal(&ProposalRequest { proposal_id })
+        );
+    let res = json::unmarshal<ProposalResponse>(response);
+    (res.id, res.title, res.summary, string::utf8(response))
 }
 
-
- ## Function `get_proposal_status` @@ -77,45 +137,22 @@ -
-Implementation +##### Implementation
public fun get_proposal_status(proposal_id: u64): (u64, String, String, bool) {
-    let obj = simple_json::empty();
-    simple_json::set_object(&mut obj, option::none<String>());
-    simple_json::increase_depth(&mut obj);
-    simple_json::set_int_raw(&mut obj, option::some(string::utf8(b"proposal_id")), true, (proposal_id as u256));
-
-    let req = json::stringify(simple_json::to_json_object(&obj));
-    let res = query_stargate(b"/initia.gov.v1.Query/Proposal", *string::bytes(&req));
-    let res = simple_json::from_json_object(json::parse(string::utf8(res)));
-    simple_json::increase_depth(&mut res);
-    simple_json::increase_depth(&mut res);
-
-    simple_json::find_and_set_index(&mut res, &string::utf8(b"id"));
-    let (_, data) = json::unpack_elem(simple_json::borrow(&mut res));
-    let (_, id) = json::as_int(data);
-
-    simple_json::find_and_set_index(&mut res, &string::utf8(b"status"));
-    let (_, data) = json::unpack_elem(simple_json::borrow(&mut res));
-    let status = json::as_string(data);
-
-    simple_json::find_and_set_index(&mut res, &string::utf8(b"submit_time"));
-    let (_, data) = json::unpack_elem(simple_json::borrow(&mut res));
-    let submit_time = json::as_string(data);
-
-    simple_json::find_and_set_index(&mut res, &string::utf8(b"emergency"));
-    let (_, data) = json::unpack_elem(simple_json::borrow(&mut res));
-    let emergency = json::as_bool(data);
-    ((id as u64), status, submit_time, emergency)
+    let response =
+        query_stargate(
+            b"/initia.gov.v1.Query/Proposal",
+            json::marshal(&ProposalRequest { proposal_id })
+        );
+    let res = json::unmarshal<ProposalResponse>(response);
+    (res.id, res.status, res.submit_time, res.emergency)
 }
 
-
- ## Function `query_custom` @@ -128,8 +165,7 @@ query_custom examples are in initia_stdlib::address module -
-Implementation +##### Implementation
native public fun query_custom(name: vector<u8>, data: vector<u8>): vector<u8>;
@@ -137,8 +173,6 @@ query_custom examples are in initia_stdlib::address module
 
 
 
-
- ## Function `query_stargate` @@ -150,13 +184,8 @@ query_custom examples are in initia_stdlib::address module -
-Implementation +##### Implementation
native public fun query_stargate(path: vector<u8>, data: vector<u8>): vector<u8>;
 
- - - -
diff --git a/initia_stdlib/doc/reward.md b/initia_stdlib/doc/reward.md deleted file mode 100644 index 4b04f54..0000000 --- a/initia_stdlib/doc/reward.md +++ /dev/null @@ -1,412 +0,0 @@ - - - -# Module `0x1::vip_reward` - - - -- [Resource `RewardStore`](#0x1_vip_reward_RewardStore) -- [Constants](#@Constants_0) -- [Function `reward_metadata`](#0x1_vip_reward_reward_metadata) -- [Function `generate_reward_store_seed`](#0x1_vip_reward_generate_reward_store_seed) -- [Function `create_reward_store_address`](#0x1_vip_reward_create_reward_store_address) -- [Function `register_reward_store`](#0x1_vip_reward_register_reward_store) -- [Function `add_reward_per_stage`](#0x1_vip_reward_add_reward_per_stage) -- [Function `withdraw`](#0x1_vip_reward_withdraw) -- [Function `balance`](#0x1_vip_reward_balance) -- [Function `get_stage_reward`](#0x1_vip_reward_get_stage_reward) -- [Function `is_reward_store_registered`](#0x1_vip_reward_is_reward_store_registered) -- [Function `get_reward_store_address`](#0x1_vip_reward_get_reward_store_address) - - -
use 0x1::bcs;
-use 0x1::coin;
-use 0x1::error;
-use 0x1::fungible_asset;
-use 0x1::object;
-use 0x1::primary_fungible_store;
-use 0x1::signer;
-use 0x1::string;
-use 0x1::table;
-use 0x1::table_key;
-use 0x1::type_info;
-use 0x1::vector;
-
- - - - - -## Resource `RewardStore` - - - -
struct RewardStore has key
-
- - - -
-Fields - - -
-
-extend_ref: object::ExtendRef -
-
- -
-
-reward_store: object::Object<fungible_asset::FungibleStore> -
-
- -
-
-reward_per_stage: table::Table<vector<u8>, u64> -
-
- -
-
- - -
- - - -## Constants - - - - - - -
const REWARD_SYMBOL: vector<u8> = [117, 105, 110, 105, 116];
-
- - - - - - - -
const EREWARD_STORE_ALREADY_EXISTS: u64 = 1;
-
- - - - - - - -
const EREWARD_STORE_NOT_FOUND: u64 = 2;
-
- - - - - - - -
const OPERATOR_REWARD_PREFIX: u8 = 242;
-
- - - - - - - -
const USER_REWARD_PREFIX: u8 = 243;
-
- - - - - -## Function `reward_metadata` - - - -
public fun reward_metadata(): object::Object<fungible_asset::Metadata>
-
- - - -
-Implementation - - -
public fun reward_metadata(): Object<Metadata> {
-    coin::metadata(@initia_std, string::utf8(REWARD_SYMBOL))
-}
-
- - - -
- - - -## Function `generate_reward_store_seed` - - - -
fun generate_reward_store_seed<Vesting: copy, drop, store>(bridge_id: u64): vector<u8>
-
- - - -
-Implementation - - -
fun generate_reward_store_seed<Vesting: copy + drop + store>(bridge_id: u64): vector<u8>{
-    let seed = if (type_info::type_name<Vesting>() == string::utf8(b"0x1::vip_vesting::OperatorVesting")) {
-        vector[OPERATOR_REWARD_PREFIX]
-    } else {
-        vector[USER_REWARD_PREFIX]
-    };
-
-    vector::append(&mut seed, bcs::to_bytes(&bridge_id));
-    return seed
-}
-
- - - -
- - - -## Function `create_reward_store_address` - - - -
fun create_reward_store_address<Vesting: copy, drop, store>(bridge_id: u64): address
-
- - - -
-Implementation - - -
fun create_reward_store_address<Vesting: copy + drop + store>(bridge_id: u64): address {
-    let seed = generate_reward_store_seed<Vesting>(bridge_id);
-    object::create_object_address(@initia_std, seed)
-}
-
- - - -
- - - -## Function `register_reward_store` - - - -
public(friend) fun register_reward_store<Vesting: copy, drop, store>(chain: &signer, bridge_id: u64)
-
- - - -
-Implementation - - -
public(friend) fun register_reward_store<Vesting: copy + drop + store>(
-    chain: &signer,
-    bridge_id: u64,
-) {
-    let seed = generate_reward_store_seed<Vesting>(bridge_id);
-    let reward_store_addr = object::create_object_address(signer::address_of(chain), seed);
-    assert!(!exists<RewardStore>(reward_store_addr), error::already_exists(EREWARD_STORE_ALREADY_EXISTS));
-
-    let constructor_ref = object::create_named_object(chain, seed, false);
-    let object = object::generate_signer(&constructor_ref);
-    let extend_ref = object::generate_extend_ref(&constructor_ref);
-    let reward_store = primary_fungible_store::ensure_primary_store_exists(reward_store_addr, reward_metadata());
-
-    move_to(
-        &object, RewardStore {
-            extend_ref,
-            reward_store,
-            reward_per_stage: table::new<vector<u8>, u64>(),
-        }
-    );
-}
-
- - - -
- - - -## Function `add_reward_per_stage` - - - -
public(friend) fun add_reward_per_stage(reward_store_addr: address, stage: u64, reward: u64)
-
- - - -
-Implementation - - -
public(friend) fun add_reward_per_stage(
-    reward_store_addr: address,
-    stage: u64,
-    reward: u64
-) acquires RewardStore {
-    let reward_store = borrow_global_mut<RewardStore>(reward_store_addr);
-    let stage_reward = table::borrow_mut_with_default(&mut reward_store.reward_per_stage, table_key::encode_u64(stage), 0);
-    *stage_reward = *stage_reward + reward;
-}
-
- - - -
- - - -## Function `withdraw` - - - -
public(friend) fun withdraw(reward_store_addr: address, amount: u64): fungible_asset::FungibleAsset
-
- - - -
-Implementation - - -
public(friend) fun withdraw(
-    reward_store_addr: address,
-    amount: u64,
-): FungibleAsset acquires RewardStore {
-    let reward_store = borrow_global<RewardStore>(reward_store_addr);
-    let reward_signer = object::generate_signer_for_extending(&reward_store.extend_ref);
-
-    fungible_asset::withdraw(&reward_signer, reward_store.reward_store, amount)
-}
-
- - - -
- - - -## Function `balance` - - - -
#[view]
-public fun balance(reward_store_addr: address): u64
-
- - - -
-Implementation - - -
public fun balance(reward_store_addr: address): u64 {
-    primary_fungible_store::balance(reward_store_addr, reward_metadata())
-}
-
- - - -
- - - -## Function `get_stage_reward` - - - -
#[view]
-public fun get_stage_reward(reward_store_addr: address, stage: u64): u64
-
- - - -
-Implementation - - -
public fun get_stage_reward(reward_store_addr: address, stage: u64): u64 acquires RewardStore {
-    let reward_store = borrow_global<RewardStore>(reward_store_addr);
-
-    let stage_reward = table::borrow_with_default(&reward_store.reward_per_stage, table_key::encode_u64(stage), &0);
-    *stage_reward
-}
-
- - - -
- - - -## Function `is_reward_store_registered` - - - -
#[view]
-public fun is_reward_store_registered<Vesting: copy, drop, store>(bridge_id: u64): bool
-
- - - -
-Implementation - - -
public fun is_reward_store_registered<Vesting: copy + drop + store>(bridge_id: u64): bool {
-    exists<RewardStore>(create_reward_store_address<Vesting>(bridge_id))
-}
-
- - - -
- - - -## Function `get_reward_store_address` - - - -
#[view]
-public fun get_reward_store_address<Vesting: copy, drop, store>(bridge_id: u64): address
-
- - - -
-Implementation - - -
public fun get_reward_store_address<Vesting: copy + drop + store>(bridge_id: u64): address {
-    let reward_addr = create_reward_store_address<Vesting>(bridge_id);
-    assert!(exists<RewardStore>(reward_addr), error::not_found(EREWARD_STORE_NOT_FOUND));
-    reward_addr
-}
-
- - - -
diff --git a/initia_stdlib/doc/royalty.md b/initia_stdlib/doc/royalty.md index a86eb49..d9776a3 100644 --- a/initia_stdlib/doc/royalty.md +++ b/initia_stdlib/doc/royalty.md @@ -22,7 +22,7 @@ royalty. - [Function `payee_address`](#0x1_royalty_payee_address) -
use 0x1::decimal128;
+
use 0x1::bigdecimal;
 use 0x1::error;
 use 0x1::object;
 use 0x1::option;
@@ -44,13 +44,12 @@ Royalties are optional for a collection.
 
 
 
-
-Fields +##### Fields
-royalty: decimal128::Decimal128 +royalty: bigdecimal::BigDecimal
@@ -64,8 +63,6 @@ Royalties are optional for a collection.
-
- ## Struct `MutatorRef` @@ -78,8 +75,7 @@ This enables creating or overwriting a - - ## Constants @@ -141,8 +135,7 @@ Add a royalty, given a ConstructorRef. -
-Implementation +##### Implementation
public fun init(ref: &ConstructorRef, royalty: Royalty) {
@@ -153,8 +146,6 @@ Add a royalty, given a ConstructorRef.
 
 
 
-
- ## Function `update` @@ -167,8 +158,7 @@ Set the royalty if it does not exist, replace it otherwise. -
-Implementation +##### Implementation
public fun update(mutator_ref: &MutatorRef, royalty: Royalty) acquires Royalty {
@@ -184,8 +174,6 @@ Set the royalty if it does not exist, replace it otherwise.
 
 
 
-
- ## Function `create` @@ -193,17 +181,19 @@ Set the royalty if it does not exist, replace it otherwise. Creates a new royalty, verifying that it is a valid percentage -
public fun create(royalty: decimal128::Decimal128, payee_address: address): royalty::Royalty
+
public fun create(royalty: bigdecimal::BigDecimal, payee_address: address): royalty::Royalty
 
-
-Implementation +##### Implementation -
public fun create(royalty: Decimal128, payee_address: address): Royalty {
-    assert!(decimal128::val(&royalty) <= decimal128::val(&decimal128::one()), error::out_of_range(EROYALTY_EXCEEDS_MAXIMUM));
+
public fun create(royalty: BigDecimal, payee_address: address): Royalty {
+    assert!(
+        bigdecimal::le(royalty, bigdecimal::one()),
+        error::out_of_range(EROYALTY_EXCEEDS_MAXIMUM)
+    );
 
     Royalty { royalty, payee_address }
 }
@@ -211,8 +201,6 @@ Creates a new royalty, verifying that it is a valid percentage
 
 
 
-
- ## Function `generate_mutator_ref` @@ -224,8 +212,7 @@ Creates a new royalty, verifying that it is a valid percentage -
-Implementation +##### Implementation
public fun generate_mutator_ref(ref: ExtendRef): MutatorRef {
@@ -235,8 +222,6 @@ Creates a new royalty, verifying that it is a valid percentage
 
 
 
-
- ## Function `exists_at` @@ -248,8 +233,7 @@ Creates a new royalty, verifying that it is a valid percentage -
-Implementation +##### Implementation
public fun exists_at(addr: address): bool {
@@ -259,8 +243,6 @@ Creates a new royalty, verifying that it is a valid percentage
 
 
 
-
- ## Function `delete` @@ -272,20 +254,20 @@ Creates a new royalty, verifying that it is a valid percentage -
-Implementation +##### Implementation
public(friend) fun delete(addr: address) acquires Royalty {
-    assert!(exists<Royalty>(addr), error::not_found(EROYALTY_DOES_NOT_EXIST));
+    assert!(
+        exists<Royalty>(addr),
+        error::not_found(EROYALTY_DOES_NOT_EXIST)
+    );
     move_from<Royalty>(addr);
 }
 
-
- ## Function `get` @@ -297,12 +279,11 @@ Creates a new royalty, verifying that it is a valid percentage -
-Implementation +##### Implementation
public fun get<T: key>(maybe_royalty: Object<T>): Option<Royalty> acquires Royalty {
-    let obj_addr = object::object_address(maybe_royalty);
+    let obj_addr = object::object_address(&maybe_royalty);
     if (exists<Royalty>(obj_addr)) {
         option::some(*borrow_global<Royalty>(obj_addr))
     } else {
@@ -313,32 +294,27 @@ Creates a new royalty, verifying that it is a valid percentage
 
 
 
-
- ## Function `royalty` -
public fun royalty(royalty: &royalty::Royalty): decimal128::Decimal128
+
public fun royalty(royalty: &royalty::Royalty): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation -
public fun royalty(royalty: &Royalty): Decimal128 {
+
public fun royalty(royalty: &Royalty): BigDecimal {
     royalty.royalty
 }
 
-
- ## Function `payee_address` @@ -350,15 +326,10 @@ Creates a new royalty, verifying that it is a valid percentage -
-Implementation +##### Implementation
public fun payee_address(royalty: &Royalty): address {
     royalty.payee_address
 }
 
- - - -
diff --git a/initia_stdlib/doc/secp256k1.md b/initia_stdlib/doc/secp256k1.md index e64227d..d66c72a 100644 --- a/initia_stdlib/doc/secp256k1.md +++ b/initia_stdlib/doc/secp256k1.md @@ -6,17 +6,19 @@ This module implements ECDSA signatures based on the prime-order secp256k1 ellptic curve (i.e., cofactor is 1). -- [Struct `PublicKey`](#0x1_secp256k1_PublicKey) -- [Struct `Signature`](#0x1_secp256k1_Signature) +- [Struct `ECDSARawPublicKey`](#0x1_secp256k1_ECDSARawPublicKey) +- [Struct `ECDSACompressedPublicKey`](#0x1_secp256k1_ECDSACompressedPublicKey) +- [Struct `ECDSASignature`](#0x1_secp256k1_ECDSASignature) - [Constants](#@Constants_0) -- [Function `public_key_from_bytes`](#0x1_secp256k1_public_key_from_bytes) -- [Function `signature_from_bytes`](#0x1_secp256k1_signature_from_bytes) -- [Function `public_key_to_bytes`](#0x1_secp256k1_public_key_to_bytes) -- [Function `signature_to_bytes`](#0x1_secp256k1_signature_to_bytes) -- [Function `verify`](#0x1_secp256k1_verify) -- [Function `recover_public_key`](#0x1_secp256k1_recover_public_key) -- [Function `verify_internal`](#0x1_secp256k1_verify_internal) -- [Function `recover_public_key_internal`](#0x1_secp256k1_recover_public_key_internal) +- [Function `ecdsa_signature_from_bytes`](#0x1_secp256k1_ecdsa_signature_from_bytes) +- [Function `ecdsa_raw_public_key_from_64_bytes`](#0x1_secp256k1_ecdsa_raw_public_key_from_64_bytes) +- [Function `ecdsa_raw_public_key_from_bytes`](#0x1_secp256k1_ecdsa_raw_public_key_from_bytes) +- [Function `ecdsa_compressed_public_key_from_bytes`](#0x1_secp256k1_ecdsa_compressed_public_key_from_bytes) +- [Function `ecdsa_raw_public_key_to_bytes`](#0x1_secp256k1_ecdsa_raw_public_key_to_bytes) +- [Function `ecdsa_compressed_public_key_to_bytes`](#0x1_secp256k1_ecdsa_compressed_public_key_to_bytes) +- [Function `ecdsa_signature_to_bytes`](#0x1_secp256k1_ecdsa_signature_to_bytes) +- [Function `ecdsa_recover`](#0x1_secp256k1_ecdsa_recover) +- [Function `ecdsa_recover_compressed`](#0x1_secp256k1_ecdsa_recover_compressed)
use 0x1::error;
@@ -25,21 +27,19 @@ This module implements ECDSA signatures based on the prime-order secp256k1 ellpt
 
 
 
-
+
 
-## Struct `PublicKey`
+## Struct `ECDSARawPublicKey`
 
-A secp256k1-based ECDSA public key.
-It can be raw or compressed public key.
+A 64-byte ECDSA public key.
 
 
-
struct PublicKey has copy, drop, store
+
struct ECDSARawPublicKey has copy, drop, store
 
-
-Fields +##### Fields
@@ -52,22 +52,19 @@ It can be raw or compressed public key.
-
+ - +## Struct `ECDSACompressedPublicKey` -## Struct `Signature` +A 33-byte ECDSA public key. -A secp256k1-based ECDSA signature. - -
struct Signature has copy, drop, store
+
struct ECDSACompressedPublicKey has copy, drop, store
 
-
-Fields +##### Fields
@@ -80,308 +77,339 @@ A secp256k1-based ECDSA signature.
-
+ - +## Struct `ECDSASignature` -## Constants +A 64-byte ECDSA signature. - +
struct ECDSASignature has copy, drop, store
+
-Wrong number of bytes were given as pubkey. -
const E_WRONG_PUBKEY_SIZE: u64 = 1;
-
+##### Fields +
+
+bytes: vector<u8> +
+
- +
+
-Wrong number of bytes were given as signature. + + +## Constants + + + + +The size of a secp256k1-based ECDSA compressed public key, in bytes. -
const E_WRONG_SIGNATURE_SIZE: u64 = 2;
+
+
const COMPRESSED_PUBLIC_KEY_SIZE: u64 = 33;
 
- + -The size of a secp256k1-based ECDSA compressed-public key, in bytes. +An error occurred while deserializing, for example due to wrong input size. -
const PUBLIC_KEY_SIZE: u64 = 33;
+
const E_DESERIALIZE: u64 = 1;
 
- + -The size of a secp256k1-based ECDSA signature, in bytes. +The size of a hashed message for secp256k1-based ECDSA signing -
const SIGNATURE_SIZE: u64 = 64;
+
const MESSAGE_SIZE: u64 = 32;
 
- + -Wrong number of bytes were given as message. +The size of a secp256k1-based ECDSA public key, in bytes. -
const E_WRONG_MESSAGE_SIZE: u64 = 2;
+
const RAW_PUBLIC_KEY_NUM_BYTES: u64 = 64;
 
- + -The size of a hashed message for secp256k1-based ECDSA signing +The size of a secp256k1-based ECDSA signature, in bytes. -
const MESSAGE_SIZE: u64 = 32;
+
const SIGNATURE_NUM_BYTES: u64 = 64;
 
- + -## Function `public_key_from_bytes` +## Function `ecdsa_signature_from_bytes` -Constructs an PublicKey struct, given 33-byte representation. +Constructs an ECDSASignature struct from the given 64 bytes. -
public fun public_key_from_bytes(bytes: vector<u8>): secp256k1::PublicKey
+
public fun ecdsa_signature_from_bytes(bytes: vector<u8>): secp256k1::ECDSASignature
 
-
-Implementation +##### Implementation -
public fun public_key_from_bytes(bytes: vector<u8>): PublicKey {
+
public fun ecdsa_signature_from_bytes(bytes: vector<u8>): ECDSASignature {
     assert!(
-        std::vector::length(&bytes) == PUBLIC_KEY_SIZE,
-        std::error::invalid_argument(PUBLIC_KEY_SIZE),
+        std::vector::length(&bytes) == SIGNATURE_NUM_BYTES,
+        std::error::invalid_argument(E_DESERIALIZE)
     );
-    PublicKey { bytes }
+    ECDSASignature { bytes }
 }
 
-
- - + -## Function `signature_from_bytes` +## Function `ecdsa_raw_public_key_from_64_bytes` -Constructs an Signature struct from the given 64 bytes. +Constructs an ECDSARawPublicKey struct, given a 64-byte raw representation. -
public fun signature_from_bytes(bytes: vector<u8>): secp256k1::Signature
+
public fun ecdsa_raw_public_key_from_64_bytes(bytes: vector<u8>): secp256k1::ECDSARawPublicKey
 
-
-Implementation +##### Implementation -
public fun signature_from_bytes(bytes: vector<u8>): Signature {
-    assert!(std::vector::length(&bytes) == SIGNATURE_SIZE, std::error::invalid_argument(E_WRONG_SIGNATURE_SIZE));
-    Signature { bytes }
+
public fun ecdsa_raw_public_key_from_64_bytes(bytes: vector<u8>): ECDSARawPublicKey {
+    ecdsa_raw_public_key_from_bytes(bytes)
 }
 
-
- - + -## Function `public_key_to_bytes` +## Function `ecdsa_raw_public_key_from_bytes` -Serializes an PublicKey struct to bytes. +Constructs an ECDSARawPublicKey struct, given a 64-byte raw representation. -
public fun public_key_to_bytes(pk: &secp256k1::PublicKey): vector<u8>
+
public fun ecdsa_raw_public_key_from_bytes(bytes: vector<u8>): secp256k1::ECDSARawPublicKey
 
-
-Implementation +##### Implementation -
public fun public_key_to_bytes(pk: &PublicKey): vector<u8> {
-    pk.bytes
+
public fun ecdsa_raw_public_key_from_bytes(bytes: vector<u8>): ECDSARawPublicKey {
+    assert!(
+        std::vector::length(&bytes) == RAW_PUBLIC_KEY_NUM_BYTES,
+        std::error::invalid_argument(E_DESERIALIZE)
+    );
+    ECDSARawPublicKey { bytes }
 }
 
-
+ - +## Function `ecdsa_compressed_public_key_from_bytes` -## Function `signature_to_bytes` +Constructs an ECDSACompressedPublicKey struct, given a 33-byte raw representation. -Serializes an Signature struct to bytes. - -
public fun signature_to_bytes(sig: &secp256k1::Signature): vector<u8>
+
public fun ecdsa_compressed_public_key_from_bytes(bytes: vector<u8>): secp256k1::ECDSACompressedPublicKey
 
-
-Implementation +##### Implementation -
public fun signature_to_bytes(sig: &Signature): vector<u8> {
-    sig.bytes
+
public fun ecdsa_compressed_public_key_from_bytes(bytes: vector<u8>):
+    ECDSACompressedPublicKey {
+    assert!(
+        std::vector::length(&bytes) == COMPRESSED_PUBLIC_KEY_SIZE,
+        std::error::invalid_argument(E_DESERIALIZE)
+    );
+    ECDSACompressedPublicKey { bytes }
 }
 
-
- - + -## Function `verify` +## Function `ecdsa_raw_public_key_to_bytes` -Returns true only the signature can verify the public key on the message +Serializes an ECDSARawPublicKey struct to 64-bytes. -
public fun verify(message: vector<u8>, public_key: &secp256k1::PublicKey, signature: &secp256k1::Signature): bool
+
public fun ecdsa_raw_public_key_to_bytes(pk: &secp256k1::ECDSARawPublicKey): vector<u8>
 
-
-Implementation +##### Implementation -
public fun verify(
-    message: vector<u8>,
-    public_key: &PublicKey,
-    signature: &Signature,
-): bool {
-    assert!(
-        std::vector::length(&message) == MESSAGE_SIZE,
-        std::error::invalid_argument(E_WRONG_MESSAGE_SIZE),
-    );
-
-    return verify_internal(message, public_key.bytes, signature.bytes)
+
public fun ecdsa_raw_public_key_to_bytes(pk: &ECDSARawPublicKey): vector<u8> {
+    pk.bytes
 }
 
-
+ - +## Function `ecdsa_compressed_public_key_to_bytes` -## Function `recover_public_key` +Serializes an ECDSARawPublicKey struct to 64-bytes. + + +
public fun ecdsa_compressed_public_key_to_bytes(pk: &secp256k1::ECDSACompressedPublicKey): vector<u8>
+
-Recovers the signer's (33-byte) compressed public key from a secp256k1 ECDSA signature given the recovery_id -and the signed message (32 byte digest). -Note that an invalid signature, or a signature from a different message, will result in the recovery of an -incorrect public key. This recovery algorithm can only be used to check validity of a signature if the signer's -public key (or its hash) is known beforehand. +##### Implementation -
public fun recover_public_key(message: vector<u8>, recovery_id: u8, signature: &secp256k1::Signature): option::Option<secp256k1::PublicKey>
+
+
public fun ecdsa_compressed_public_key_to_bytes(
+    pk: &ECDSACompressedPublicKey
+): vector<u8> {
+    pk.bytes
+}
 
-
-Implementation + +## Function `ecdsa_signature_to_bytes` -
public fun recover_public_key(
-    message: vector<u8>,
-    recovery_id: u8,
-    signature: &Signature,
-): Option<PublicKey> {
-    assert!(
-        std::vector::length(&message) == MESSAGE_SIZE,
-        std::error::invalid_argument(E_WRONG_MESSAGE_SIZE),
-    );
+Serializes an ECDSASignature struct to 64-bytes.
 
-    let (pk, success) = recover_public_key_internal(recovery_id, message, signature.bytes);
-    if (success) {
-        std::option::some(public_key_from_bytes(pk))
-    } else {
-        std::option::none<PublicKey>()
-    }
-}
+
+
public fun ecdsa_signature_to_bytes(sig: &secp256k1::ECDSASignature): vector<u8>
 
-
+##### Implementation - -## Function `verify_internal` +
public fun ecdsa_signature_to_bytes(sig: &ECDSASignature): vector<u8> {
+    sig.bytes
+}
+
-Returns true if signature verifies on public_key and message -and returns false otherwise. -
fun verify_internal(message: vector<u8>, public_key: vector<u8>, signature: vector<u8>): bool
-
+ +## Function `ecdsa_recover` +Recovers the signer's raw (64-byte) public key from a secp256k1 ECDSA signature given the recovery_id and the signed +message (32 byte digest). -
-Implementation +Note that an invalid signature, or a signature from a different message, will result in the recovery of an +incorrect public key. This recovery algorithm can only be used to check validity of a signature if the signer's +public key (or its hash) is known beforehand. -
native fun verify_internal(
-    message: vector<u8>,
-    public_key: vector<u8>,
-    signature: vector<u8>,
-): bool;
+
public fun ecdsa_recover(message: vector<u8>, recovery_id: u8, signature: &secp256k1::ECDSASignature): option::Option<secp256k1::ECDSARawPublicKey>
 
-
+##### Implementation - -## Function `recover_public_key_internal` +
public fun ecdsa_recover(
+    message: vector<u8>, recovery_id: u8, signature: &ECDSASignature
+): Option<ECDSARawPublicKey> {
+    assert!(
+        std::vector::length(&message) == MESSAGE_SIZE,
+        std::error::invalid_argument(E_DESERIALIZE)
+    );
 
-Returns (public_key, true) if signature verifies on message under the recovered public_key
-and returns ([], false) otherwise.
+    let (pk, success) =
+        recover_public_key_internal(
+            recovery_id,
+            message,
+            signature.bytes,
+            false
+        );
+    if (success) {
+        std::option::some(ecdsa_raw_public_key_from_bytes(pk))
+    } else {
+        std::option::none<ECDSARawPublicKey>()
+    }
+}
+
-
fun recover_public_key_internal(recovery_id: u8, message: vector<u8>, signature: vector<u8>): (vector<u8>, bool)
-
+ + +## Function `ecdsa_recover_compressed` +Recovers the signer's raw (64-byte) public key from a secp256k1 ECDSA signature given the recovery_id and the signed +message (32 byte digest). -
-Implementation +Note that an invalid signature, or a signature from a different message, will result in the recovery of an +incorrect public key. This recovery algorithm can only be used to check validity of a signature if the signer's +public key (or its hash) is known beforehand. -
native fun recover_public_key_internal(
-    recovery_id: u8,
-    message: vector<u8>,
-    signature: vector<u8>,
-): (vector<u8>, bool);
+
public fun ecdsa_recover_compressed(message: vector<u8>, recovery_id: u8, signature: &secp256k1::ECDSASignature): option::Option<secp256k1::ECDSACompressedPublicKey>
 
-
+##### Implementation + + +
public fun ecdsa_recover_compressed(
+    message: vector<u8>, recovery_id: u8, signature: &ECDSASignature
+): Option<ECDSACompressedPublicKey> {
+    assert!(
+        std::vector::length(&message) == MESSAGE_SIZE,
+        std::error::invalid_argument(E_DESERIALIZE)
+    );
+
+    let (pk, success) =
+        recover_public_key_internal(
+            recovery_id,
+            message,
+            signature.bytes,
+            true
+        );
+    if (success) {
+        std::option::some(ecdsa_compressed_public_key_from_bytes(pk))
+    } else {
+        std::option::none<ECDSACompressedPublicKey>()
+    }
+}
+
diff --git a/initia_stdlib/doc/simple_json.md b/initia_stdlib/doc/simple_json.md deleted file mode 100644 index 23dd20e..0000000 --- a/initia_stdlib/doc/simple_json.md +++ /dev/null @@ -1,635 +0,0 @@ - - - -# Module `0x1::simple_json` - -simple_json is a serde style json wrapper to build objects easier - - -- [Struct `SimpleJsonObject`](#0x1_simple_json_SimpleJsonObject) -- [Constants](#@Constants_0) -- [Function `empty`](#0x1_simple_json_empty) -- [Function `from_json_object`](#0x1_simple_json_from_json_object) -- [Function `to_json_object`](#0x1_simple_json_to_json_object) -- [Function `index`](#0x1_simple_json_index) -- [Function `increase_depth`](#0x1_simple_json_increase_depth) -- [Function `decrease_depth`](#0x1_simple_json_decrease_depth) -- [Function `set_index_internal`](#0x1_simple_json_set_index_internal) -- [Function `set_child_length`](#0x1_simple_json_set_child_length) -- [Function `borrow`](#0x1_simple_json_borrow) -- [Function `borrow_mut`](#0x1_simple_json_borrow_mut) -- [Function `set_index`](#0x1_simple_json_set_index) -- [Function `set_to_last_index`](#0x1_simple_json_set_to_last_index) -- [Function `find_and_set_index`](#0x1_simple_json_find_and_set_index) -- [Function `try_find_and_set_index`](#0x1_simple_json_try_find_and_set_index) -- [Function `set_bool`](#0x1_simple_json_set_bool) -- [Function `set_int_raw`](#0x1_simple_json_set_int_raw) -- [Function `set_int_string`](#0x1_simple_json_set_int_string) -- [Function `set_dec_string`](#0x1_simple_json_set_dec_string) -- [Function `set_string`](#0x1_simple_json_set_string) -- [Function `set_array`](#0x1_simple_json_set_array) -- [Function `set_object`](#0x1_simple_json_set_object) - - -
use 0x1::decimal256;
-use 0x1::json;
-use 0x1::option;
-use 0x1::string;
-
- - - - - -## Struct `SimpleJsonObject` - - - -
struct SimpleJsonObject has copy, drop
-
- - - -
-Fields - - -
-
-obj: json::JsonObject -
-
- -
-
-index: json::JsonIndex -
-
- -
-
- - -
- - - -## Constants - - - - - - -
const EKEY_NOT_FOUND: u64 = 0;
-
- - - - - -## Function `empty` - - - -
public fun empty(): simple_json::SimpleJsonObject
-
- - - -
-Implementation - - -
public fun empty(): SimpleJsonObject{
-    SimpleJsonObject {
-        obj: json::empty(),
-        index: json::start_index(),
-    }
-}
-
- - - -
- - - -## Function `from_json_object` - - - -
public fun from_json_object(object: json::JsonObject): simple_json::SimpleJsonObject
-
- - - -
-Implementation - - -
public fun from_json_object(object: JsonObject): SimpleJsonObject{
-    SimpleJsonObject {
-        obj: object,
-        index: json::start_index(),
-    }
-}
-
- - - -
- - - -## Function `to_json_object` - - - -
public fun to_json_object(object: &simple_json::SimpleJsonObject): &json::JsonObject
-
- - - -
-Implementation - - -
public fun to_json_object(object: &SimpleJsonObject): &JsonObject{
-    &object.obj
-}
-
- - - -
- - - -## Function `index` - - - -
public fun index(object: &simple_json::SimpleJsonObject): &json::JsonIndex
-
- - - -
-Implementation - - -
public fun index(object: &SimpleJsonObject): &JsonIndex{
-    &object.index
-}
-
- - - -
- - - -## Function `increase_depth` - - - -
public fun increase_depth(object: &mut simple_json::SimpleJsonObject)
-
- - - -
-Implementation - - -
public fun increase_depth(object: &mut SimpleJsonObject) {
-    object.index = json::get_next_index(&object.index, 0)
-}
-
- - - -
- - - -## Function `decrease_depth` - - - -
public fun decrease_depth(object: &mut simple_json::SimpleJsonObject)
-
- - - -
-Implementation - - -
public fun decrease_depth(object: &mut SimpleJsonObject) {
-    let (prev_index, _) = json::get_prev_index(&object.index);
-    object.index = prev_index;
-}
-
- - - -
- - - -## Function `set_index_internal` - - - -
fun set_index_internal(object: &mut simple_json::SimpleJsonObject): u64
-
- - - -
-Implementation - - -
fun set_index_internal(object: &mut SimpleJsonObject): u64{
-    if(json::get_depth(&object.index) == 1) return 0;
-
-    let (prev_index, last) = json::get_prev_index(&object.index);
-
-    if(last == 0 && json::get_child_length(json::borrow(&object.obj, &prev_index)) == 0) return 0;
-    object.index = json::get_next_index(&prev_index, last + 1);
-    last+1
-}
-
- - - -
- - - -## Function `set_child_length` - - - -
fun set_child_length(object: &mut simple_json::SimpleJsonObject)
-
- - - -
-Implementation - - -
fun set_child_length(object: &mut SimpleJsonObject) {
-    let (prev_index, last) = json::get_prev_index(&object.index);
-    json::set_child_length(json::borrow_mut(&mut object.obj, &prev_index) ,last+1);
-}
-
- - - -
- - - -## Function `borrow` - - - -
public fun borrow(object: &simple_json::SimpleJsonObject): &json::JsonElem
-
- - - -
-Implementation - - -
public fun borrow(object: &SimpleJsonObject): &JsonElem {
-    json::borrow(&object.obj, &object.index)
-}
-
- - - -
- - - -## Function `borrow_mut` - - - -
public fun borrow_mut(object: &mut simple_json::SimpleJsonObject): &mut json::JsonElem
-
- - - -
-Implementation - - -
public fun borrow_mut(object: &mut SimpleJsonObject): &mut JsonElem {
-    json::borrow_mut(&mut object.obj, &object.index)
-}
-
- - - -
- - - -## Function `set_index` - - - -
public fun set_index(object: &mut simple_json::SimpleJsonObject, position: u64)
-
- - - -
-Implementation - - -
public fun set_index(object: &mut SimpleJsonObject, position: u64){
-    let (prev_index, _) = json::get_prev_index(&object.index);
-    object.index = json::get_next_index(&prev_index, position);
-}
-
- - - -
- - - -## Function `set_to_last_index` - - - -
public fun set_to_last_index(object: &mut simple_json::SimpleJsonObject)
-
- - - -
-Implementation - - -
public fun set_to_last_index(object: &mut SimpleJsonObject){
-    let (prev_index, _) = json::get_prev_index(&object.index);
-    let child_length = json::get_child_length(json::borrow(&object.obj, &prev_index));
-    if(child_length == 0) return;
-    object.index = json::get_next_index(&prev_index, child_length - 1);
-}
-
- - - -
- - - -## Function `find_and_set_index` - - - -
public fun find_and_set_index(object: &mut simple_json::SimpleJsonObject, key: &string::String)
-
- - - -
-Implementation - - -
public fun find_and_set_index(object: &mut SimpleJsonObject, key: &String) {
-    let (prev_index, _) = json::get_prev_index(&object.index);
-    let find_index = json::find(&object.obj, &prev_index, key);
-
-    assert!(!json::is_null_index(&find_index), EKEY_NOT_FOUND);
-    object.index = find_index;
-}
-
- - - -
- - - -## Function `try_find_and_set_index` - - - -
public fun try_find_and_set_index(object: &mut simple_json::SimpleJsonObject, key: &string::String): bool
-
- - - -
-Implementation - - -
public fun try_find_and_set_index(object: &mut SimpleJsonObject, key: &String):bool {
-    let (prev_index, _) = json::get_prev_index(&object.index);
-    let find_index = json::find(&object.obj, &prev_index, key);
-
-    if ( json::is_null_index(&find_index)) {
-        false
-    } else {
-        object.index = find_index;
-        true
-    }
-}
-
- - - -
- - - -## Function `set_bool` - - - -
public fun set_bool(object: &mut simple_json::SimpleJsonObject, key: option::Option<string::String>, value: bool)
-
- - - -
-Implementation - - -
public fun set_bool(object: &mut SimpleJsonObject, key: Option<String>, value: bool) {
-    set_index_internal(object);
-    json::set_bool(&mut object.obj, object.index, key, value);
-    if(json::get_depth(&object.index) != 1) set_child_length(object);
-}
-
- - - -
- - - -## Function `set_int_raw` - - - -
public fun set_int_raw(object: &mut simple_json::SimpleJsonObject, key: option::Option<string::String>, is_positive: bool, value: u256)
-
- - - -
-Implementation - - -
public fun set_int_raw(object:&mut SimpleJsonObject, key: Option<String>, is_positive: bool, value: u256) {
-    set_index_internal(object);
-    json::set_int_raw(&mut object.obj, object.index, key, is_positive, value);
-    if(json::get_depth(&object.index) != 1) set_child_length(object);
-}
-
- - - -
- - - -## Function `set_int_string` - - - -
public fun set_int_string(object: &mut simple_json::SimpleJsonObject, key: option::Option<string::String>, is_positive: bool, value: u256)
-
- - - -
-Implementation - - -
public fun set_int_string(object:&mut SimpleJsonObject, key: Option<String>, is_positive: bool, value: u256) {
-    set_index_internal(object);
-    json::set_int_string(&mut object.obj, object.index, key, is_positive, value);
-    if(json::get_depth(&object.index) != 1) set_child_length(object);
-}
-
- - - -
- - - -## Function `set_dec_string` - - - -
public fun set_dec_string(object: &mut simple_json::SimpleJsonObject, key: option::Option<string::String>, is_positive: bool, value: decimal256::Decimal256)
-
- - - -
-Implementation - - -
public fun set_dec_string(object:&mut SimpleJsonObject, key: Option<String>, is_positive: bool, value: Decimal256) {
-    set_index_internal(object);
-    json::set_dec_string(&mut object.obj, object.index, key, is_positive, value);
-    if(json::get_depth(&object.index) != 1) set_child_length(object);
-}
-
- - - -
- - - -## Function `set_string` - - - -
public fun set_string(object: &mut simple_json::SimpleJsonObject, key: option::Option<string::String>, value: string::String)
-
- - - -
-Implementation - - -
public fun set_string(object: &mut SimpleJsonObject, key: Option<String>, value: String) {
-    set_index_internal(object);
-    json::set_string(&mut object.obj, object.index, key, value);
-    if(json::get_depth(&object.index) != 1) set_child_length(object);
-}
-
- - - -
- - - -## Function `set_array` - - - -
public fun set_array(object: &mut simple_json::SimpleJsonObject, key: option::Option<string::String>)
-
- - - -
-Implementation - - -
public fun set_array(object: &mut SimpleJsonObject, key: Option<String>) {
-    set_index_internal(object);
-    json::set_array(&mut object.obj, object.index, key, 0);
-    if(json::get_depth(&object.index) != 1) set_child_length(object);
-}
-
- - - -
- - - -## Function `set_object` - - - -
public fun set_object(object: &mut simple_json::SimpleJsonObject, key: option::Option<string::String>)
-
- - - -
-Implementation - - -
public fun set_object(object: &mut SimpleJsonObject, key: Option<String>) {
-    set_index_internal(object);
-    json::set_object(&mut object.obj, object.index, key, 0);
-    if(json::get_depth(&object.index) != 1) set_child_length(object);
-}
-
- - - -
diff --git a/initia_stdlib/doc/simple_map.md b/initia_stdlib/doc/simple_map.md index d2f6b71..d3a714b 100644 --- a/initia_stdlib/doc/simple_map.md +++ b/initia_stdlib/doc/simple_map.md @@ -3,11 +3,11 @@ # Module `0x1::simple_map` -This module provides a solution for sorted maps, that is it has the properties that +This module provides a solution for unsorted maps, that is it has the properties that 1) Keys point to Values 2) Each Key must be unique -3) A Key can be found within O(Log N) time -4) The data is stored as a sorted by Key +3) A Key can be found within O(N) time +4) The keys are unsorted. 5) Adds and removals take O(N) time @@ -15,19 +15,26 @@ This module provides a solution for sorted maps, that is it has the properties t - [Struct `Element`](#0x1_simple_map_Element) - [Constants](#@Constants_0) - [Function `length`](#0x1_simple_map_length) +- [Function `new`](#0x1_simple_map_new) +- [Function `new_from`](#0x1_simple_map_new_from) - [Function `create`](#0x1_simple_map_create) - [Function `borrow`](#0x1_simple_map_borrow) - [Function `borrow_mut`](#0x1_simple_map_borrow_mut) - [Function `contains_key`](#0x1_simple_map_contains_key) - [Function `destroy_empty`](#0x1_simple_map_destroy_empty) - [Function `add`](#0x1_simple_map_add) +- [Function `add_all`](#0x1_simple_map_add_all) +- [Function `upsert`](#0x1_simple_map_upsert) +- [Function `keys`](#0x1_simple_map_keys) +- [Function `values`](#0x1_simple_map_values) +- [Function `to_vec_pair`](#0x1_simple_map_to_vec_pair) +- [Function `destroy`](#0x1_simple_map_destroy) - [Function `remove`](#0x1_simple_map_remove) -- [Function `find`](#0x1_simple_map_find) -
use 0x1::comparator;
-use 0x1::error;
+
use 0x1::error;
 use 0x1::option;
+use 0x1::vector;
 
@@ -43,8 +50,7 @@ This module provides a solution for sorted maps, that is it has the properties t -
-Fields +##### Fields
@@ -57,8 +63,6 @@ This module provides a solution for sorted maps, that is it has the properties t
-
- ## Struct `Element` @@ -70,8 +74,7 @@ This module provides a solution for sorted maps, that is it has the properties t -
-Fields +##### Fields
@@ -90,8 +93,6 @@ This module provides a solution for sorted maps, that is it has the properties t
-
- ## Constants @@ -99,18 +100,20 @@ This module provides a solution for sorted maps, that is it has the properties t +Map key already exists -
const EKEY_ALREADY_EXISTS: u64 = 0;
+
const EKEY_ALREADY_EXISTS: u64 = 1;
 
+Map key is not found -
const EKEY_NOT_FOUND: u64 = 1;
+
const EKEY_NOT_FOUND: u64 = 2;
 
@@ -121,287 +124,437 @@ This module provides a solution for sorted maps, that is it has the properties t -
public fun length<Key: store, Value: store>(map: &simple_map::SimpleMap<Key, Value>): u64
+
public fun length<Key: store, Value: store>(self: &simple_map::SimpleMap<Key, Value>): u64
 
-
-Implementation +##### Implementation -
public fun length<Key: store, Value: store>(map: &SimpleMap<Key, Value>): u64 {
-    vector::length(&map.data)
+
public fun length<Key: store, Value: store>(self: &SimpleMap<Key, Value>): u64 {
+    vector::length(&self.data)
 }
 
-
+ + +## Function `new` + +Create an empty SimpleMap. + + +
public fun new<Key: store, Value: store>(): simple_map::SimpleMap<Key, Value>
+
+ + + +##### Implementation + + +
public fun new<Key: store, Value: store>(): SimpleMap<Key, Value> {
+    SimpleMap { data: vector::empty() }
+}
+
+ + + + + +## Function `new_from` + +Create a SimpleMap from a vector of keys and values. The keys must be unique. + + +
public fun new_from<Key: store, Value: store>(keys: vector<Key>, values: vector<Value>): simple_map::SimpleMap<Key, Value>
+
+ + + +##### Implementation + + +
public fun new_from<Key: store, Value: store>(
+    keys: vector<Key>, values: vector<Value>
+): SimpleMap<Key, Value> {
+    let map = new();
+    add_all(&mut map, keys, values);
+    map
+}
+
+ + ## Function `create` +Create an empty SimpleMap. +This function is deprecated, use new instead. -
public fun create<Key: store, Value: store>(): simple_map::SimpleMap<Key, Value>
+
#[deprecated]
+public fun create<Key: store, Value: store>(): simple_map::SimpleMap<Key, Value>
 
-
-Implementation +##### Implementation
public fun create<Key: store, Value: store>(): SimpleMap<Key, Value> {
-    SimpleMap {
-        data: vector::empty(),
-    }
+    new()
 }
 
-
- ## Function `borrow` -
public fun borrow<Key: store, Value: store>(map: &simple_map::SimpleMap<Key, Value>, key: &Key): &Value
+
public fun borrow<Key: store, Value: store>(self: &simple_map::SimpleMap<Key, Value>, key: &Key): &Value
 
-
-Implementation +##### Implementation
public fun borrow<Key: store, Value: store>(
-    map: &SimpleMap<Key, Value>,
-    key: &Key,
+    self: &SimpleMap<Key, Value>, key: &Key
 ): &Value {
-    let (maybe_idx, _) = find(map, key);
+    let maybe_idx = find(self, key);
     assert!(option::is_some(&maybe_idx), error::invalid_argument(EKEY_NOT_FOUND));
     let idx = option::extract(&mut maybe_idx);
-    &vector::borrow(&map.data, idx).value
+    &vector::borrow(&self.data, idx).value
 }
 
-
- ## Function `borrow_mut` -
public fun borrow_mut<Key: store, Value: store>(map: &mut simple_map::SimpleMap<Key, Value>, key: &Key): &mut Value
+
public fun borrow_mut<Key: store, Value: store>(self: &mut simple_map::SimpleMap<Key, Value>, key: &Key): &mut Value
 
-
-Implementation +##### Implementation
public fun borrow_mut<Key: store, Value: store>(
-    map: &mut SimpleMap<Key, Value>,
-    key: &Key,
+    self: &mut SimpleMap<Key, Value>, key: &Key
 ): &mut Value {
-    let (maybe_idx, _) = find(map, key);
+    let maybe_idx = find(self, key);
     assert!(option::is_some(&maybe_idx), error::invalid_argument(EKEY_NOT_FOUND));
     let idx = option::extract(&mut maybe_idx);
-    &mut vector::borrow_mut(&mut map.data, idx).value
+    &mut vector::borrow_mut(&mut self.data, idx).value
 }
 
-
- ## Function `contains_key` -
public fun contains_key<Key: store, Value: store>(map: &simple_map::SimpleMap<Key, Value>, key: &Key): bool
+
public fun contains_key<Key: store, Value: store>(self: &simple_map::SimpleMap<Key, Value>, key: &Key): bool
 
-
-Implementation +##### Implementation
public fun contains_key<Key: store, Value: store>(
-    map: &SimpleMap<Key, Value>,
-    key: &Key,
+    self: &SimpleMap<Key, Value>, key: &Key
 ): bool {
-    let (maybe_idx, _) = find(map, key);
+    let maybe_idx = find(self, key);
     option::is_some(&maybe_idx)
 }
 
-
- ## Function `destroy_empty` -
public fun destroy_empty<Key: store, Value: store>(map: simple_map::SimpleMap<Key, Value>)
+
public fun destroy_empty<Key: store, Value: store>(self: simple_map::SimpleMap<Key, Value>)
 
-
-Implementation +##### Implementation -
public fun destroy_empty<Key: store, Value: store>(map: SimpleMap<Key, Value>) {
-    let SimpleMap { data } = map;
+
public fun destroy_empty<Key: store, Value: store>(
+    self: SimpleMap<Key, Value>
+) {
+    let SimpleMap { data } = self;
     vector::destroy_empty(data);
 }
 
-
- ## Function `add` +Add a key/value pair to the map. The key must not already exist. -
public fun add<Key: store, Value: store>(map: &mut simple_map::SimpleMap<Key, Value>, key: Key, value: Value)
+
public fun add<Key: store, Value: store>(self: &mut simple_map::SimpleMap<Key, Value>, key: Key, value: Value)
 
-
-Implementation +##### Implementation
public fun add<Key: store, Value: store>(
-    map: &mut SimpleMap<Key, Value>,
+    self: &mut SimpleMap<Key, Value>,
     key: Key,
-    value: Value,
+    value: Value
 ) {
-    let (maybe_idx, maybe_placement) = find(map, &key);
+    let maybe_idx = find(self, &key);
     assert!(option::is_none(&maybe_idx), error::invalid_argument(EKEY_ALREADY_EXISTS));
 
-    // Append to the end and then swap elements until the list is ordered again
-    vector::push_back(&mut map.data, Element { key, value });
+    vector::push_back(&mut self.data, Element { key, value });
+}
+
+ + + + + +## Function `add_all` + +Add multiple key/value pairs to the map. The keys must not already exist. + + +
public fun add_all<Key: store, Value: store>(self: &mut simple_map::SimpleMap<Key, Value>, keys: vector<Key>, values: vector<Value>)
+
+ + + +##### Implementation + + +
public fun add_all<Key: store, Value: store>(
+    self: &mut SimpleMap<Key, Value>,
+    keys: vector<Key>,
+    values: vector<Value>
+) {
+    vector::zip(
+        keys,
+        values,
+        |key, value| {
+            add(self, key, value);
+        }
+    );
+}
+
+ + + + + +## Function `upsert` + +Insert key/value pair or update an existing key to a new value + - let placement = option::extract(&mut maybe_placement); - let end = vector::length(&map.data) - 1; - while (placement < end) { - vector::swap(&mut map.data, placement, end); - placement = placement + 1; +
public fun upsert<Key: store, Value: store>(self: &mut simple_map::SimpleMap<Key, Value>, key: Key, value: Value): (option::Option<Key>, option::Option<Value>)
+
+ + + +##### Implementation + + +
public fun upsert<Key: store, Value: store>(
+    self: &mut SimpleMap<Key, Value>,
+    key: Key,
+    value: Value
+): (std::option::Option<Key>, std::option::Option<Value>) {
+    let data = &mut self.data;
+    let len = vector::length(data);
+    let i = 0;
+    while (i < len) {
+        let element = vector::borrow(data, i);
+        if (&element.key == &key) {
+            vector::push_back(data, Element { key, value });
+            vector::swap(data, i, len);
+            let Element { key, value } = vector::pop_back(data);
+            return (std::option::some(key), std::option::some(value))
+        };
+        i = i + 1;
     };
+    vector::push_back(&mut self.data, Element { key, value });
+    (std::option::none(), std::option::none())
 }
 
-
+ + +## Function `keys` + +Return all keys in the map. This requires keys to be copyable. + + +
public fun keys<Key: copy, Value>(self: &simple_map::SimpleMap<Key, Value>): vector<Key>
+
- -## Function `remove` +##### Implementation -
public fun remove<Key: store, Value: store>(map: &mut simple_map::SimpleMap<Key, Value>, key: &Key): (Key, Value)
+
public fun keys<Key: copy, Value>(self: &SimpleMap<Key, Value>): vector<Key> {
+    vector::map_ref(
+        &self.data,
+        |e| {
+            let e: &Element<Key, Value> = e;
+            e.key
+        }
+    )
+}
 
-
-Implementation + +## Function `values` -
public fun remove<Key: store, Value: store>(
-    map: &mut SimpleMap<Key, Value>,
-    key: &Key,
-): (Key, Value) {
-    let (maybe_idx, _) = find(map, key);
-    assert!(option::is_some(&maybe_idx), error::invalid_argument(EKEY_NOT_FOUND));
+Return all values in the map. This requires values to be copyable.
 
-    let placement = option::extract(&mut maybe_idx);
-    let end = vector::length(&map.data) - 1;
 
-    while (placement < end) {
-        vector::swap(&mut map.data, placement, placement + 1);
-        placement = placement + 1;
-    };
+
public fun values<Key, Value: copy>(self: &simple_map::SimpleMap<Key, Value>): vector<Value>
+
- let Element { key, value } = vector::pop_back(&mut map.data); - (key, value) + + +##### Implementation + + +
public fun values<Key, Value: copy>(self: &SimpleMap<Key, Value>): vector<Value> {
+    vector::map_ref(
+        &self.data,
+        |e| {
+            let e: &Element<Key, Value> = e;
+            e.value
+        }
+    )
 }
 
-
+ + +## Function `to_vec_pair` + +Transform the map into two vectors with the keys and values respectively +Primarily used to destroy a map + + +
public fun to_vec_pair<Key: store, Value: store>(self: simple_map::SimpleMap<Key, Value>): (vector<Key>, vector<Value>)
+
- -## Function `find` +##### Implementation -
fun find<Key: store, Value: store>(map: &simple_map::SimpleMap<Key, Value>, key: &Key): (option::Option<u64>, option::Option<u64>)
+
public fun to_vec_pair<Key: store, Value: store>(
+    self: SimpleMap<Key, Value>
+): (vector<Key>, vector<Value>) {
+    let keys: vector<Key> = vector::empty();
+    let values: vector<Value> = vector::empty();
+    let SimpleMap { data } = self;
+    vector::for_each(
+        data,
+        |e| {
+            let Element { key, value } = e;
+            vector::push_back(&mut keys, key);
+            vector::push_back(&mut values, value);
+        }
+    );
+    (keys, values)
+}
 
-
-Implementation + +## Function `destroy` -
fun find<Key: store, Value: store>(
-    map: &SimpleMap<Key, Value>,
-    key: &Key,
-): (option::Option<u64>, option::Option<u64>) {
-    let length = vector::length(&map.data);
+For maps that cannot be dropped this is a utility to destroy them
+using lambdas to destroy the individual keys and values.
 
-    if (length == 0) {
-        return (option::none(), option::some(0))
-    };
 
-    let left = 0;
-    let right = length;
+
public fun destroy<Key: store, Value: store>(self: simple_map::SimpleMap<Key, Value>, dk: |Key|, dv: |Value|)
+
+ - while (left != right) { - let mid = (left + right) / 2; - let potential_key = &vector::borrow(&map.data, mid).key; - if (comparator::is_smaller_than(&comparator::compare(potential_key, key))) { - left = mid + 1; - } else { - right = mid; - }; - }; - if (left != length && key == &vector::borrow(&map.data, left).key) { - (option::some(left), option::none()) - } else { - (option::none(), option::some(left)) - } +##### Implementation + + +
public inline fun destroy<Key: store, Value: store>(
+    self: SimpleMap<Key, Value>,
+    dk: |Key|,
+    dv: |Value|
+) {
+    let (keys, values) = to_vec_pair(self);
+    vector::destroy(keys, |_k| dk(_k));
+    vector::destroy(values, |_v| dv(_v));
 }
 
-
+ + +## Function `remove` + +Remove a key/value pair from the map. The key must exist. + + +
public fun remove<Key: store, Value: store>(self: &mut simple_map::SimpleMap<Key, Value>, key: &Key): (Key, Value)
+
+ + + +##### Implementation + + +
public fun remove<Key: store, Value: store>(
+    self: &mut SimpleMap<Key, Value>, key: &Key
+): (Key, Value) {
+    let maybe_idx = find(self, key);
+    assert!(option::is_some(&maybe_idx), error::invalid_argument(EKEY_NOT_FOUND));
+    let placement = option::extract(&mut maybe_idx);
+    let Element { key, value } = vector::swap_remove(&mut self.data, placement);
+    (key, value)
+}
+
diff --git a/initia_stdlib/doc/simple_nft.md b/initia_stdlib/doc/simple_nft.md index 622539c..418409e 100644 --- a/initia_stdlib/doc/simple_nft.md +++ b/initia_stdlib/doc/simple_nft.md @@ -13,9 +13,7 @@ Sample of nft extension including metadata property type by using 0x1::initia_nf - [Function `create_collection_object`](#0x1_simple_nft_create_collection_object) - [Function `mint`](#0x1_simple_nft_mint) - [Function `mint_nft_object`](#0x1_simple_nft_mint_nft_object) -- [Function `borrow`](#0x1_simple_nft_borrow) - [Function `are_properties_mutable`](#0x1_simple_nft_are_properties_mutable) -- [Function `authorized_borrow`](#0x1_simple_nft_authorized_borrow) - [Function `burn`](#0x1_simple_nft_burn) - [Function `set_description`](#0x1_simple_nft_set_description) - [Function `set_uri`](#0x1_simple_nft_set_uri) @@ -24,23 +22,20 @@ Sample of nft extension including metadata property type by using 0x1::initia_nf - [Function `remove_property`](#0x1_simple_nft_remove_property) - [Function `update_property`](#0x1_simple_nft_update_property) - [Function `update_typed_property`](#0x1_simple_nft_update_typed_property) -- [Function `collection_object`](#0x1_simple_nft_collection_object) -- [Function `borrow_collection`](#0x1_simple_nft_borrow_collection) - [Function `is_mutable_collection_description`](#0x1_simple_nft_is_mutable_collection_description) - [Function `is_mutable_collection_royalty`](#0x1_simple_nft_is_mutable_collection_royalty) - [Function `is_mutable_collection_uri`](#0x1_simple_nft_is_mutable_collection_uri) - [Function `is_mutable_collection_nft_description`](#0x1_simple_nft_is_mutable_collection_nft_description) - [Function `is_mutable_collection_nft_uri`](#0x1_simple_nft_is_mutable_collection_nft_uri) - [Function `is_mutable_collection_nft_properties`](#0x1_simple_nft_is_mutable_collection_nft_properties) -- [Function `authorized_borrow_collection`](#0x1_simple_nft_authorized_borrow_collection) - [Function `set_collection_description`](#0x1_simple_nft_set_collection_description) - [Function `set_collection_royalties`](#0x1_simple_nft_set_collection_royalties) - [Function `set_collection_royalties_call`](#0x1_simple_nft_set_collection_royalties_call) - [Function `set_collection_uri`](#0x1_simple_nft_set_collection_uri) -
use 0x1::collection;
-use 0x1::decimal128;
+
use 0x1::bigdecimal;
+use 0x1::collection;
 use 0x1::error;
 use 0x1::initia_nft;
 use 0x1::nft;
@@ -66,8 +61,7 @@ Storage state for managing the no-code Collection.
 
 
 
-
-Fields +##### Fields
@@ -80,8 +74,6 @@ Storage state for managing the no-code Collection.
-
- ## Resource `SimpleNft` @@ -94,8 +86,7 @@ Storage state for managing the no-code Nft. -
-Fields +##### Fields
@@ -108,8 +99,6 @@ Storage state for managing the no-code Nft.
-
- ## Constants @@ -172,13 +161,12 @@ The property map being mutated is not mutable Create a new collection -
public entry fun create_collection(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: decimal128::Decimal128)
+
public entry fun create_collection(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation
public entry fun create_collection(
@@ -193,7 +181,7 @@ Create a new collection
     mutable_nft_description: bool,
     mutable_nft_properties: bool,
     mutable_nft_uri: bool,
-    royalty: Decimal128,
+    royalty: BigDecimal
 ) {
     create_collection_object(
         creator,
@@ -207,28 +195,25 @@ Create a new collection
         mutable_nft_description,
         mutable_nft_properties,
         mutable_nft_uri,
-        royalty,
+        royalty
     );
 }
 
-
- ## Function `create_collection_object` -
public fun create_collection_object(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: decimal128::Decimal128): object::Object<simple_nft::SimpleNftCollection>
+
public fun create_collection_object(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: bigdecimal::BigDecimal): object::Object<simple_nft::SimpleNftCollection>
 
-
-Implementation +##### Implementation
public fun create_collection_object(
@@ -243,27 +228,26 @@ Create a new collection
     mutable_nft_description: bool,
     mutable_nft_properties: bool,
     mutable_nft_uri: bool,
-    royalty: Decimal128,
+    royalty: BigDecimal
 ): Object<SimpleNftCollection> {
-    let (_, extend_ref) = initia_nft::create_collection_object(
-        creator,
-        description,
-        max_supply,
-        name,
-        uri,
-        mutable_description,
-        mutable_royalty,
-        mutable_uri,
-        mutable_nft_description,
-        mutable_nft_uri,
-        royalty,
-    );
+    let (_, extend_ref) =
+        initia_nft::create_collection_object(
+            creator,
+            description,
+            max_supply,
+            name,
+            uri,
+            mutable_description,
+            mutable_royalty,
+            mutable_uri,
+            mutable_nft_description,
+            mutable_nft_uri,
+            royalty
+        );
 
     let object_signer = object::generate_signer_for_extending(&extend_ref);
 
-    let simple_nft_collection = SimpleNftCollection {
-        mutable_nft_properties,
-    };
+    let simple_nft_collection = SimpleNftCollection { mutable_nft_properties };
     move_to(&object_signer, simple_nft_collection);
     object::address_to_object<SimpleNftCollection>(signer::address_of(&object_signer))
 }
@@ -271,8 +255,6 @@ Create a new collection
 
 
 
-
- ## Function `mint` @@ -285,8 +267,7 @@ With an existing collection, directly mint a viable nft into the creators accoun -
-Implementation +##### Implementation
public entry fun mint(
@@ -298,22 +279,31 @@ With an existing collection, directly mint a viable nft into the creators accoun
     property_keys: vector<String>,
     property_types: vector<String>,
     property_values: vector<vector<u8>>,
-    to: Option<address>,
+    to: Option<address>
 ) {
-    let nft_object = mint_nft_object(
-        creator, collection, description,
-        token_id, uri, property_keys, property_types, property_values,
-    );
+    let nft_object =
+        mint_nft_object(
+            creator,
+            collection,
+            description,
+            token_id,
+            uri,
+            property_keys,
+            property_types,
+            property_values
+        );
     if (option::is_some(&to)) {
-        object::transfer(creator, nft_object, option::extract(&mut to));
+        object::transfer(
+            creator,
+            nft_object,
+            option::extract(&mut to)
+        );
     }
 }
 
-
- ## Function `mint_nft_object` @@ -326,8 +316,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun mint_nft_object(
@@ -338,23 +327,29 @@ Mint a nft into an existing collection, and retrieve the object / address of the
     uri: String,
     property_keys: vector<String>,
     property_types: vector<String>,
-    property_values: vector<vector<u8>>,
+    property_values: vector<vector<u8>>
 ): Object<SimpleNft> {
-    let (object, extend_ref) = initia_nft::mint_nft_object(
-        creator,
-        collection,
-        description,
-        token_id,
-        uri,
-        true,
-    );
+    let (object, extend_ref) =
+        initia_nft::mint_nft_object(
+            creator,
+            collection,
+            description,
+            token_id,
+            uri,
+            true
+        );
     let s = object::generate_signer_for_extending(&extend_ref);
 
-    let properties = property_map::prepare_input(property_keys, property_types, property_values);
+    let properties =
+        property_map::prepare_input(
+            property_keys,
+            property_types,
+            property_values
+        );
     property_map::init(&s, properties);
 
     let simple_nft = SimpleNft {
-        property_mutator_ref: property_map::generate_mutator_ref(&s),
+        property_mutator_ref: property_map::generate_mutator_ref(&s)
     };
     move_to(&s, simple_nft);
 
@@ -364,37 +359,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- - - -## Function `borrow` - - - -
fun borrow<T: key>(nft: object::Object<T>): &simple_nft::SimpleNft
-
- - - -
-Implementation - - -
inline fun borrow<T: key>(nft: Object<T>): &SimpleNft {
-    let nft_address = object::object_address(nft);
-    assert!(
-        exists<SimpleNft>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-    borrow_global<SimpleNft>(nft_address)
-}
-
- - - -
- ## Function `are_properties_mutable` @@ -407,8 +371,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun are_properties_mutable<T: key>(nft: Object<T>): bool acquires SimpleNftCollection {
@@ -419,42 +382,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- - - -## Function `authorized_borrow` - - - -
fun authorized_borrow<T: key>(nft: object::Object<T>, creator: &signer): &simple_nft::SimpleNft
-
- - - -
-Implementation - - -
inline fun authorized_borrow<T: key>(nft: Object<T>, creator: &signer): &SimpleNft {
-    let nft_address = object::object_address(nft);
-    assert!(
-        exists<SimpleNft>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-
-    assert!(
-        nft::creator(nft) == signer::address_of(creator),
-        error::permission_denied(ENOT_CREATOR),
-    );
-    borrow_global<SimpleNft>(nft_address)
-}
-
- - - -
- ## Function `burn` @@ -466,22 +393,21 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun burn<T: key>(owner: &signer, nft: Object<T>) acquires SimpleNft {
-    let nft_address = object::object_address(nft);
+    let nft_address = object::object_address(&nft);
     assert!(
         exists<SimpleNft>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
+        error::not_found(ENFT_DOES_NOT_EXIST)
     );
     assert!(
         object::owns(nft, signer::address_of(owner)),
-        error::permission_denied(ENOT_OWNER),
+        error::permission_denied(ENOT_OWNER)
     );
 
-    let simple_nft = move_from<SimpleNft>(object::object_address(nft));
+    let simple_nft = move_from<SimpleNft>(object::object_address(&nft));
     let SimpleNft { property_mutator_ref } = simple_nft;
     property_map::burn(property_mutator_ref);
     initia_nft::burn(owner, nft);
@@ -490,8 +416,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `set_description` @@ -503,14 +427,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_description<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    description: String,
+    creator: &signer, nft: Object<T>, description: String
 ) {
     initia_nft::set_description(creator, nft, description);
 }
@@ -518,8 +439,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `set_uri` @@ -531,14 +450,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_uri<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    uri: String,
+    creator: &signer, nft: Object<T>, uri: String
 ) {
     initia_nft::set_uri(creator, nft, uri);
 }
@@ -546,8 +462,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `add_property` @@ -559,8 +473,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun add_property<T: key>(
@@ -568,22 +481,25 @@ Mint a nft into an existing collection, and retrieve the object / address of the
     nft: Object<T>,
     key: String,
     type: String,
-    value: vector<u8>,
+    value: vector<u8>
 ) acquires SimpleNftCollection, SimpleNft {
     let simple_nft = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
-    property_map::add(&simple_nft.property_mutator_ref, key, type, value);
+    property_map::add(
+        &simple_nft.property_mutator_ref,
+        key,
+        type,
+        value
+    );
 }
 
-
- ## Function `add_typed_property` @@ -595,20 +511,19 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun add_typed_property<T: key, V: drop>(
     creator: &signer,
     nft: Object<T>,
     key: String,
-    value: V,
+    value: V
 ) acquires SimpleNftCollection, SimpleNft {
     let simple_nft = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
     property_map::add_typed(&simple_nft.property_mutator_ref, key, value);
@@ -617,8 +532,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `remove_property` @@ -630,19 +543,16 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun remove_property<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    key: String,
+    creator: &signer, nft: Object<T>, key: String
 ) acquires SimpleNftCollection, SimpleNft {
     let simple_nft = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
     property_map::remove(&simple_nft.property_mutator_ref, &key);
@@ -651,8 +561,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `update_property` @@ -664,8 +572,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun update_property<T: key>(
@@ -673,22 +580,25 @@ Mint a nft into an existing collection, and retrieve the object / address of the
     nft: Object<T>,
     key: String,
     type: String,
-    value: vector<u8>,
+    value: vector<u8>
 ) acquires SimpleNftCollection, SimpleNft {
     let simple_nft = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
-    property_map::update(&simple_nft.property_mutator_ref, &key, type, value);
+    property_map::update(
+        &simple_nft.property_mutator_ref,
+        &key,
+        type,
+        value
+    );
 }
 
-
- ## Function `update_typed_property` @@ -700,84 +610,31 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun update_typed_property<T: key, V: drop>(
     creator: &signer,
     nft: Object<T>,
     key: String,
-    value: V,
+    value: V
 ) acquires SimpleNftCollection, SimpleNft {
     let simple_nft = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
-    property_map::update_typed(&simple_nft.property_mutator_ref, &key, value);
-}
-
- - - -
- - - -## Function `collection_object` - - - -
fun collection_object(creator: &signer, name: &string::String): object::Object<simple_nft::SimpleNftCollection>
-
- - - -
-Implementation - - -
inline fun collection_object(creator: &signer, name: &String): Object<SimpleNftCollection> {
-    let collection_addr = collection::create_collection_address(signer::address_of(creator), name);
-    object::address_to_object<SimpleNftCollection>(collection_addr)
-}
-
- - - -
- - - -## Function `borrow_collection` - - - -
fun borrow_collection<T: key>(nft: object::Object<T>): &simple_nft::SimpleNftCollection
-
- - - -
-Implementation - - -
inline fun borrow_collection<T: key>(nft: Object<T>): &SimpleNftCollection {
-    let collection_address = object::object_address(nft);
-    assert!(
-        exists<SimpleNftCollection>(collection_address),
-        error::not_found(ECOLLECTION_DOES_NOT_EXIST),
+    property_map::update_typed(
+        &simple_nft.property_mutator_ref,
+        &key,
+        value
     );
-    borrow_global<SimpleNftCollection>(collection_address)
 }
 
-
- ## Function `is_mutable_collection_description` @@ -789,12 +646,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_description<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool {
     initia_nft::is_mutable_collection_description(collection)
 }
@@ -802,8 +658,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_royalty` @@ -815,12 +669,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_royalty<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool {
     initia_nft::is_mutable_collection_royalty(collection)
 }
@@ -828,8 +681,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_uri` @@ -841,21 +692,16 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation -
public fun is_mutable_collection_uri<T: key>(
-    collection: Object<T>,
-): bool {
+
public fun is_mutable_collection_uri<T: key>(collection: Object<T>): bool {
     initia_nft::is_mutable_collection_uri(collection)
 }
 
-
- ## Function `is_mutable_collection_nft_description` @@ -867,12 +713,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_description<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool {
     initia_nft::is_mutable_collection_nft_description(collection)
 }
@@ -880,8 +725,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_nft_uri` @@ -893,12 +736,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_uri<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool {
     initia_nft::is_mutable_collection_nft_uri(collection)
 }
@@ -906,8 +748,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_nft_properties` @@ -919,12 +759,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_properties<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SimpleNftCollection {
     borrow_collection(collection).mutable_nft_properties
 }
@@ -932,41 +771,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- - - -## Function `authorized_borrow_collection` - - - -
fun authorized_borrow_collection<T: key>(collection: object::Object<T>, creator: &signer): &simple_nft::SimpleNftCollection
-
- - - -
-Implementation - - -
inline fun authorized_borrow_collection<T: key>(collection: Object<T>, creator: &signer): &SimpleNftCollection {
-    let collection_address = object::object_address(collection);
-    assert!(
-        exists<SimpleNftCollection>(collection_address),
-        error::not_found(ECOLLECTION_DOES_NOT_EXIST),
-    );
-    assert!(
-        collection::creator(collection) == signer::address_of(creator),
-        error::permission_denied(ENOT_CREATOR),
-    );
-    borrow_global<SimpleNftCollection>(collection_address)
-}
-
- - - -
- ## Function `set_collection_description` @@ -978,14 +782,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_collection_description<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    description: String,
+    creator: &signer, collection: Object<T>, description: String
 ) {
     initia_nft::set_collection_description(creator, collection, description);
 }
@@ -993,8 +794,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `set_collection_royalties` @@ -1006,14 +805,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun set_collection_royalties<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    royalty: royalty::Royalty,
+    creator: &signer, collection: Object<T>, royalty: royalty::Royalty
 ) {
     initia_nft::set_collection_royalties(creator, collection, royalty);
 }
@@ -1021,28 +817,25 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `set_collection_royalties_call` -
entry fun set_collection_royalties_call<T: key>(creator: &signer, collection: object::Object<T>, royalty: decimal128::Decimal128, payee_address: address)
+
entry fun set_collection_royalties_call<T: key>(creator: &signer, collection: object::Object<T>, royalty: bigdecimal::BigDecimal, payee_address: address)
 
-
-Implementation +##### Implementation
entry fun set_collection_royalties_call<T: key>(
     creator: &signer,
     collection: Object<T>,
-    royalty: Decimal128,
-    payee_address: address,
+    royalty: BigDecimal,
+    payee_address: address
 ) {
     let royalty = royalty::create(royalty, payee_address);
     set_collection_royalties(creator, collection, royalty);
@@ -1051,8 +844,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `set_collection_uri` @@ -1064,19 +855,12 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_collection_uri<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    uri: String,
+    creator: &signer, collection: Object<T>, uri: String
 ) {
     initia_nft::set_collection_uri(creator, collection, uri);
 }
 
- - - -
diff --git a/initia_stdlib/doc/soul_bound_token.md b/initia_stdlib/doc/soul_bound_token.md index 740c27b..c2d6cc8 100644 --- a/initia_stdlib/doc/soul_bound_token.md +++ b/initia_stdlib/doc/soul_bound_token.md @@ -14,13 +14,10 @@ initia_std::nft module. - [Function `create_collection_object`](#0x1_soul_bound_token_create_collection_object) - [Function `mint`](#0x1_soul_bound_token_mint) - [Function `mint_soul_bound_token_object`](#0x1_soul_bound_token_mint_soul_bound_token_object) -- [Function `mint_internal`](#0x1_soul_bound_token_mint_internal) -- [Function `borrow`](#0x1_soul_bound_token_borrow) - [Function `are_properties_mutable`](#0x1_soul_bound_token_are_properties_mutable) - [Function `is_mutable_description`](#0x1_soul_bound_token_is_mutable_description) - [Function `is_mutable_name`](#0x1_soul_bound_token_is_mutable_name) - [Function `is_mutable_uri`](#0x1_soul_bound_token_is_mutable_uri) -- [Function `authorized_borrow`](#0x1_soul_bound_token_authorized_borrow) - [Function `set_description`](#0x1_soul_bound_token_set_description) - [Function `set_uri`](#0x1_soul_bound_token_set_uri) - [Function `add_property`](#0x1_soul_bound_token_add_property) @@ -28,8 +25,6 @@ initia_std::nft module. - [Function `remove_property`](#0x1_soul_bound_token_remove_property) - [Function `update_property`](#0x1_soul_bound_token_update_property) - [Function `update_typed_property`](#0x1_soul_bound_token_update_typed_property) -- [Function `collection_object`](#0x1_soul_bound_token_collection_object) -- [Function `borrow_collection`](#0x1_soul_bound_token_borrow_collection) - [Function `is_mutable_collection_description`](#0x1_soul_bound_token_is_mutable_collection_description) - [Function `is_mutable_collection_royalty`](#0x1_soul_bound_token_is_mutable_collection_royalty) - [Function `is_mutable_collection_uri`](#0x1_soul_bound_token_is_mutable_collection_uri) @@ -37,15 +32,14 @@ initia_std::nft module. - [Function `is_mutable_collection_nft_name`](#0x1_soul_bound_token_is_mutable_collection_nft_name) - [Function `is_mutable_collection_nft_uri`](#0x1_soul_bound_token_is_mutable_collection_nft_uri) - [Function `is_mutable_collection_nft_properties`](#0x1_soul_bound_token_is_mutable_collection_nft_properties) -- [Function `authorized_borrow_collection`](#0x1_soul_bound_token_authorized_borrow_collection) - [Function `set_collection_description`](#0x1_soul_bound_token_set_collection_description) - [Function `set_collection_royalties`](#0x1_soul_bound_token_set_collection_royalties) - [Function `set_collection_royalties_call`](#0x1_soul_bound_token_set_collection_royalties_call) - [Function `set_collection_uri`](#0x1_soul_bound_token_set_collection_uri) -
use 0x1::collection;
-use 0x1::decimal128;
+
use 0x1::bigdecimal;
+use 0x1::collection;
 use 0x1::error;
 use 0x1::nft;
 use 0x1::object;
@@ -70,8 +64,7 @@ Storage state for managing the no-code Collection.
 
 
 
-
-Fields +##### Fields
@@ -126,8 +119,6 @@ Storage state for managing the no-code Collection.
-
- ## Resource `SoulBoundToken` @@ -140,8 +131,7 @@ Storage state for managing the no-code Token. -
-Fields +##### Fields
@@ -160,8 +150,6 @@ Storage state for managing the no-code Token.
-
- ## Constants @@ -224,13 +212,12 @@ The property map being mutated is not mutable Create a new collection -
public entry fun create_collection(creator: &signer, description: string::String, max_supply: u64, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_name: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: decimal128::Decimal128)
+
public entry fun create_collection(creator: &signer, description: string::String, max_supply: u64, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_name: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation
public entry fun create_collection(
@@ -246,7 +233,7 @@ Create a new collection
     mutable_nft_name: bool,
     mutable_nft_properties: bool,
     mutable_nft_uri: bool,
-    royalty: Decimal128,
+    royalty: BigDecimal
 ) {
     create_collection_object(
         creator,
@@ -261,28 +248,25 @@ Create a new collection
         mutable_nft_name,
         mutable_nft_properties,
         mutable_nft_uri,
-        royalty,
+        royalty
     );
 }
 
-
- ## Function `create_collection_object` -
public fun create_collection_object(creator: &signer, description: string::String, max_supply: u64, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_name: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: decimal128::Decimal128): object::Object<soul_bound_token::SoulBoundTokenCollection>
+
public fun create_collection_object(creator: &signer, description: string::String, max_supply: u64, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_name: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: bigdecimal::BigDecimal): object::Object<soul_bound_token::SoulBoundTokenCollection>
 
-
-Implementation +##### Implementation
public fun create_collection_object(
@@ -298,31 +282,38 @@ Create a new collection
     mutable_nft_name: bool,
     mutable_nft_properties: bool,
     mutable_nft_uri: bool,
-    royalty: Decimal128,
+    royalty: BigDecimal
 ): Object<SoulBoundTokenCollection> {
     let creator_addr = signer::address_of(creator);
     let royalty = royalty::create(royalty, creator_addr);
-    let constructor_ref = collection::create_fixed_collection(
-        creator,
-        description,
-        max_supply,
-        name,
-        option::some(royalty),
-        uri,
-    );
+    let constructor_ref =
+        collection::create_fixed_collection(
+            creator,
+            description,
+            max_supply,
+            name,
+            option::some(royalty),
+            uri
+        );
 
     let object_signer = object::generate_signer(&constructor_ref);
-    let mutator_ref = if (mutable_description || mutable_uri) {
-        option::some(collection::generate_mutator_ref(&constructor_ref))
-    } else {
-        option::none()
-    };
-
-    let royalty_mutator_ref = if (mutable_royalty) {
-        option::some(royalty::generate_mutator_ref(object::generate_extend_ref(&constructor_ref)))
-    } else {
-        option::none()
-    };
+    let mutator_ref =
+        if (mutable_description || mutable_uri) {
+            option::some(collection::generate_mutator_ref(&constructor_ref))
+        } else {
+            option::none()
+        };
+
+    let royalty_mutator_ref =
+        if (mutable_royalty) {
+            option::some(
+                royalty::generate_mutator_ref(
+                    object::generate_extend_ref(&constructor_ref)
+                )
+            )
+        } else {
+            option::none()
+        };
 
     let soul_bound_token_collection = SoulBoundTokenCollection {
         mutator_ref,
@@ -332,7 +323,7 @@ Create a new collection
         mutable_nft_description,
         mutable_nft_name,
         mutable_nft_properties,
-        mutable_nft_uri,
+        mutable_nft_uri
     };
     move_to(&object_signer, soul_bound_token_collection);
     object::object_from_constructor_ref(&constructor_ref)
@@ -341,8 +332,6 @@ Create a new collection
 
 
 
-
- ## Function `mint` @@ -355,8 +344,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun mint(
@@ -368,7 +356,7 @@ With an existing collection, directly mint a soul bound token into the recipient
     property_keys: vector<String>,
     property_types: vector<String>,
     property_values: vector<vector<u8>>,
-    soul_bound_to: address,
+    soul_bound_to: address
 ) acquires SoulBoundTokenCollection {
     mint_soul_bound_token_object(
         creator,
@@ -386,8 +374,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `mint_soul_bound_token_object` @@ -400,8 +386,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun mint_soul_bound_token_object(
@@ -413,18 +398,19 @@ With an existing collection, directly mint a soul bound token into the recipient
     property_keys: vector<String>,
     property_types: vector<String>,
     property_values: vector<vector<u8>>,
-    soul_bound_to: address,
+    soul_bound_to: address
 ): Object<SoulBoundToken> acquires SoulBoundTokenCollection {
-    let constructor_ref = mint_internal(
-        creator,
-        collection,
-        description,
-        name,
-        uri,
-        property_keys,
-        property_types,
-        property_values,
-    );
+    let constructor_ref =
+        mint_internal(
+            creator,
+            collection,
+            description,
+            name,
+            uri,
+            property_keys,
+            property_types,
+            property_values
+        );
 
     let transfer_ref = object::generate_transfer_ref(&constructor_ref);
     let linear_transfer_ref = object::generate_linear_transfer_ref(&transfer_ref);
@@ -437,104 +423,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- - - -## Function `mint_internal` - - - -
fun mint_internal(creator: &signer, collection: string::String, description: string::String, name: string::String, uri: string::String, property_keys: vector<string::String>, property_types: vector<string::String>, property_values: vector<vector<u8>>): object::ConstructorRef
-
- - - -
-Implementation - - -
fun mint_internal(
-    creator: &signer,
-    collection: String,
-    description: String,
-    name: String,
-    uri: String,
-    property_keys: vector<String>,
-    property_types: vector<String>,
-    property_values: vector<vector<u8>>,
-): ConstructorRef acquires SoulBoundTokenCollection {
-    let constructor_ref = nft::create(
-        creator,
-        collection,
-        description,
-        name,
-        option::none(),
-        uri,
-    );
-    let s = object::generate_signer(&constructor_ref);
-
-    let object_signer = object::generate_signer(&constructor_ref);
-
-    let collection_obj = collection_object(creator, &collection);
-    let collection = borrow_collection(collection_obj);
-
-    let mutator_ref = if (
-        collection.mutable_nft_description
-            || collection.mutable_nft_name
-            || collection.mutable_nft_uri
-    ) {
-        option::some(nft::generate_mutator_ref(&constructor_ref))
-    } else {
-        option::none()
-    };
-
-    let soul_bound_token = SoulBoundToken {
-        mutator_ref,
-        property_mutator_ref: property_map::generate_mutator_ref(&s),
-    };
-    move_to(&object_signer, soul_bound_token);
-
-    let properties = property_map::prepare_input(property_keys, property_types, property_values);
-    property_map::init(&s, properties);
-
-    constructor_ref
-}
-
- - - -
- - - -## Function `borrow` - - - -
fun borrow<T: key>(nft: object::Object<T>): &soul_bound_token::SoulBoundToken
-
- - - -
-Implementation - - -
inline fun borrow<T: key>(nft: Object<T>): &SoulBoundToken {
-    let nft_address = object::object_address(nft);
-    assert!(
-        exists<SoulBoundToken>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-    borrow_global<SoulBoundToken>(nft_address)
-}
-
- - - -
- ## Function `are_properties_mutable` @@ -547,8 +435,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun are_properties_mutable<T: key>(nft: Object<T>): bool acquires SoulBoundTokenCollection {
@@ -559,8 +446,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_description` @@ -573,8 +458,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_description<T: key>(nft: Object<T>): bool acquires SoulBoundTokenCollection {
@@ -584,8 +468,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_name` @@ -598,8 +480,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_name<T: key>(nft: Object<T>): bool acquires SoulBoundTokenCollection {
@@ -609,8 +490,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_uri` @@ -623,8 +502,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_uri<T: key>(nft: Object<T>): bool acquires SoulBoundTokenCollection {
@@ -634,42 +512,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- - - -## Function `authorized_borrow` - - - -
fun authorized_borrow<T: key>(nft: object::Object<T>, creator: &signer): &soul_bound_token::SoulBoundToken
-
- - - -
-Implementation - - -
inline fun authorized_borrow<T: key>(nft: Object<T>, creator: &signer): &SoulBoundToken {
-    let nft_address = object::object_address(nft);
-    assert!(
-        exists<SoulBoundToken>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-
-    assert!(
-        nft::creator(nft) == signer::address_of(creator),
-        error::permission_denied(ENOT_CREATOR),
-    );
-    borrow_global<SoulBoundToken>(nft_address)
-}
-
- - - -
- ## Function `set_description` @@ -681,28 +523,26 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun set_description<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    description: String,
+    creator: &signer, nft: Object<T>, description: String
 ) acquires SoulBoundTokenCollection, SoulBoundToken {
     assert!(
         is_mutable_description(nft),
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
     );
     let soul_bound_token = authorized_borrow(nft, creator);
-    nft::set_description(option::borrow(&soul_bound_token.mutator_ref), description);
+    nft::set_description(
+        option::borrow(&soul_bound_token.mutator_ref),
+        description
+    );
 }
 
-
- ## Function `set_uri` @@ -714,28 +554,26 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun set_uri<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    uri: String,
+    creator: &signer, nft: Object<T>, uri: String
 ) acquires SoulBoundTokenCollection, SoulBoundToken {
     assert!(
         is_mutable_uri(nft),
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
     );
     let soul_bound_token = authorized_borrow(nft, creator);
-    nft::set_uri(option::borrow(&soul_bound_token.mutator_ref), uri);
+    nft::set_uri(
+        option::borrow(&soul_bound_token.mutator_ref),
+        uri
+    );
 }
 
-
- ## Function `add_property` @@ -747,8 +585,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun add_property<T: key>(
@@ -756,22 +593,25 @@ With an existing collection, directly mint a soul bound token into the recipient
     nft: Object<T>,
     key: String,
     type: String,
-    value: vector<u8>,
+    value: vector<u8>
 ) acquires SoulBoundTokenCollection, SoulBoundToken {
     let soul_bound_token = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
-    property_map::add(&soul_bound_token.property_mutator_ref, key, type, value);
+    property_map::add(
+        &soul_bound_token.property_mutator_ref,
+        key,
+        type,
+        value
+    );
 }
 
-
- ## Function `add_typed_property` @@ -783,30 +623,31 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun add_typed_property<T: key, V: drop>(
     creator: &signer,
     nft: Object<T>,
     key: String,
-    value: V,
+    value: V
 ) acquires SoulBoundTokenCollection, SoulBoundToken {
     let soul_bound_token = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
-    property_map::add_typed(&soul_bound_token.property_mutator_ref, key, value);
+    property_map::add_typed(
+        &soul_bound_token.property_mutator_ref,
+        key,
+        value
+    );
 }
 
-
- ## Function `remove_property` @@ -818,19 +659,16 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun remove_property<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    key: String,
+    creator: &signer, nft: Object<T>, key: String
 ) acquires SoulBoundTokenCollection, SoulBoundToken {
     let soul_bound_token = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
     property_map::remove(&soul_bound_token.property_mutator_ref, &key);
@@ -839,8 +677,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `update_property` @@ -852,8 +688,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun update_property<T: key>(
@@ -861,22 +696,25 @@ With an existing collection, directly mint a soul bound token into the recipient
     nft: Object<T>,
     key: String,
     type: String,
-    value: vector<u8>,
+    value: vector<u8>
 ) acquires SoulBoundTokenCollection, SoulBoundToken {
     let soul_bound_token = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
-    property_map::update(&soul_bound_token.property_mutator_ref, &key, type, value);
+    property_map::update(
+        &soul_bound_token.property_mutator_ref,
+        &key,
+        type,
+        value
+    );
 }
 
-
- ## Function `update_typed_property` @@ -888,84 +726,31 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun update_typed_property<T: key, V: drop>(
     creator: &signer,
     nft: Object<T>,
     key: String,
-    value: V,
+    value: V
 ) acquires SoulBoundTokenCollection, SoulBoundToken {
     let soul_bound_token = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
-    property_map::update_typed(&soul_bound_token.property_mutator_ref, &key, value);
-}
-
- - - -
- - - -## Function `collection_object` - - - -
fun collection_object(creator: &signer, name: &string::String): object::Object<soul_bound_token::SoulBoundTokenCollection>
-
- - - -
-Implementation - - -
inline fun collection_object(creator: &signer, name: &String): Object<SoulBoundTokenCollection> {
-    let collection_addr = collection::create_collection_address(signer::address_of(creator), name);
-    object::address_to_object<SoulBoundTokenCollection>(collection_addr)
-}
-
- - - -
- - - -## Function `borrow_collection` - - - -
fun borrow_collection<T: key>(nft: object::Object<T>): &soul_bound_token::SoulBoundTokenCollection
-
- - - -
-Implementation - - -
inline fun borrow_collection<T: key>(nft: Object<T>): &SoulBoundTokenCollection {
-    let collection_address = object::object_address(nft);
-    assert!(
-        exists<SoulBoundTokenCollection>(collection_address),
-        error::not_found(ECOLLECTION_DOES_NOT_EXIST),
+    property_map::update_typed(
+        &soul_bound_token.property_mutator_ref,
+        &key,
+        value
     );
-    borrow_global<SoulBoundTokenCollection>(collection_address)
 }
 
-
- ## Function `is_mutable_collection_description` @@ -977,12 +762,11 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_collection_description<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SoulBoundTokenCollection {
     borrow_collection(collection).mutable_description
 }
@@ -990,8 +774,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_collection_royalty` @@ -1003,12 +785,11 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_collection_royalty<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SoulBoundTokenCollection {
     option::is_some(&borrow_collection(collection).royalty_mutator_ref)
 }
@@ -1016,8 +797,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_collection_uri` @@ -1029,12 +808,11 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_collection_uri<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SoulBoundTokenCollection {
     borrow_collection(collection).mutable_uri
 }
@@ -1042,8 +820,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_collection_nft_description` @@ -1055,12 +831,11 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_description<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SoulBoundTokenCollection {
     borrow_collection(collection).mutable_nft_description
 }
@@ -1068,8 +843,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_collection_nft_name` @@ -1081,12 +854,11 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_name<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SoulBoundTokenCollection {
     borrow_collection(collection).mutable_nft_name
 }
@@ -1094,8 +866,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_collection_nft_uri` @@ -1107,12 +877,11 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_uri<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SoulBoundTokenCollection {
     borrow_collection(collection).mutable_nft_uri
 }
@@ -1120,8 +889,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_collection_nft_properties` @@ -1133,12 +900,11 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_properties<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SoulBoundTokenCollection {
     borrow_collection(collection).mutable_nft_properties
 }
@@ -1146,41 +912,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- - - -## Function `authorized_borrow_collection` - - - -
fun authorized_borrow_collection<T: key>(collection: object::Object<T>, creator: &signer): &soul_bound_token::SoulBoundTokenCollection
-
- - - -
-Implementation - - -
inline fun authorized_borrow_collection<T: key>(collection: Object<T>, creator: &signer): &SoulBoundTokenCollection {
-    let collection_address = object::object_address(collection);
-    assert!(
-        exists<SoulBoundTokenCollection>(collection_address),
-        error::not_found(ECOLLECTION_DOES_NOT_EXIST),
-    );
-    assert!(
-        collection::creator(collection) == signer::address_of(creator),
-        error::permission_denied(ENOT_CREATOR),
-    );
-    borrow_global<SoulBoundTokenCollection>(collection_address)
-}
-
- - - -
- ## Function `set_collection_description` @@ -1192,28 +923,27 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun set_collection_description<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    description: String,
+    creator: &signer, collection: Object<T>, description: String
 ) acquires SoulBoundTokenCollection {
-    let soul_bound_token_collection = authorized_borrow_collection(collection, creator);
+    let soul_bound_token_collection =
+        authorized_borrow_collection(collection, creator);
     assert!(
         soul_bound_token_collection.mutable_description,
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
+    );
+    collection::set_description(
+        option::borrow(&soul_bound_token_collection.mutator_ref),
+        description
     );
-    collection::set_description(option::borrow(&soul_bound_token_collection.mutator_ref), description);
 }
 
-
- ## Function `set_collection_royalties` @@ -1225,48 +955,46 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun set_collection_royalties<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    royalty: royalty::Royalty,
+    creator: &signer, collection: Object<T>, royalty: royalty::Royalty
 ) acquires SoulBoundTokenCollection {
-    let soul_bound_token_collection = authorized_borrow_collection(collection, creator);
+    let soul_bound_token_collection =
+        authorized_borrow_collection(collection, creator);
     assert!(
         option::is_some(&soul_bound_token_collection.royalty_mutator_ref),
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
+    );
+    royalty::update(
+        option::borrow(&soul_bound_token_collection.royalty_mutator_ref),
+        royalty
     );
-    royalty::update(option::borrow(&soul_bound_token_collection.royalty_mutator_ref), royalty);
 }
 
-
- ## Function `set_collection_royalties_call` -
entry fun set_collection_royalties_call<T: key>(creator: &signer, collection: object::Object<T>, royalty: decimal128::Decimal128, payee_address: address)
+
entry fun set_collection_royalties_call<T: key>(creator: &signer, collection: object::Object<T>, royalty: bigdecimal::BigDecimal, payee_address: address)
 
-
-Implementation +##### Implementation
entry fun set_collection_royalties_call<T: key>(
     creator: &signer,
     collection: Object<T>,
-    royalty: Decimal128,
-    payee_address: address,
+    royalty: BigDecimal,
+    payee_address: address
 ) acquires SoulBoundTokenCollection {
     let royalty = royalty::create(royalty, payee_address);
     set_collection_royalties(creator, collection, royalty);
@@ -1275,8 +1003,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `set_collection_uri` @@ -1288,24 +1014,21 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun set_collection_uri<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    uri: String,
+    creator: &signer, collection: Object<T>, uri: String
 ) acquires SoulBoundTokenCollection {
-    let soul_bound_token_collection = authorized_borrow_collection(collection, creator);
+    let soul_bound_token_collection =
+        authorized_borrow_collection(collection, creator);
     assert!(
         soul_bound_token_collection.mutable_uri,
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
+    );
+    collection::set_uri(
+        option::borrow(&soul_bound_token_collection.mutator_ref),
+        uri
     );
-    collection::set_uri(option::borrow(&soul_bound_token_collection.mutator_ref), uri);
 }
 
- - - -
diff --git a/initia_stdlib/doc/stableswap.md b/initia_stdlib/doc/stableswap.md index 4c5e537..e26a065 100644 --- a/initia_stdlib/doc/stableswap.md +++ b/initia_stdlib/doc/stableswap.md @@ -7,48 +7,48 @@ - [Resource `ModuleStore`](#0x1_stableswap_ModuleStore) - [Resource `Pool`](#0x1_stableswap_Pool) -- [Struct `CreatePairEvent`](#0x1_stableswap_CreatePairEvent) +- [Struct `CreatePoolEvent`](#0x1_stableswap_CreatePoolEvent) - [Struct `ProvideEvent`](#0x1_stableswap_ProvideEvent) - [Struct `WithdrawEvent`](#0x1_stableswap_WithdrawEvent) - [Struct `SwapEvent`](#0x1_stableswap_SwapEvent) +- [Struct `UpdateSwapFeeEvent`](#0x1_stableswap_UpdateSwapFeeEvent) +- [Struct `UpdateAnnEvent`](#0x1_stableswap_UpdateAnnEvent) - [Struct `Ann`](#0x1_stableswap_Ann) -- [Struct `PairResponse`](#0x1_stableswap_PairResponse) +- [Struct `PoolResponse`](#0x1_stableswap_PoolResponse) - [Constants](#@Constants_0) - [Function `get_swap_simulation`](#0x1_stableswap_get_swap_simulation) +- [Function `get_swap_simulation_given_out`](#0x1_stableswap_get_swap_simulation_given_out) - [Function `get_swap_simulation_by_denom`](#0x1_stableswap_get_swap_simulation_by_denom) -- [Function `get_pair`](#0x1_stableswap_get_pair) -- [Function `get_all_pairs`](#0x1_stableswap_get_all_pairs) -- [Function `init_module`](#0x1_stableswap_init_module) -- [Function `unpack_pair_response`](#0x1_stableswap_unpack_pair_response) -- [Function `create_pair_script`](#0x1_stableswap_create_pair_script) +- [Function `get_provide_simulation`](#0x1_stableswap_get_provide_simulation) +- [Function `get_imbalance_withdraw_simulation`](#0x1_stableswap_get_imbalance_withdraw_simulation) +- [Function `get_single_asset_withdraw_simulation`](#0x1_stableswap_get_single_asset_withdraw_simulation) +- [Function `get_pool`](#0x1_stableswap_get_pool) +- [Function `get_all_pools`](#0x1_stableswap_get_all_pools) +- [Function `spot_price`](#0x1_stableswap_spot_price) +- [Function `unpack_pool_response`](#0x1_stableswap_unpack_pool_response) +- [Function `create_pool_script`](#0x1_stableswap_create_pool_script) - [Function `update_swap_fee_rate`](#0x1_stableswap_update_swap_fee_rate) - [Function `update_ann`](#0x1_stableswap_update_ann) - [Function `provide_liquidity_script`](#0x1_stableswap_provide_liquidity_script) - [Function `withdraw_liquidity_script`](#0x1_stableswap_withdraw_liquidity_script) +- [Function `imbalance_withdraw_liquidity_script`](#0x1_stableswap_imbalance_withdraw_liquidity_script) +- [Function `single_asset_withdraw_liquidity_script`](#0x1_stableswap_single_asset_withdraw_liquidity_script) - [Function `swap_script`](#0x1_stableswap_swap_script) -- [Function `create_pair`](#0x1_stableswap_create_pair) +- [Function `create_pool`](#0x1_stableswap_create_pool) - [Function `provide_liquidity`](#0x1_stableswap_provide_liquidity) - [Function `withdraw_liquidity`](#0x1_stableswap_withdraw_liquidity) +- [Function `single_asset_withdraw_liquidity`](#0x1_stableswap_single_asset_withdraw_liquidity) - [Function `swap`](#0x1_stableswap_swap) - [Function `pool_info`](#0x1_stableswap_pool_info) -- [Function `borrow_pool`](#0x1_stableswap_borrow_pool) -- [Function `borrow_pool_mut`](#0x1_stableswap_borrow_pool_mut) -- [Function `get_current_ann`](#0x1_stableswap_get_current_ann) -- [Function `check_coin_metadata`](#0x1_stableswap_check_coin_metadata) -- [Function `get_pool_amounts`](#0x1_stableswap_get_pool_amounts) -- [Function `get_amounts`](#0x1_stableswap_get_amounts) -- [Function `get_coin_addresses`](#0x1_stableswap_get_coin_addresses) -- [Function `get_d`](#0x1_stableswap_get_d) -- [Function `get_y`](#0x1_stableswap_get_y) +- [Function `single_asset_withdraw_simulation`](#0x1_stableswap_single_asset_withdraw_simulation) +- [Function `imbalance_withdraw_simulation`](#0x1_stableswap_imbalance_withdraw_simulation) - [Function `swap_simulation`](#0x1_stableswap_swap_simulation) -- [Function `mul_div_u64`](#0x1_stableswap_mul_div_u64) -- [Function `mul_div_u128`](#0x1_stableswap_mul_div_u128) -- [Function `check_chain_permission`](#0x1_stableswap_check_chain_permission) +- [Function `provide_simulation`](#0x1_stableswap_provide_simulation) -
use 0x1::block;
+
use 0x1::bigdecimal;
+use 0x1::block;
 use 0x1::coin;
-use 0x1::decimal128;
 use 0x1::error;
 use 0x1::event;
 use 0x1::fungible_asset;
@@ -74,19 +74,18 @@
 
 
 
-
-Fields +##### Fields
-pairs: table::Table<address, bool> +pools: table::Table<address, bool>
-pair_count: u64 +pool_count: u64
@@ -94,8 +93,6 @@
-
- ## Resource `Pool` @@ -107,8 +104,7 @@ -
-Fields +##### Fields
@@ -125,7 +121,7 @@ ANN
-swap_fee_rate: decimal128::Decimal128 +swap_fee_rate: bigdecimal::BigDecimal
swap fee @@ -157,22 +153,19 @@
-
- - + -## Struct `CreatePairEvent` +## Struct `CreatePoolEvent`
#[event]
-struct CreatePairEvent has drop, store
+struct CreatePoolEvent has drop, store
 
-
-Fields +##### Fields
@@ -195,7 +188,7 @@
-swap_fee_rate: decimal128::Decimal128 +swap_fee_rate: bigdecimal::BigDecimal
@@ -203,8 +196,6 @@
-
- ## Struct `ProvideEvent` @@ -217,8 +208,7 @@ -
-Fields +##### Fields
@@ -233,6 +223,12 @@
+
+
+fee_amounts: vector<u64> +
+
+
liquidity_token: address @@ -249,8 +245,6 @@
-
- ## Struct `WithdrawEvent` @@ -263,8 +257,7 @@ -
-Fields +##### Fields
@@ -279,6 +272,12 @@
+
+
+fee_amounts: vector<u64> +
+
+
liquidity_token: address @@ -295,8 +294,6 @@
-
- ## Struct `SwapEvent` @@ -309,8 +306,7 @@ -
-Fields +##### Fields
@@ -353,7 +349,67 @@
-
+ + +## Struct `UpdateSwapFeeEvent` + + + +
#[event]
+struct UpdateSwapFeeEvent has drop, store
+
+ + + +##### Fields + + +
+
+liquidity_token: address +
+
+ +
+
+swap_fee_rate: bigdecimal::BigDecimal +
+
+ +
+
+ + + + +## Struct `UpdateAnnEvent` + + + +
#[event]
+struct UpdateAnnEvent has drop, store
+
+ + + +##### Fields + + +
+
+liquidity_token: address +
+
+ +
+
+ann: stableswap::Ann +
+
+ +
+
+ @@ -366,8 +422,7 @@ -
-Fields +##### Fields
@@ -398,21 +453,18 @@
-
- - + -## Struct `PairResponse` +## Struct `PoolResponse` -
struct PairResponse has copy, drop, store
+
struct PoolResponse has copy, drop, store
 
-
-Fields +##### Fields
@@ -441,7 +493,7 @@
-swap_fee_rate: decimal128::Decimal128 +swap_fee_rate: bigdecimal::BigDecimal
@@ -449,13 +501,21 @@
-
- ## Constants + + +Only chain can execute. + + +
const EUNAUTHORIZED: u64 = 7;
+
+ + + Wrong coin type given @@ -575,16 +635,6 @@ All start_after must be provided or not - - -Only chain can execute. - - -
const EUNAUTHORIZED: u64 = 7;
-
- - - end time must be larger than start time @@ -605,29 +655,29 @@ Can not withdraw zero liquidity - + -
const MAX_FEE_RATE: u128 = 10000000000000000;
+
const MAX_LIMIT: u8 = 30;
 
- + -
const MAX_LIMIT: u8 = 30;
+
const A_PRECISION: u256 = 100;
 
- + -
const A_PRECISION: u256 = 100;
+
const EMAX_LIQUIDITY: u64 = 21;
 
@@ -649,27 +699,28 @@ Return swap simulation result
#[view]
-public fun get_swap_simulation(pair: object::Object<stableswap::Pool>, offer_metadata: object::Object<fungible_asset::Metadata>, return_metadata: object::Object<fungible_asset::Metadata>, offer_amount: u64): u64
+public fun get_swap_simulation(pool_obj: object::Object<stableswap::Pool>, offer_metadata: object::Object<fungible_asset::Metadata>, return_metadata: object::Object<fungible_asset::Metadata>, offer_amount: u64): u64
 
-
-Implementation +##### Implementation
public fun get_swap_simulation(
-    pair: Object<Pool>,
+    pool_obj: Object<Pool>,
     offer_metadata: Object<Metadata>,
     return_metadata: Object<Metadata>,
-    offer_amount: u64,
+    offer_amount: u64
 ): u64 acquires Pool {
-    let (return_amount, fee_amount) = swap_simulation(
-        pair,
-        offer_metadata,
-        return_metadata,
-        offer_amount,
-    );
+    let (return_amount, fee_amount) =
+        swap_simulation(
+            pool_obj,
+            offer_metadata,
+            return_metadata,
+            offer_amount,
+            true
+        );
 
     return_amount - fee_amount
 }
@@ -677,7 +728,42 @@ Return swap simulation result
 
 
 
-
+ + +## Function `get_swap_simulation_given_out` + +Return swap simulation result + + +
#[view]
+public fun get_swap_simulation_given_out(pool_obj: object::Object<stableswap::Pool>, offer_metadata: object::Object<fungible_asset::Metadata>, return_metadata: object::Object<fungible_asset::Metadata>, return_amount: u64): u64
+
+ + + +##### Implementation + + +
public fun get_swap_simulation_given_out(
+    pool_obj: Object<Pool>,
+    offer_metadata: Object<Metadata>,
+    return_metadata: Object<Metadata>,
+    return_amount: u64
+): u64 acquires Pool {
+    let (offer_amount, _) =
+        swap_simulation(
+            pool_obj,
+            offer_metadata,
+            return_metadata,
+            return_amount,
+            false
+        );
+
+    offer_amount
+}
+
+ + @@ -686,54 +772,151 @@ Return swap simulation result
#[view]
-public fun get_swap_simulation_by_denom(pair: object::Object<stableswap::Pool>, offer_denom: string::String, return_denom: string::String, offer_amount: u64): u64
+public fun get_swap_simulation_by_denom(pool_obj: object::Object<stableswap::Pool>, offer_denom: string::String, return_denom: string::String, offer_amount: u64): u64
 
-
-Implementation +##### Implementation
public fun get_swap_simulation_by_denom(
-    pair: Object<Pool>,
+    pool_obj: Object<Pool>,
     offer_denom: String,
     return_denom: String,
-    offer_amount: u64,
+    offer_amount: u64
 ): u64 acquires Pool {
     let offer_metadata = coin::denom_to_metadata(offer_denom);
     let return_metadata = coin::denom_to_metadata(return_denom);
-    get_swap_simulation(pair, offer_metadata, return_metadata, offer_amount)
+    get_swap_simulation(
+        pool_obj,
+        offer_metadata,
+        return_metadata,
+        offer_amount
+    )
+}
+
+ + + + + +## Function `get_provide_simulation` + + + +
#[view]
+public fun get_provide_simulation(pool_obj: object::Object<stableswap::Pool>, coin_amounts: vector<u64>): u64
+
+ + + +##### Implementation + + +
public fun get_provide_simulation(
+    pool_obj: Object<Pool>, coin_amounts: vector<u64>
+): u64 acquires Pool {
+    let (liquidity_amount, _) = provide_simulation(pool_obj, coin_amounts);
+    liquidity_amount
+}
+
+ + + + + +## Function `get_imbalance_withdraw_simulation` + + + +
#[view]
+public fun get_imbalance_withdraw_simulation(pool_obj: object::Object<stableswap::Pool>, coin_amounts: vector<u64>): u64
+
+ + + +##### Implementation + + +
public fun get_imbalance_withdraw_simulation(
+    pool_obj: Object<Pool>, coin_amounts: vector<u64>
+): u64 acquires Pool {
+    let (liquidity_amount, _) =
+        imbalance_withdraw_simulation(
+            pool_obj,
+            coin_amounts,
+            option::none()
+        );
+    liquidity_amount
 }
 
-
+ + +## Function `get_single_asset_withdraw_simulation` + + + +
#[view]
+public fun get_single_asset_withdraw_simulation(pool_obj: object::Object<stableswap::Pool>, return_coin_metadata: object::Object<fungible_asset::Metadata>, liquidity_amount: u64): u64
+
+ + + +##### Implementation + + +
public fun get_single_asset_withdraw_simulation(
+    pool_obj: Object<Pool>,
+    return_coin_metadata: Object<Metadata>,
+    liquidity_amount: u64
+): u64 acquires Pool {
+    let pool = borrow_pool(pool_obj);
+
+    // get return index
+    let (found, return_index) = vector::index_of(
+        &pool.coin_metadata, &return_coin_metadata
+    );
+    assert!(found, error::invalid_argument(ECOIN_TYPE));
+
+    let (liquidity_amount, _) =
+        single_asset_withdraw_simulation(
+            pool_obj,
+            liquidity_amount,
+            return_index
+        );
+    liquidity_amount
+}
+
- -## Function `get_pair` + + + +## Function `get_pool`
#[view]
-public fun get_pair(pool: object::Object<stableswap::Pool>): stableswap::PairResponse
+public fun get_pool(pool: object::Object<stableswap::Pool>): stableswap::PoolResponse
 
-
-Implementation +##### Implementation -
public fun get_pair(
-    pool: Object<Pool>,
-): PairResponse acquires Pool {
+
public fun get_pool(pool: Object<Pool>): PoolResponse acquires Pool {
     let (coin_metadata, coin_balances, current_ann, swap_fee_rate) = pool_info(pool);
-    let coin_denoms = vector::map(coin_metadata, |metadata| coin::metadata_to_denom(metadata));
+    let coin_denoms = vector::map(
+        coin_metadata,
+        |metadata| coin::metadata_to_denom(metadata)
+    );
 
-    PairResponse {
+    PoolResponse {
         coin_metadata,
         coin_denoms,
         coin_balances,
@@ -745,28 +928,24 @@ Return swap simulation result
 
 
 
-
+ - - -## Function `get_all_pairs` +## Function `get_all_pools`
#[view]
-public fun get_all_pairs(start_after: option::Option<address>, limit: u8): vector<stableswap::PairResponse>
+public fun get_all_pools(start_after: option::Option<address>, limit: u8): vector<stableswap::PoolResponse>
 
-
-Implementation +##### Implementation -
public fun get_all_pairs(
-    start_after: Option<address>,
-    limit: u8,
-): vector<PairResponse> acquires ModuleStore, Pool {
+
public fun get_all_pools(
+    start_after: Option<address>, limit: u8
+): vector<PoolResponse> acquires ModuleStore, Pool {
     if (limit > MAX_LIMIT) {
         limit = MAX_LIMIT;
     };
@@ -774,17 +953,18 @@ Return swap simulation result
     let module_store = borrow_global<ModuleStore>(@initia_std);
 
     let res = vector[];
-    let pairs_iter = table::iter(
-        &module_store.pairs,
+    let pools_iter = table::iter(
+        &module_store.pools,
         option::none(),
         start_after,
-        2,
+        2
     );
 
-    while (vector::length(&res) < (limit as u64) && table::prepare<address, bool>(&mut pairs_iter)) {
-        let (key, _) = table::next<address, bool>(&mut pairs_iter);
-        let pair_response = get_pair(object::address_to_object<Pool>(key));
-        vector::push_back(&mut res, pair_response)
+    while (vector::length(&res) < (limit as u64)
+        && table::prepare<address, bool>(pools_iter)) {
+        let (key, _) = table::next<address, bool>(pools_iter);
+        let pool_response = get_pool(object::address_to_object<Pool>(key));
+        vector::push_back(&mut res, pool_response)
     };
 
     res
@@ -793,85 +973,124 @@ Return swap simulation result
 
 
 
-
- - + -## Function `init_module` +## Function `spot_price` -
fun init_module(chain: &signer)
+
#[view]
+public fun spot_price(pool_obj: object::Object<stableswap::Pool>, base_metadata: object::Object<fungible_asset::Metadata>, quote_metadata: object::Object<fungible_asset::Metadata>): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation + +
public fun spot_price(
+    pool_obj: Object<Pool>,
+    base_metadata: Object<Metadata>,
+    quote_metadata: Object<Metadata>
+): BigDecimal acquires Pool {
+    let pool = borrow_pool(pool_obj);
+    let ann = get_current_ann(&pool.ann);
+    let pool_addr = object::object_address(&pool_obj);
+    let amounts = get_pool_amounts(pool_addr, pool.coin_metadata);
+    let d = get_d(amounts, ann);
+    let swap_amount = d / 1000;
+
+    if (swap_amount < 1000000) {
+        let len = vector::length(&amounts);
+        let i = 0;
+        while (i < len) {
+            let amount = vector::borrow_mut(&mut amounts, i);
+            *amount = *amount * 1000000;
+            i = i + 1;
+        };
+
+        swap_amount = swap_amount * 1000000;
+    };
+
+    let (base_return_amount, _) =
+        swap_simulation_with_given_amounts(
+            pool_obj,
+            amounts,
+            quote_metadata,
+            base_metadata,
+            swap_amount,
+            true
+        );
+    let (quote_return_amount, _) =
+        swap_simulation_with_given_amounts(
+            pool_obj,
+            amounts,
+            base_metadata,
+            quote_metadata,
+            swap_amount,
+            true
+        );
 
-
fun init_module(chain: &signer) {
-    move_to(chain, ModuleStore { pairs: table::new(), pair_count: 0 })
+    bigdecimal::from_ratio_u64(
+        quote_return_amount + swap_amount,
+        base_return_amount + swap_amount
+    )
 }
 
-
- - + -## Function `unpack_pair_response` +## Function `unpack_pool_response` -
public fun unpack_pair_response(pair_response: &stableswap::PairResponse): (vector<object::Object<fungible_asset::Metadata>>, vector<string::String>, vector<u64>, u64, decimal128::Decimal128)
+
public fun unpack_pool_response(pool_response: &stableswap::PoolResponse): (vector<object::Object<fungible_asset::Metadata>>, vector<string::String>, vector<u64>, u64, bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation -
public fun unpack_pair_response(pair_response: &PairResponse): (vector<Object<Metadata>>, vector<String>, vector<u64>, u64, Decimal128) {
+
public fun unpack_pool_response(
+    pool_response: &PoolResponse
+): (vector<Object<Metadata>>, vector<String>, vector<u64>, u64, BigDecimal) {
     (
-        pair_response.coin_metadata,
-        pair_response.coin_denoms,
-        pair_response.coin_balances,
-        pair_response.current_ann,
-        pair_response.swap_fee_rate,
+        pool_response.coin_metadata,
+        pool_response.coin_denoms,
+        pool_response.coin_balances,
+        pool_response.current_ann,
+        pool_response.swap_fee_rate
     )
 }
 
-
+ - +## Function `create_pool_script` -## Function `create_pair_script` - -
public entry fun create_pair_script(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: decimal128::Decimal128, coin_metadata: vector<object::Object<fungible_asset::Metadata>>, coin_amounts: vector<u64>, ann: u64)
+
public entry fun create_pool_script(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: bigdecimal::BigDecimal, coin_metadata: vector<object::Object<fungible_asset::Metadata>>, coin_amounts: vector<u64>, ann: u64)
 
-
-Implementation +##### Implementation -
public entry fun create_pair_script(
+
public entry fun create_pool_script(
     creator: &signer,
     name: String,
     symbol: String,
-    swap_fee_rate: Decimal128,
+    swap_fee_rate: BigDecimal,
     coin_metadata: vector<Object<Metadata>>,
     coin_amounts: vector<u64>,
-    ann: u64,
+    ann: u64
 ) acquires Pool, ModuleStore {
     let coins: vector<FungibleAsset> = vector[];
     let i = 0;
@@ -879,134 +1098,162 @@ Return swap simulation result
     while (i < n) {
         let metadata = *vector::borrow(&coin_metadata, i);
         let amount = *vector::borrow(&coin_amounts, i);
-        vector::push_back(&mut coins, primary_fungible_store::withdraw(creator, metadata, amount));
+        vector::push_back(
+            &mut coins,
+            primary_fungible_store::withdraw(creator, metadata, amount)
+        );
         i = i + 1;
     };
 
-    let liquidity_token = create_pair(creator, name, symbol, swap_fee_rate, coins, ann);
+    let liquidity_token = create_pool(
+        creator,
+        name,
+        symbol,
+        swap_fee_rate,
+        coins,
+        ann
+    );
     primary_fungible_store::deposit(signer::address_of(creator), liquidity_token);
 }
 
-
- ## Function `update_swap_fee_rate` -
public entry fun update_swap_fee_rate(account: &signer, pair: object::Object<stableswap::Pool>, new_swap_fee_rate: decimal128::Decimal128)
+
public entry fun update_swap_fee_rate(account: &signer, pool_obj: object::Object<stableswap::Pool>, new_swap_fee_rate: bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation -
public entry fun update_swap_fee_rate(account: &signer, pair: Object<Pool>, new_swap_fee_rate: Decimal128) acquires Pool {
+
public entry fun update_swap_fee_rate(
+    account: &signer, pool_obj: Object<Pool>, new_swap_fee_rate: BigDecimal
+) acquires Pool {
     check_chain_permission(account);
-    let pool = borrow_pool_mut(pair);
+    let pool = borrow_pool_mut(pool_obj);
     pool.swap_fee_rate = new_swap_fee_rate;
+
+    event::emit(
+        UpdateSwapFeeEvent {
+            liquidity_token: object::object_address(&pool_obj),
+            swap_fee_rate: new_swap_fee_rate
+        }
+    )
 }
 
-
- ## Function `update_ann` -
public entry fun update_ann(account: &signer, pair: object::Object<stableswap::Pool>, ann_after: u64, timestamp_after: u64)
+
public entry fun update_ann(account: &signer, pool_obj: object::Object<stableswap::Pool>, ann_after: u64, timestamp_after: u64)
 
-
-Implementation +##### Implementation -
public entry fun update_ann(account: &signer, pair: Object<Pool>, ann_after: u64, timestamp_after: u64) acquires Pool {
+
public entry fun update_ann(
+    account: &signer,
+    pool_obj: Object<Pool>,
+    ann_after: u64,
+    timestamp_after: u64
+) acquires Pool {
     check_chain_permission(account);
-    let (_, timestamp) = block::get_block_info();
-    let pool = borrow_pool_mut(pair);
+    let (_, timestamp) = block::get_block_info();
+    let pool = borrow_pool_mut(pool_obj);
     pool.ann.ann_before = get_current_ann(&pool.ann);
-    pool.ann.timestamp_before = timestamp;
+    pool.ann.timestamp_before = timestamp;
     pool.ann.ann_after = ann_after;
     pool.ann.timestamp_after = timestamp_after;
+
+    event::emit(
+        UpdateAnnEvent {
+            liquidity_token: object::object_address(&pool_obj),
+            ann: pool.ann
+        }
+    )
 }
 
-
- ## Function `provide_liquidity_script` -
public entry fun provide_liquidity_script(account: &signer, pair: object::Object<stableswap::Pool>, coin_amounts: vector<u64>, min_liquidity: option::Option<u64>)
+
public entry fun provide_liquidity_script(account: &signer, pool_obj: object::Object<stableswap::Pool>, coin_amounts: vector<u64>, min_liquidity: option::Option<u64>)
 
-
-Implementation +##### Implementation
public entry fun provide_liquidity_script(
     account: &signer,
-    pair: Object<Pool>,
+    pool_obj: Object<Pool>,
     coin_amounts: vector<u64>,
-    min_liquidity: Option<u64>,
+    min_liquidity: Option<u64>
 ) acquires Pool {
     let coins: vector<FungibleAsset> = vector[];
-    let pool = borrow_pool(pair);
+    let pool = borrow_pool(pool_obj);
 
     let i = 0;
     let n = vector::length(&coin_amounts);
     while (i < n) {
         let metadata = *vector::borrow(&pool.coin_metadata, i);
         let amount = *vector::borrow(&coin_amounts, i);
-        vector::push_back(&mut coins, primary_fungible_store::withdraw(account, metadata, amount));
+        vector::push_back(
+            &mut coins,
+            primary_fungible_store::withdraw(account, metadata, amount)
+        );
         i = i + 1;
     };
 
-    let liquidity_token = provide_liquidity(pair, coins, min_liquidity);
+    let liquidity_token = provide_liquidity(pool_obj, coins, min_liquidity);
     primary_fungible_store::deposit(signer::address_of(account), liquidity_token);
 }
 
-
- ## Function `withdraw_liquidity_script` -
public entry fun withdraw_liquidity_script(account: &signer, pair: object::Object<stableswap::Pool>, liquidity_amount: u64, min_return_amounts: vector<option::Option<u64>>)
+
public entry fun withdraw_liquidity_script(account: &signer, pool_obj: object::Object<stableswap::Pool>, liquidity_amount: u64, min_return_amounts: vector<option::Option<u64>>)
 
-
-Implementation +##### Implementation -
public entry fun withdraw_liquidity_script(account: &signer, pair: Object<Pool>, liquidity_amount: u64, min_return_amounts: vector<Option<u64>>) acquires Pool {
-    let liquidity_token = primary_fungible_store::withdraw(account, pair, liquidity_amount);
+
public entry fun withdraw_liquidity_script(
+    account: &signer,
+    pool_obj: Object<Pool>,
+    liquidity_amount: u64,
+    min_return_amounts: vector<Option<u64>>
+) acquires Pool {
+    let liquidity_token =
+        primary_fungible_store::withdraw(account, pool_obj, liquidity_amount);
     let coins = withdraw_liquidity(liquidity_token, min_return_amounts);
 
     let i = 0;
@@ -1023,84 +1270,192 @@ Return swap simulation result
 
 
 
-
- - + -## Function `swap_script` +## Function `imbalance_withdraw_liquidity_script` -
public entry fun swap_script(account: &signer, pair: object::Object<stableswap::Pool>, offer_coin_metadata: object::Object<fungible_asset::Metadata>, return_coin_metadata: object::Object<fungible_asset::Metadata>, offer_amount: u64, min_return_amount: option::Option<u64>)
+
public entry fun imbalance_withdraw_liquidity_script(account: &signer, pool_obj: object::Object<stableswap::Pool>, coin_amounts: vector<u64>, max_liquidity: option::Option<u64>)
 
-
-Implementation +##### Implementation -
public entry fun swap_script(
+
public entry fun imbalance_withdraw_liquidity_script(
     account: &signer,
-    pair: Object<Pool>,
-    offer_coin_metadata: Object<Metadata>,
-    return_coin_metadata: Object<Metadata>,
-    offer_amount: u64,
-    min_return_amount: Option<u64>,
-) acquires Pool{
-    let offer_coin = primary_fungible_store::withdraw(account, offer_coin_metadata, offer_amount);
-    let return_coin = swap(pair, offer_coin, return_coin_metadata, min_return_amount);
-    primary_fungible_store::deposit(signer::address_of(account), return_coin);
+    pool_obj: Object<Pool>,
+    coin_amounts: vector<u64>,
+    max_liquidity: Option<u64>
+) acquires Pool {
+    let (liquidity_amount, fee_amounts) =
+        imbalance_withdraw_simulation(
+            pool_obj,
+            coin_amounts,
+            max_liquidity
+        );
+    let liquidity_token =
+        primary_fungible_store::withdraw(account, pool_obj, liquidity_amount);
+    let pool = borrow_pool(pool_obj);
+    let pool_signer = object::generate_signer_for_extending(&pool.extend_ref);
+    coin::burn(&pool.burn_cap, liquidity_token);
+
+    let n = vector::length(&pool.coin_metadata);
+
+    let i = 0;
+    while (i < n) {
+        let coin_metadata = *vector::borrow(&pool.coin_metadata, i);
+        let amount = *vector::borrow(&mut coin_amounts, i);
+        let coin =
+            primary_fungible_store::withdraw(&pool_signer, coin_metadata, amount);
+        primary_fungible_store::deposit(signer::address_of(account), coin);
+        i = i + 1;
+    };
+
+    event::emit<WithdrawEvent>(
+        WithdrawEvent {
+            coins: get_coin_addresses(pool.coin_metadata),
+            coin_amounts,
+            fee_amounts,
+            liquidity_token: object::object_address(&pool_obj),
+            liquidity: liquidity_amount
+        }
+    );
 }
 
-
+ - +## Function `single_asset_withdraw_liquidity_script` -## Function `create_pair` - -
public fun create_pair(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: decimal128::Decimal128, coins: vector<fungible_asset::FungibleAsset>, ann: u64): fungible_asset::FungibleAsset
+
public entry fun single_asset_withdraw_liquidity_script(account: &signer, pool_obj: object::Object<stableswap::Pool>, return_coin_metadata: object::Object<fungible_asset::Metadata>, liquidity_amount: u64, min_return_amount: option::Option<u64>)
 
-
-Implementation +##### Implementation -
public fun create_pair(
-    creator: &signer,
-    name: String,
-    symbol: String,
-    swap_fee_rate: Decimal128,
+
public entry fun single_asset_withdraw_liquidity_script(
+    account: &signer,
+    pool_obj: Object<Pool>,
+    return_coin_metadata: Object<Metadata>,
+    liquidity_amount: u64,
+    min_return_amount: Option<u64>
+) acquires Pool {
+    let liquidity_token =
+        primary_fungible_store::withdraw(account, pool_obj, liquidity_amount);
+    let return_coin =
+        single_asset_withdraw_liquidity(
+            liquidity_token,
+            return_coin_metadata,
+            min_return_amount
+        );
+    primary_fungible_store::deposit(signer::address_of(account), return_coin);
+}
+
+ + + + + +## Function `swap_script` + + + +
public entry fun swap_script(account: &signer, pool_obj: object::Object<stableswap::Pool>, offer_coin_metadata: object::Object<fungible_asset::Metadata>, return_coin_metadata: object::Object<fungible_asset::Metadata>, offer_amount: u64, min_return_amount: option::Option<u64>)
+
+ + + +##### Implementation + + +
public entry fun swap_script(
+    account: &signer,
+    pool_obj: Object<Pool>,
+    offer_coin_metadata: Object<Metadata>,
+    return_coin_metadata: Object<Metadata>,
+    offer_amount: u64,
+    min_return_amount: Option<u64>
+) acquires Pool {
+    let offer_coin =
+        primary_fungible_store::withdraw(
+            account,
+            offer_coin_metadata,
+            offer_amount
+        );
+    let return_coin =
+        swap(
+            pool_obj,
+            offer_coin,
+            return_coin_metadata,
+            min_return_amount
+        );
+    primary_fungible_store::deposit(signer::address_of(account), return_coin);
+}
+
+ + + + + +## Function `create_pool` + + + +
public fun create_pool(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: bigdecimal::BigDecimal, coins: vector<fungible_asset::FungibleAsset>, ann: u64): fungible_asset::FungibleAsset
+
+ + + +##### Implementation + + +
public fun create_pool(
+    creator: &signer,
+    name: String,
+    symbol: String,
+    swap_fee_rate: BigDecimal,
     coins: vector<FungibleAsset>,
-    ann: u64,
+    ann: u64
 ): FungibleAsset acquires Pool, ModuleStore {
-    let (_, timestamp) = block::get_block_info();
-    let (mint_cap, burn_cap, freeze_cap, extend_ref) = coin::initialize_and_generate_extend_ref (
-        creator,
-        option::none(),
-        name,
-        symbol,
-        6,
-        string::utf8(b""),
-        string::utf8(b""),
+    assert!(
+        vector::length(&coins) >= 2,
+        error::invalid_argument(EN_COINS)
     );
+    let (_, timestamp) = block::get_block_info();
+    let (mint_cap, burn_cap, freeze_cap, extend_ref) =
+        coin::initialize_and_generate_extend_ref(
+            creator,
+            option::none(),
+            name,
+            symbol,
+            6,
+            string::utf8(b""),
+            string::utf8(b"")
+        );
 
     let coin_metadata: vector<Object<Metadata>> = vector[];
     let len = vector::length(&coins);
     let i = 0;
     while (i < len) {
         let j = i + 1;
-        let coin_metadata_i = fungible_asset::metadata_from_asset(vector::borrow(&coins, i));
+        let coin_metadata_i =
+            fungible_asset::metadata_from_asset(vector::borrow(&coins, i));
         while (j < len) {
-            let coin_metadata_j = fungible_asset::metadata_from_asset(vector::borrow(&coins, j));
-            assert!(coin_metadata_i != coin_metadata_j, error::invalid_argument(ESAME_COIN_TYPE));
+            let coin_metadata_j =
+                fungible_asset::metadata_from_asset(vector::borrow(&coins, j));
+            assert!(
+                coin_metadata_i != coin_metadata_j,
+                error::invalid_argument(ESAME_COIN_TYPE)
+            );
             j = j + 1;
         };
         vector::push_back(&mut coin_metadata, coin_metadata_i);
@@ -1108,57 +1463,58 @@ Return swap simulation result
     };
 
     assert!(
-        decimal128::val(&swap_fee_rate) < MAX_FEE_RATE,
+        bigdecimal::le(swap_fee_rate, max_fee_rate()),
         error::invalid_argument(EOUT_OF_SWAP_FEE_RATE_RANGE)
     );
 
-    let pair_signer = &object::generate_signer_for_extending(&extend_ref);
-    let pair_address = signer::address_of(pair_signer);
-    // transfer pair object's ownership to initia_std
-    object::transfer_raw(creator, pair_address, @initia_std);
+    let pool_signer = &object::generate_signer_for_extending(&extend_ref);
+    let pool_address = signer::address_of(pool_signer);
+    // transfer pool object's ownership to initia_std
+    object::transfer_raw(creator, pool_address, @initia_std);
 
     move_to(
-        pair_signer,
+        pool_signer,
         Pool {
             extend_ref,
             ann: Ann {
                 ann_before: ann,
                 ann_after: ann,
-                timestamp_before: timestamp,
-                timestamp_after: timestamp,
+                timestamp_before: timestamp,
+                timestamp_after: timestamp
             },
             swap_fee_rate,
             coin_metadata,
             burn_cap,
             freeze_cap,
-            mint_cap,
+            mint_cap
         }
     );
 
-    let liquidity_token = provide_liquidity(
-        object::address_to_object<Pool>(pair_address),
-        coins,
-        option::none(),
-    );
+    let liquidity_token =
+        provide_liquidity(
+            object::address_to_object<Pool>(pool_address),
+            coins,
+            option::none()
+        );
 
     // update module store
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    module_store.pair_count = module_store.pair_count + 1;
+    module_store.pool_count = module_store.pool_count + 1;
 
     table::add(
-        &mut module_store.pairs,
-        pair_address,
-        true,
+        &mut module_store.pools,
+        pool_address,
+        true
     );
 
-    // emit create pair event
-    event::emit<CreatePairEvent>(
-        CreatePairEvent {
+    // emit create pool event
+    event::emit<CreatePoolEvent>(
+        CreatePoolEvent {
             coins: get_coin_addresses(coin_metadata),
-            liquidity_token: pair_address,
+            liquidity_token: pool_address,
             ann,
-            swap_fee_rate,
-        },
+            swap_fee_rate
+        }
     );
 
     return liquidity_token
@@ -1167,97 +1523,55 @@ Return swap simulation result
 
 
 
-
- ## Function `provide_liquidity` -
public fun provide_liquidity(pair: object::Object<stableswap::Pool>, coins: vector<fungible_asset::FungibleAsset>, min_liquidity: option::Option<u64>): fungible_asset::FungibleAsset
+
public fun provide_liquidity(pool_obj: object::Object<stableswap::Pool>, coins: vector<fungible_asset::FungibleAsset>, min_liquidity: option::Option<u64>): fungible_asset::FungibleAsset
 
-
-Implementation +##### Implementation -
public fun provide_liquidity(pair: Object<Pool>, coins: vector<FungibleAsset>, min_liquidity: Option<u64>): FungibleAsset acquires Pool {
-    let pool = borrow_pool(pair);
-    let pair_addr = object::object_address(pair);
+
public fun provide_liquidity(
+    pool_obj: Object<Pool>, coins: vector<FungibleAsset>, min_liquidity: Option<u64>
+): FungibleAsset acquires Pool {
+    let pool = borrow_pool(pool_obj);
+    // check before simaultion
     let n = check_coin_metadata(&pool.coin_metadata, &coins);
-    let ann = get_current_ann(&pool.ann);
-
-    let pool_amounts_before = get_pool_amounts(pair_addr, pool.coin_metadata);
-    let d_before = get_d(pool_amounts_before, ann);
-    let total_supply = option::extract(&mut fungible_asset::supply(pair));
     let amounts = get_amounts(&coins);
-
-    // pool amounts before adjust fee
-    let pool_amounts_after: vector<u64> = vector[];
-    let i = 0;
-    while (i < n) {
-        let pool_amount = *vector::borrow(&pool_amounts_before, i);
-        let offer_amount = *vector::borrow(&amounts, i);
-        if (total_supply == 0) {
-            assert!(offer_amount > 0, error::invalid_argument(EZERO_LIQUIDITY));
-        };
-        vector::push_back(&mut pool_amounts_after, pool_amount + offer_amount);
-        i = i + 1;
-    };
-
-    let d_ideal = get_d(pool_amounts_after, ann);
-
-    // calc fees
-    let liquidity_amount = if (total_supply > 0) {
-        let provide_fee_rate = decimal128::new(
-            decimal128::val(&pool.swap_fee_rate) * (n as u128) / (4 * (n - 1) as u128)
-        );
-        i = 0;
-        while (i < n) {
-            let pool_amount_before = *vector::borrow(&pool_amounts_before, i);
-            let pool_amount_after = vector::borrow_mut(&mut pool_amounts_after, i);
-            let ideal_balance = mul_div_u64(d_ideal, pool_amount_before, d_before);
-            let diff = if (ideal_balance > *pool_amount_after) {
-                ideal_balance - *pool_amount_after
-            } else {
-                *pool_amount_after - ideal_balance
-            };
-            let fee = decimal128::mul_u64(&provide_fee_rate, diff);
-            *pool_amount_after = *pool_amount_after - fee;
-            i = i + 1;
-        };
-
-        let d_real = get_d(pool_amounts_after, ann);
-        (mul_div_u128(total_supply, (d_real - d_before as u128), (d_before as u128)) as u64)
-    } else {
-        d_ideal
-    };
+    let (liquidity_amount, fee_amounts) = provide_simulation(pool_obj, amounts);
 
     assert!(
-        option::is_none(&min_liquidity) || *option::borrow(&min_liquidity) <= liquidity_amount,
-        error::invalid_state(EMIN_LIQUIDITY),
+        option::is_none(&min_liquidity)
+            || *option::borrow(&min_liquidity) <= liquidity_amount,
+        error::invalid_state(EMIN_LIQUIDITY)
     );
 
-    i = 0;
+    let pool_addr = object::object_address(&pool_obj);
+    let i = 0;
     while (i < n) {
         let fa = vector::pop_back(&mut coins);
-        primary_fungible_store::deposit(pair_addr, fa);
+        primary_fungible_store::deposit(pool_addr, fa);
         i = i + 1;
     };
     vector::destroy_empty(coins);
 
+    let pool = borrow_pool(pool_obj);
     let liquidity_token = coin::mint(&pool.mint_cap, liquidity_amount);
 
     event::emit<ProvideEvent>(
         ProvideEvent {
             coins: get_coin_addresses(pool.coin_metadata),
             coin_amounts: amounts,
-            liquidity_token: pair_addr,
-            liquidity: liquidity_amount,
-        },
+            fee_amounts,
+            liquidity_token: pool_addr,
+            liquidity: liquidity_amount
+        }
     );
 
     return liquidity_token
@@ -1266,8 +1580,6 @@ Return swap simulation result
 
 
 
-
- ## Function `withdraw_liquidity` @@ -1279,50 +1591,75 @@ Return swap simulation result -
-Implementation +##### Implementation -
public fun withdraw_liquidity(liquidity_token: FungibleAsset, min_return_amounts: vector<Option<u64>>): vector<FungibleAsset> acquires Pool {
-    let pair_addr = object::object_address(fungible_asset::metadata_from_asset(&liquidity_token));
-    let pair = object::address_to_object<Pool>(pair_addr);
+
public fun withdraw_liquidity(
+    liquidity_token: FungibleAsset, min_return_amounts: vector<Option<u64>>
+): vector<FungibleAsset> acquires Pool {
+    let pool_addr =
+        object::object_address(
+            &fungible_asset::metadata_from_asset(&liquidity_token)
+        );
+    let pool_obj = object::address_to_object<Pool>(pool_addr);
     let liquidity_amount = fungible_asset::amount(&liquidity_token);
-    assert!(liquidity_amount != 0, error::invalid_argument(EZERO_LIQUIDITY));
-    let pool = borrow_pool(pair);
-    let pair_signer = object::generate_signer_for_extending(&pool.extend_ref);
-    let total_supply = option::extract(&mut fungible_asset::supply(pair));
+    assert!(
+        liquidity_amount != 0,
+        error::invalid_argument(EZERO_LIQUIDITY)
+    );
+    let pool = borrow_pool(pool_obj);
+    let pool_signer = object::generate_signer_for_extending(&pool.extend_ref);
+    let total_supply = option::extract(&mut fungible_asset::supply(pool_obj));
     let n = vector::length(&pool.coin_metadata);
 
     let return_coins: vector<FungibleAsset> = vector[];
-    let pool_amounts = get_pool_amounts(pair_addr, pool.coin_metadata);
+    let pool_amounts = get_pool_amounts(pool_addr, pool.coin_metadata);
     let coin_amounts: vector<u64> = vector[];
 
+    let fee_amounts: vector<u64> = vector[];
     let i = 0;
     while (i < n) {
+        vector::push_back(&mut fee_amounts, 0);
         let pool_amount = *vector::borrow(&pool_amounts, i);
-        let return_amount = (mul_div_u128((pool_amount as u128), (liquidity_amount as u128), total_supply) as u64);
+        let return_amount =
+            (
+                mul_div_u128(
+                    (pool_amount as u128),
+                    (liquidity_amount as u128),
+                    total_supply
+                ) as u64
+            );
         let min_return = vector::borrow(&min_return_amounts, i);
         let coin_metadata = *vector::borrow(&pool.coin_metadata, i);
 
         assert!(
-            option::is_none(min_return) || *option::borrow(min_return) <= return_amount,
-            error::invalid_state(EMIN_WITHDRAW),
+            option::is_none(min_return)
+                || *option::borrow(min_return) <= return_amount,
+            error::invalid_state(EMIN_WITHDRAW)
         );
 
         vector::push_back(&mut coin_amounts, return_amount);
-        vector::push_back(&mut return_coins, primary_fungible_store::withdraw(&pair_signer, coin_metadata, return_amount));
+        vector::push_back(
+            &mut return_coins,
+            primary_fungible_store::withdraw(
+                &pool_signer,
+                coin_metadata,
+                return_amount
+            )
+        );
         i = i + 1;
     };
 
     coin::burn(&pool.burn_cap, liquidity_token);
 
-    event::emit<ProvideEvent>(
-        ProvideEvent {
+    event::emit<WithdrawEvent>(
+        WithdrawEvent {
             coins: get_coin_addresses(pool.coin_metadata),
             coin_amounts,
-            liquidity_token: pair_addr,
-            liquidity: liquidity_amount,
-        },
+            fee_amounts,
+            liquidity_token: pool_addr,
+            liquidity: liquidity_amount
+        }
     );
 
     return return_coins
@@ -1331,569 +1668,516 @@ Return swap simulation result
 
 
 
-
+ - - -## Function `swap` +## Function `single_asset_withdraw_liquidity` -
public fun swap(pair: object::Object<stableswap::Pool>, offer_coin: fungible_asset::FungibleAsset, return_coin_metadata: object::Object<fungible_asset::Metadata>, min_return_amount: option::Option<u64>): fungible_asset::FungibleAsset
+
public fun single_asset_withdraw_liquidity(liquidity_token: fungible_asset::FungibleAsset, return_coin_metadata: object::Object<fungible_asset::Metadata>, min_return_amount: option::Option<u64>): fungible_asset::FungibleAsset
 
-
-Implementation +##### Implementation -
public fun swap(pair: Object<Pool>, offer_coin: FungibleAsset, return_coin_metadata: Object<Metadata>, min_return_amount: Option<u64>): FungibleAsset acquires Pool {
-    let offer_coin_metadata = fungible_asset::metadata_from_asset(&offer_coin);
-    let offer_amount = fungible_asset::amount(&offer_coin);
-    let (return_amount, fee_amount) = swap_simulation(pair, offer_coin_metadata, return_coin_metadata, offer_amount);
-    return_amount = return_amount - fee_amount;
-
+
public fun single_asset_withdraw_liquidity(
+    liquidity_token: FungibleAsset,
+    return_coin_metadata: Object<Metadata>,
+    min_return_amount: Option<u64>
+): FungibleAsset acquires Pool {
+    // get pool infos
+    let pool_addr =
+        object::object_address(
+            &fungible_asset::metadata_from_asset(&liquidity_token)
+        );
+    let pool_obj = object::address_to_object<Pool>(pool_addr);
+    let liquidity_amount = fungible_asset::amount(&liquidity_token);
     assert!(
-        option::is_none(&min_return_amount) || *option::borrow(&min_return_amount) <= return_amount,
-        error::invalid_state(EMIN_RETURN),
+        liquidity_amount != 0,
+        error::invalid_argument(EZERO_LIQUIDITY)
     );
 
-    let pool = borrow_pool(pair);
-    let pair_addr = object::object_address(pair);
-    let pair_signer = object::generate_signer_for_extending(&pool.extend_ref);
-    primary_fungible_store::deposit(pair_addr, offer_coin);
-    let return_coin = primary_fungible_store::withdraw(&pair_signer, return_coin_metadata, return_amount);
+    let pool = borrow_pool(pool_obj);
+    let pool_signer = object::generate_signer_for_extending(&pool.extend_ref);
+    let n = vector::length(&pool.coin_metadata);
 
-    event::emit<SwapEvent>(
-        SwapEvent {
-            offer_coin: object::object_address(offer_coin_metadata),
-            return_coin: object::object_address(return_coin_metadata),
-            liquidity_token: pair_addr,
-            fee_amount,
-            offer_amount,
-            return_amount,
-        },
+    // get return index
+    let (found, return_index) = vector::index_of(
+        &pool.coin_metadata, &return_coin_metadata
+    );
+    assert!(found, error::invalid_argument(ECOIN_TYPE));
+
+    // calculate amount of returning asset
+    let (return_amount, fee) =
+        single_asset_withdraw_simulation(
+            pool_obj,
+            liquidity_amount,
+            return_index
+        );
+    assert!(
+        option::is_none(&min_return_amount)
+            || *option::borrow(&min_return_amount) <= return_amount,
+        error::invalid_state(EMIN_RETURN)
     );
 
-    return return_coin
-}
-
- - - -
- - - -## Function `pool_info` - - - -
public fun pool_info(pair: object::Object<stableswap::Pool>): (vector<object::Object<fungible_asset::Metadata>>, vector<u64>, u64, decimal128::Decimal128)
-
- - - -
-Implementation + // withdraw return coin + let return_coin = + primary_fungible_store::withdraw( + &pool_signer, + return_coin_metadata, + return_amount + ); + // burn liquidity token + let pool = borrow_pool(pool_obj); + coin::burn(&pool.burn_cap, liquidity_token); -
public fun pool_info(pair: Object<Pool>): (vector<Object<Metadata>>, vector<u64>, u64, Decimal128) acquires Pool {
-    let pair_addr = object::object_address(pair);
-    let pool = borrow_global<Pool>(pair_addr);
+    // generate withdraw/fee amounts for event
+    let coin_amounts: vector<u64> = vector[];
+    let fee_amounts: vector<u64> = vector[];
+    let i = 0;
+    while (i < n) {
+        let (amount, fee) = if (i == return_index) {
+            (return_amount, fee)
+        } else { (0, 0) };
+        vector::push_back(&mut coin_amounts, amount);
+        vector::push_back(&mut fee_amounts, fee);
+        i = i + 1;
+    };
 
-    let ann = get_current_ann(&pool.ann);
-    let pool_amounts = get_pool_amounts(pair_addr, pool.coin_metadata);
+    // emit withdraw event
+    event::emit<WithdrawEvent>(
+        WithdrawEvent {
+            coins: get_coin_addresses(pool.coin_metadata),
+            coin_amounts,
+            fee_amounts,
+            liquidity_token: pool_addr,
+            liquidity: liquidity_amount
+        }
+    );
 
-    (
-        pool.coin_metadata,
-        pool_amounts,
-        ann,
-        pool.swap_fee_rate,
-    )
+    return_coin
 }
 
-
- - - -## Function `borrow_pool` - - - -
fun borrow_pool(pair: object::Object<stableswap::Pool>): &stableswap::Pool
-
- + +## Function `swap` -
-Implementation -
inline fun borrow_pool(pair: Object<Pool>): &Pool {
-    borrow_global<Pool>(object::object_address(pair))
-}
+
public fun swap(pool_obj: object::Object<stableswap::Pool>, offer_coin: fungible_asset::FungibleAsset, return_coin_metadata: object::Object<fungible_asset::Metadata>, min_return_amount: option::Option<u64>): fungible_asset::FungibleAsset
 
-
+##### Implementation - - -## Function `borrow_pool_mut` - - - -
fun borrow_pool_mut(pair: object::Object<stableswap::Pool>): &mut stableswap::Pool
-
+
public fun swap(
+    pool_obj: Object<Pool>,
+    offer_coin: FungibleAsset,
+    return_coin_metadata: Object<Metadata>,
+    min_return_amount: Option<u64>
+): FungibleAsset acquires Pool {
+    let offer_coin_metadata = fungible_asset::metadata_from_asset(&offer_coin);
+    let offer_amount = fungible_asset::amount(&offer_coin);
+    let (return_amount, fee_amount) =
+        swap_simulation(
+            pool_obj,
+            offer_coin_metadata,
+            return_coin_metadata,
+            offer_amount,
+            true
+        );
+    return_amount = return_amount - fee_amount;
 
+    assert!(
+        option::is_none(&min_return_amount)
+            || *option::borrow(&min_return_amount) <= return_amount,
+        error::invalid_state(EMIN_RETURN)
+    );
 
-
-Implementation + let pool = borrow_pool(pool_obj); + let pool_addr = object::object_address(&pool_obj); + let pool_signer = object::generate_signer_for_extending(&pool.extend_ref); + primary_fungible_store::deposit(pool_addr, offer_coin); + let return_coin = + primary_fungible_store::withdraw( + &pool_signer, + return_coin_metadata, + return_amount + ); + event::emit<SwapEvent>( + SwapEvent { + offer_coin: object::object_address(&offer_coin_metadata), + return_coin: object::object_address(&return_coin_metadata), + liquidity_token: pool_addr, + fee_amount, + offer_amount, + return_amount + } + ); -
inline fun borrow_pool_mut(pair: Object<Pool>): &mut Pool {
-    borrow_global_mut<Pool>(object::object_address(pair))
+    return return_coin
 }
 
-
- - + -## Function `get_current_ann` +## Function `pool_info` -
fun get_current_ann(ann: &stableswap::Ann): u64
+
public fun pool_info(pool_obj: object::Object<stableswap::Pool>): (vector<object::Object<fungible_asset::Metadata>>, vector<u64>, u64, bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation -
fun get_current_ann(ann: &Ann): u64 {
-    let (_, timestamp) = block::get_block_info();
+
public fun pool_info(
+    pool_obj: Object<Pool>
+): (vector<Object<Metadata>>, vector<u64>, u64, BigDecimal) acquires Pool {
+    let pool_addr = object::object_address(&pool_obj);
+    let pool = borrow_global<Pool>(pool_addr);
 
-    if (timestamp >= ann.timestamp_after) {
-        return ann.ann_after
-    };
+    let ann = get_current_ann(&pool.ann);
+    let pool_amounts = get_pool_amounts(pool_addr, pool.coin_metadata);
 
-    if (ann.ann_after > ann.ann_before) {
-        return ann.ann_before + (ann.ann_after - ann.ann_before) * (timestamp - ann.timestamp_before) / (ann.timestamp_after - ann.timestamp_before)
-    } else {
-        return ann.ann_before - (ann.ann_before - ann.ann_after) * (timestamp - ann.timestamp_before) / (ann.timestamp_after - ann.timestamp_before)
-    }
+    (pool.coin_metadata, pool_amounts, ann, pool.swap_fee_rate)
 }
 
-
- - - -## Function `check_coin_metadata` - - - -
fun check_coin_metadata(coin_metadata: &vector<object::Object<fungible_asset::Metadata>>, coins: &vector<fungible_asset::FungibleAsset>): u64
-
- - - -
-Implementation + +## Function `single_asset_withdraw_simulation` -
fun check_coin_metadata(coin_metadata: &vector<Object<Metadata>>, coins: &vector<FungibleAsset>): u64 {
-    let len = vector::length(coin_metadata);
-    assert!(len == vector::length(coins), error::invalid_argument(EN_COINS));
 
-    let i = 0;
-    while (i < len) {
-        let metadata = vector::borrow(coin_metadata, i);
-        let metadata_ = fungible_asset::metadata_from_asset(vector::borrow(coins, i));
-        assert!(*metadata == metadata_, error::invalid_argument(ECOIN_TYPE));
-        i = i + 1;
-    };
 
-    return len
-}
+
public fun single_asset_withdraw_simulation(pool_obj: object::Object<stableswap::Pool>, liquidity_amount: u64, return_index: u64): (u64, u64)
 
-
+##### Implementation - -## Function `get_pool_amounts` - - - -
fun get_pool_amounts(pair_addr: address, coin_metadata: vector<object::Object<fungible_asset::Metadata>>): vector<u64>
-
- - - -
-Implementation +
public fun single_asset_withdraw_simulation(
+    pool_obj: Object<Pool>, liquidity_amount: u64, return_index: u64
+): (u64, u64) acquires Pool {
+    let pool_addr = object::object_address(&pool_obj);
+    let pool = borrow_global<Pool>(pool_addr);
+    let n = vector::length(&pool.coin_metadata);
+    let ann = get_current_ann(&pool.ann);
+    let withdraw_fee_rate =
+        bigdecimal::div_by_u64(
+            bigdecimal::mul_by_u64(pool.swap_fee_rate, n),
+            4 * (n - 1)
+        );
+    let total_supply = option::extract(&mut fungible_asset::supply(pool_obj));
+    let pool_amounts = get_pool_amounts(pool_addr, pool.coin_metadata);
+    let d_before = get_d(pool_amounts, ann);
+    let d_after =
+        d_before
+            - (
+                mul_div_u128(
+                    (liquidity_amount as u128),
+                    (d_before as u128),
+                    total_supply
+                ) as u64
+            );
+
+    let y_without_fee = get_y_with_given_d(
+        pool_amounts,
+        return_index,
+        ann,
+        d_after
+    );
+    let return_amount_without_fee =
+        *vector::borrow(&pool_amounts, return_index) - y_without_fee;
 
+    // calculate fee
 
-
fun get_pool_amounts(pair_addr: address, coin_metadata: vector<Object<Metadata>>): vector<u64> {
-    let amounts: vector<u64> = vector[];
-    let len = vector::length(&coin_metadata);
+    // amount that after fee removed
+    let pool_amounts_reduced = pool_amounts;
     let i = 0;
-    while(i < len) {
-        let metadata = *vector::borrow(&coin_metadata, i);
-        vector::push_back(&mut amounts, primary_fungible_store::balance(pair_addr, metadata));
-        i = i + 1;
-    };
-
-    return amounts
-}
-
- - - -
- - - -## Function `get_amounts` - - - -
fun get_amounts(coins: &vector<fungible_asset::FungibleAsset>): vector<u64>
-
- - - -
-Implementation - + while (i < n) { + // get difference with ideal amount + let amount_diff = + if (i == return_index) { + mul_div_u64( + *vector::borrow(&pool_amounts, i), + d_after, + d_before + ) - y_without_fee + } else { + *vector::borrow(&pool_amounts, i) + - mul_div_u64( + *vector::borrow(&pool_amounts, i), + d_after, + d_before + ) + }; -
fun get_amounts(coins: &vector<FungibleAsset>): vector<u64> {
-    let amounts: vector<u64> = vector[];
-    let len = vector::length(coins);
-    let i = 0;
-    while(i < len) {
-        let amount = fungible_asset::amount(vector::borrow(coins, i));
-        vector::push_back(&mut amounts, amount);
+        let pool_amount = vector::borrow_mut(&mut pool_amounts_reduced, i);
+        *pool_amount = *pool_amount
+            - bigdecimal::mul_by_u64_truncate(withdraw_fee_rate, amount_diff);
         i = i + 1;
     };
 
-    return amounts
-}
-
- - - -
- - - -## Function `get_coin_addresses` - - - -
fun get_coin_addresses(coin_metadata: vector<object::Object<fungible_asset::Metadata>>): vector<address>
-
- - - -
-Implementation - - -
fun get_coin_addresses(coin_metadata: vector<Object<Metadata>>): vector<address> {
-    let addresses: vector<address> = vector[];
-    let len = vector::length(&coin_metadata);
-    let i = 0;
-    while(i < len) {
-        let addr = object::object_address(*vector::borrow(&coin_metadata, i));
-        vector::push_back(&mut addresses, addr);
-        i = i + 1;
-    };
+    let return_amount =
+        *vector::borrow(&pool_amounts_reduced, return_index)
+            - get_y_with_given_d(
+                pool_amounts_reduced,
+                return_index,
+                ann,
+                d_after
+            ) - 1; // sub 1 in case of rounding errors
 
-    return addresses
+    (return_amount, return_amount_without_fee - return_amount)
 }
 
-
+ - +## Function `imbalance_withdraw_simulation` -## Function `get_d` - -
fun get_d(amounts: vector<u64>, ann: u64): u64
+
public fun imbalance_withdraw_simulation(pool_obj: object::Object<stableswap::Pool>, coin_amounts: vector<u64>, max_liquidity_amount: option::Option<u64>): (u64, vector<u64>)
 
-
-Implementation - +##### Implementation -
fun get_d(amounts: vector<u64>, ann: u64): u64 {
-    let ann = (ann as u256);
 
-    let sum: u256 = 0;
-    let n = (vector::length(&amounts) as u256);
-    let i = 0;
-    while (i < (n as u64)) {
-        sum = sum + (*vector::borrow(&amounts, i) as u256);
-        i = i + 1;
-    };
-    if (sum == 0) return 0;
-    let d = sum;
+
public fun imbalance_withdraw_simulation(
+    pool_obj: Object<Pool>,
+    coin_amounts: vector<u64>,
+    max_liquidity_amount: Option<u64>
+): (u64, vector<u64>) acquires Pool {
+    let pool_addr = object::object_address(&pool_obj);
+    let pool = borrow_global<Pool>(pool_addr);
+    let n = vector::length(&pool.coin_metadata);
+    let ann = get_current_ann(&pool.ann);
+    let withdraw_fee_rate =
+        bigdecimal::div_by_u64(
+            bigdecimal::mul_by_u64(pool.swap_fee_rate, n),
+            4 * (n - 1)
+        );
+    let total_supply = option::extract(&mut fungible_asset::supply(pool_obj));
 
-    let i = 0;
+    assert!(
+        n == vector::length(&coin_amounts),
+        error::invalid_argument(EN_COINS)
+    );
 
-    // converge
-    // d = (ann * sum - d_prod) / (ann - 1)
-    while (i < 255) {
-        let d_prev = d;
-        // D ** (n + 1) / (n ** n * prod)
-        let d_prod = d;
-        let j = 0;
-        while (j < (n as u64)) {
-            d_prod = d_prod * d / (n as u256) / (*vector::borrow(&amounts, j) as u256);
-            j = j + 1;
-        };
+    let pool_amounts_before = get_pool_amounts(pool_addr, pool.coin_metadata);
+    let pool_amounts_after = copy pool_amounts_before;
+    let d_before = get_d(pool_amounts_before, ann);
 
-        d = (ann * sum / A_PRECISION + d_prod * n) * d / ((ann - A_PRECISION) * d / A_PRECISION + (n + 1) * d_prod);
-        if (d > d_prev) {
-            if (d - d_prev <= 1) break
-        } else {
-            if (d_prev - d <= 1) break
-        };
+    // update pool amounts after withdraw
+    let i = 0;
+    while (i < n) {
+        let pool_amount = vector::borrow_mut(&mut pool_amounts_after, i);
+        let withdraw_amount = *vector::borrow(&coin_amounts, i);
+        *pool_amount = *pool_amount - withdraw_amount;
         i = i + 1;
     };
 
-    return (d as u64)
-}
-
- - - -
- - - -## Function `get_y` + let d_after_without_fee = get_d(pool_amounts_after, ann); -get counterparty's amount + let fees: vector<u64> = vector[]; - -
fun get_y(offer_index: u64, return_index: u64, offer_amount: u64, pool_amounts: vector<u64>, ann: u64): u64
-
- - - -
-Implementation - - -
fun get_y(offer_index: u64, return_index: u64, offer_amount: u64, pool_amounts: vector<u64>, ann: u64): u64 {
-    let d = (get_d(pool_amounts, ann) as u256);
-
-    let ann = (ann as u256);
-    // Done by solving quadratic equation iteratively.
-    // x_1**2 + x_1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)
-    // y**2 + b*y = c
-
-    // y = (y**2 + c) / (2*y + b)
-    let n = vector::length(&pool_amounts);
+    // calculate fee
     let i = 0;
-    let sum = 0; // sum'
-    let c = d;
     while (i < n) {
-        if (i == return_index) {
-            i = i + 1;
-            continue
-        };
-
-        let pool_amount = if (i == offer_index) {
-            (*vector::borrow(&pool_amounts, i) + offer_amount as u256)
-        } else {
-            (*vector::borrow(&pool_amounts, i) as u256)
-        };
-
-        sum = sum + pool_amount;
-        c = c * d / (pool_amount * (n as u256));
+        let ideal_balance =
+            mul_div_u64(
+                *vector::borrow(&pool_amounts_before, i),
+                d_after_without_fee,
+                d_before
+            );
+        let balance_after = vector::borrow_mut(&mut pool_amounts_after, i);
+        let amount_diff =
+            if (*balance_after > ideal_balance) {
+                *balance_after - ideal_balance
+            } else {
+                ideal_balance - *balance_after
+            };
+        let fee = bigdecimal::mul_by_u64_ceil(withdraw_fee_rate, amount_diff);
+        vector::push_back(&mut fees, fee);
+        *balance_after = *balance_after - fee; // to get d_after remove fee
         i = i + 1;
     };
 
-    c = c * d * A_PRECISION / ann / (n as u256);
-    let b_plus_d = sum + d * A_PRECISION / ann; // need to sub d but sub later due to value must be less than 0
-
-    let y_prev;
-    let y = d;
-
-    let i = 0;
-    // converge
-    while (i < 255) {
-        y_prev = y;
-        y = (y * y + c) / (2 * y + b_plus_d - d); // sub d here
+    let d_after = get_d(pool_amounts_after, ann);
+    let liquidity_amount =
+        (
+            mul_div_u128(
+                total_supply,
+                (d_before - d_after as u128),
+                (d_before as u128)
+            ) as u64
+        );
+    assert!(
+        liquidity_amount != 0,
+        error::invalid_state(EZERO_LIQUIDITY)
+    );
+    liquidity_amount = liquidity_amount + 1; // add 1 just in case of rounding errors
 
-        if (y > y_prev) {
-            if (y - y_prev <= 1) break
-        } else {
-            if (y_prev - y <= 1) break
-        };
-        i = i + 1;
-    };
+    assert!(
+        option::is_none(&max_liquidity_amount)
+            || *option::borrow(&max_liquidity_amount) >= liquidity_amount,
+        error::invalid_state(EMAX_LIQUIDITY)
+    );
 
-    (y as u64)
+    (liquidity_amount, fees)
 }
 
-
- ## Function `swap_simulation` -
fun swap_simulation(pair: object::Object<stableswap::Pool>, offer_coin_metadata: object::Object<fungible_asset::Metadata>, return_coin_metadata: object::Object<fungible_asset::Metadata>, offer_amount: u64): (u64, u64)
+
public fun swap_simulation(pool_obj: object::Object<stableswap::Pool>, offer_coin_metadata: object::Object<fungible_asset::Metadata>, return_coin_metadata: object::Object<fungible_asset::Metadata>, amount: u64, is_offer_amount: bool): (u64, u64)
 
-
-Implementation +##### Implementation -
fun swap_simulation(
-    pair: Object<Pool>,
+
public fun swap_simulation(
+    pool_obj: Object<Pool>,
     offer_coin_metadata: Object<Metadata>,
     return_coin_metadata: Object<Metadata>,
-    offer_amount: u64,
+    amount: u64,
+    is_offer_amount: bool
 ): (u64, u64) acquires Pool {
-    let pool = borrow_pool(pair);
-    let pair_addr = object::object_address(pair);
-    let n = vector::length(&pool.coin_metadata);
-
-    let ann = get_current_ann(&pool.ann);
-    let pool_amounts = get_pool_amounts(pair_addr, pool.coin_metadata);
-    let offer_index = n;
-    let return_index = n;
-    let i = 0;
-    while (i < n) {
-        let metadata = *vector::borrow(&pool.coin_metadata, i);
-        if (metadata == offer_coin_metadata){
-            offer_index = i
-        };
-        if (metadata == return_coin_metadata){
-            return_index = i
-        };
-        if (offer_index != n && return_index != n) {
-            break
-        };
-        i = i + 1;
-    };
-
-    assert!(offer_index != n && return_index != n, error::invalid_argument(ECOIN_TYPE));
-
-    let y = get_y(offer_index, return_index, offer_amount, pool_amounts, ann);
-    let return_amount = *vector::borrow(&pool_amounts, return_index) - y - 1; // sub 1 just in case
-    let fee_amount = decimal128::mul_u64(&pool.swap_fee_rate, return_amount);
-    (return_amount, fee_amount)
-}
-
- - - -
- - - -## Function `mul_div_u64` - - - -
fun mul_div_u64(a: u64, b: u64, c: u64): u64
-
- - - -
-Implementation - - -
fun mul_div_u64(a: u64, b: u64, c: u64): u64 {
-    return ((a as u128) * (b as u128) / (c as u128) as u64)
+    let pool = borrow_pool(pool_obj);
+    let pool_addr = object::object_address(&pool_obj);
+    let pool_amounts = get_pool_amounts(pool_addr, pool.coin_metadata);
+    swap_simulation_with_given_amounts(
+        pool_obj,
+        pool_amounts,
+        offer_coin_metadata,
+        return_coin_metadata,
+        amount,
+        is_offer_amount
+    )
 }
 
-
- - - -## Function `mul_div_u128` - - - -
fun mul_div_u128(a: u128, b: u128, c: u128): u128
-
+ +## Function `provide_simulation` -
-Implementation - -
fun mul_div_u128(a: u128, b: u128, c: u128): u128 {
-    return ((a as u256) * (b as u256) / (c as u256) as u128)
-}
+
public fun provide_simulation(pool_obj: object::Object<stableswap::Pool>, amounts: vector<u64>): (u64, vector<u64>)
 
-
- - +##### Implementation -## Function `check_chain_permission` - -Check signer is chain +
public fun provide_simulation(
+    pool_obj: Object<Pool>, amounts: vector<u64>
+): (u64, vector<u64>) acquires Pool {
+    let pool = borrow_pool(pool_obj);
+    let pool_addr = object::object_address(&pool_obj);
+    let ann = get_current_ann(&pool.ann);
 
-
fun check_chain_permission(chain: &signer)
-
+ let pool_amounts_before = get_pool_amounts(pool_addr, pool.coin_metadata); + let d_before = get_d(pool_amounts_before, ann); + let total_supply = option::extract(&mut fungible_asset::supply(pool_obj)); + let n = vector::length(&amounts); + // pool amounts before adjust fee + let pool_amounts_after: vector<u64> = vector[]; + let i = 0; + while (i < n) { + let pool_amount = *vector::borrow(&pool_amounts_before, i); + let offer_amount = *vector::borrow(&amounts, i); + if (total_supply == 0) { + assert!( + offer_amount > 0, + error::invalid_argument(EZERO_LIQUIDITY) + ); + }; + vector::push_back( + &mut pool_amounts_after, + pool_amount + offer_amount + ); + i = i + 1; + }; + let d_ideal = get_d(pool_amounts_after, ann); + let fee_amounts: vector<u64> = vector[]; -
-Implementation + // calc fees + let liquidity_amount = + if (total_supply > 0) { + let provide_fee_rate = + bigdecimal::div_by_u64( + bigdecimal::mul_by_u64(pool.swap_fee_rate, n), + 4 * (n - 1) + ); + i = 0; + while (i < n) { + let pool_amount_before = *vector::borrow(&pool_amounts_before, i); + let pool_amount_after = vector::borrow_mut(&mut pool_amounts_after, i); + let ideal_balance = mul_div_u64( + d_ideal, + pool_amount_before, + d_before + ); + let diff = + if (ideal_balance > *pool_amount_after) { + ideal_balance - *pool_amount_after + } else { + *pool_amount_after - ideal_balance + }; + let fee = bigdecimal::mul_by_u64_ceil(provide_fee_rate, diff); + vector::push_back(&mut fee_amounts, fee); + *pool_amount_after = *pool_amount_after - fee; + i = i + 1; + }; + let d_real = get_d(pool_amounts_after, ann); + ( + mul_div_u128( + total_supply, + (d_real - d_before as u128), + (d_before as u128) + ) as u64 + ) + } else { + d_ideal + }; -
fun check_chain_permission(chain: &signer) {
-    assert!(signer::address_of(chain) == @initia_std, error::permission_denied(EUNAUTHORIZED));
+    (liquidity_amount, fee_amounts)
 }
 
- - - -
diff --git a/initia_stdlib/doc/staking.md b/initia_stdlib/doc/staking.md index ebd6cb8..fbfc515 100644 --- a/initia_stdlib/doc/staking.md +++ b/initia_stdlib/doc/staking.md @@ -20,13 +20,6 @@ - [Struct `UnbondingResponse`](#0x1_staking_UnbondingResponse) - [Constants](#@Constants_0) - [Function `reward_metadata`](#0x1_staking_reward_metadata) -- [Function `init_module`](#0x1_staking_init_module) -- [Function `load_staking_state`](#0x1_staking_load_staking_state) -- [Function `load_staking_state_mut`](#0x1_staking_load_staking_state_mut) -- [Function `load_delegation`](#0x1_staking_load_delegation) -- [Function `load_delegation_mut`](#0x1_staking_load_delegation_mut) -- [Function `load_unbonding`](#0x1_staking_load_unbonding) -- [Function `load_unbonding_mut`](#0x1_staking_load_unbonding_mut) - [Function `get_delegation_response_from_delegation`](#0x1_staking_get_delegation_response_from_delegation) - [Function `get_unbonding_response_from_unbonding`](#0x1_staking_get_unbonding_response_from_unbonding) - [Function `get_delegation`](#0x1_staking_get_delegation) @@ -41,7 +34,6 @@ - [Function `get_validator_from_unbonding_response`](#0x1_staking_get_validator_from_unbonding_response) - [Function `get_release_time_from_unbonding_response`](#0x1_staking_get_release_time_from_unbonding_response) - [Function `get_unbonding_amount_from_unbonding_response`](#0x1_staking_get_unbonding_amount_from_unbonding_response) -- [Function `check_chain_permission`](#0x1_staking_check_chain_permission) - [Function `initialize_for_chain`](#0x1_staking_initialize_for_chain) - [Function `slash_unbonding_for_chain`](#0x1_staking_slash_unbonding_for_chain) - [Function `deposit_unbonding_coin_for_chain`](#0x1_staking_deposit_unbonding_coin_for_chain) @@ -55,7 +47,6 @@ - [Function `claim_unbonding_script`](#0x1_staking_claim_unbonding_script) - [Function `claim_reward_script`](#0x1_staking_claim_reward_script) - [Function `claim_reward`](#0x1_staking_claim_reward) -- [Function `calculate_reward`](#0x1_staking_calculate_reward) - [Function `empty_delegation`](#0x1_staking_empty_delegation) - [Function `get_metadata_from_delegation`](#0x1_staking_get_metadata_from_delegation) - [Function `get_validator_from_delegation`](#0x1_staking_get_validator_from_delegation) @@ -65,9 +56,6 @@ - [Function `withdraw_delegation`](#0x1_staking_withdraw_delegation) - [Function `extract_delegation`](#0x1_staking_extract_delegation) - [Function `merge_delegation`](#0x1_staking_merge_delegation) -- [Function `destroy_delegation_and_extract_reward`](#0x1_staking_destroy_delegation_and_extract_reward) -- [Function `unbonding_share_from_amount`](#0x1_staking_unbonding_share_from_amount) -- [Function `unbonding_amount_from_share`](#0x1_staking_unbonding_amount_from_share) - [Function `empty_unbonding`](#0x1_staking_empty_unbonding) - [Function `get_metadata_from_unbonding`](#0x1_staking_get_metadata_from_unbonding) - [Function `get_validator_from_unbonding`](#0x1_staking_get_validator_from_unbonding) @@ -80,17 +68,15 @@ - [Function `extract_unbonding`](#0x1_staking_extract_unbonding) - [Function `merge_unbonding`](#0x1_staking_merge_unbonding) - [Function `claim_unbonding`](#0x1_staking_claim_unbonding) -- [Function `delegate_internal`](#0x1_staking_delegate_internal) -- [Function `undelegate_internal`](#0x1_staking_undelegate_internal) - [Function `share_to_amount`](#0x1_staking_share_to_amount) - [Function `amount_to_share`](#0x1_staking_amount_to_share)
use 0x1::account;
+use 0x1::bigdecimal;
 use 0x1::block;
 use 0x1::coin;
 use 0x1::cosmos;
-use 0x1::decimal128;
 use 0x1::error;
 use 0x1::event;
 use 0x1::fungible_asset;
@@ -115,8 +101,7 @@
 
 
 
-
-Fields +##### Fields
@@ -129,8 +114,6 @@
-
- ## Struct `StakingState` @@ -142,8 +125,7 @@ -
-Fields +##### Fields
@@ -160,19 +142,19 @@
-total_share: u128 +total_share: bigdecimal::BigDecimal
-unbonding_share: u128 +unbonding_share: bigdecimal::BigDecimal
-reward_index: decimal128::Decimal128 +reward_index: bigdecimal::BigDecimal
@@ -204,8 +186,6 @@
-
- ## Struct `Delegation` @@ -218,8 +198,7 @@ Define a delegation entry which can be transferred. -
-Fields +##### Fields
@@ -236,13 +215,13 @@ Define a delegation entry which can be transferred.
-share: u64 +share: bigdecimal::BigDecimal
-reward_index: decimal128::Decimal128 +reward_index: bigdecimal::BigDecimal
@@ -250,8 +229,6 @@ Define a delegation entry which can be transferred.
-
- ## Struct `Unbonding` @@ -264,8 +241,7 @@ Define a unbonding entry which can be transferred. -
-Fields +##### Fields
@@ -282,7 +258,7 @@ Define a unbonding entry which can be transferred.
-unbonding_share: u64 +unbonding_share: bigdecimal::BigDecimal
@@ -296,8 +272,6 @@ Define a unbonding entry which can be transferred.
-
- ## Resource `DelegationStore` @@ -311,8 +285,7 @@ These are kept in a single resource to ensure locality of data. -
-Fields +##### Fields
@@ -331,8 +304,6 @@ These are kept in a single resource to ensure locality of data.
-
- ## Struct `UnbondingKey` @@ -345,8 +316,7 @@ Key for Unbonding -
-Fields +##### Fields
@@ -365,8 +335,6 @@ Key for Unbonding
-
- ## Struct `RewardEvent` @@ -380,8 +348,7 @@ Event emitted when some amount of reward is claimed by entry function. -
-Fields +##### Fields
@@ -406,8 +373,6 @@ Event emitted when some amount of reward is claimed by entry function.
-
- ## Struct `DelegationDepositEvent` @@ -421,8 +386,7 @@ Event emitted when a Delegation is deposited to an account. -
-Fields +##### Fields
@@ -445,7 +409,7 @@ Event emitted when a Delegation is deposited to an account.
-share: u64 +share: bigdecimal::BigDecimal
@@ -453,8 +417,6 @@ Event emitted when a Delegation is deposited to an account.
-
- ## Struct `DelegationWithdrawEvent` @@ -468,8 +430,7 @@ Event emitted when a Delegation is withdrawn from an account. -
-Fields +##### Fields
@@ -492,7 +453,7 @@ Event emitted when a Delegation is withdrawn from an account.
-share: u64 +share: bigdecimal::BigDecimal
@@ -500,8 +461,6 @@ Event emitted when a Delegation is withdrawn from an account.
-
- ## Struct `UnbondingDepositEvent` @@ -515,8 +474,7 @@ Event emitted when a Unbonding is deposited from an account. -
-Fields +##### Fields
@@ -539,7 +497,7 @@ Event emitted when a Unbonding is deposited from an account.
-share: u64 +share: bigdecimal::BigDecimal
@@ -553,8 +511,6 @@ Event emitted when a Unbonding is deposited from an account.
-
- ## Struct `UnbondingWithdrawEvent` @@ -568,8 +524,7 @@ Event emitted when a Unbonding is withdrawn from an account. -
-Fields +##### Fields
@@ -592,7 +547,7 @@ Event emitted when a Unbonding is withdrawn from an account.
-share: u64 +share: bigdecimal::BigDecimal
@@ -606,8 +561,6 @@ Event emitted when a Unbonding is withdrawn from an account.
-
- ## Struct `DelegationResponse` @@ -619,8 +572,7 @@ Event emitted when a Unbonding is withdrawn from an account. -
-Fields +##### Fields
@@ -637,7 +589,7 @@ Event emitted when a Unbonding is withdrawn from an account.
-share: u64 +share: bigdecimal::BigDecimal
@@ -651,8 +603,6 @@ Event emitted when a Unbonding is withdrawn from an account.
-
- ## Struct `UnbondingResponse` @@ -664,8 +614,7 @@ Event emitted when a Unbonding is withdrawn from an account. -
-Fields +##### Fields
@@ -696,8 +645,6 @@ Event emitted when a Unbonding is withdrawn from an account.
-
- ## Constants @@ -723,6 +670,16 @@ Max number of view function response items. + + +release_time of the source_unbonding must be sooner than or equal to the one of dst_unbonding + + +
const ERELEASE_TIME: u64 = 9;
+
+ + + Can not find delegation @@ -813,16 +770,6 @@ Can not claim before release_time - - -release_time of the source_unbonding must be sooner than or equal to the one of dst_unbonding - - -
const ERELEASE_TIME: u64 = 9;
-
- - - Chain already has StakingState for the given metadata @@ -893,8 +840,7 @@ Validator of delegation which is used as operand doesn't match the other operand -
-Implementation +##### Implementation
public fun reward_metadata(): Object<Metadata> {
@@ -904,204 +850,6 @@ Validator of delegation which is used as operand doesn't match the other operand
 
 
 
-
- - - -## Function `init_module` - - - -
fun init_module(chain: &signer)
-
- - - -
-Implementation - - -
fun init_module(chain: &signer) {
-    move_to(chain, ModuleStore {
-        staking_states: table::new(),
-    });
-}
-
- - - -
- - - -## Function `load_staking_state` - - - -
fun load_staking_state(staking_states: &table::Table<object::Object<fungible_asset::Metadata>, table::Table<string::String, staking::StakingState>>, metadata: object::Object<fungible_asset::Metadata>, validator: string::String): &staking::StakingState
-
- - - -
-Implementation - - -
fun load_staking_state (staking_states: &Table<Object<Metadata>, Table<String, StakingState>>, metadata: Object<Metadata>, validator: String): &StakingState {
-    assert!(table::contains(staking_states, metadata), error::not_found(ESTAKING_STATE_NOT_EXISTS));
-    let states = table::borrow(staking_states, metadata);
-
-    assert!(table::contains(states, validator), error::not_found(ESTAKING_STATE_NOT_EXISTS));
-    table::borrow(states, validator)
-}
-
- - - -
- - - -## Function `load_staking_state_mut` - - - -
fun load_staking_state_mut(staking_states: &mut table::Table<object::Object<fungible_asset::Metadata>, table::Table<string::String, staking::StakingState>>, metadata: object::Object<fungible_asset::Metadata>, validator: string::String): &mut staking::StakingState
-
- - - -
-Implementation - - -
fun load_staking_state_mut (staking_states: &mut Table<Object<Metadata>, Table<String, StakingState>>, metadata: Object<Metadata>, validator: String): &mut StakingState {
-    assert!(table::contains(staking_states, metadata), error::not_found(ESTAKING_STATE_NOT_EXISTS));
-    let states = table::borrow_mut(staking_states, metadata);
-
-    assert!(table::contains(states, validator), error::not_found(ESTAKING_STATE_NOT_EXISTS));
-    table::borrow_mut(states, validator)
-}
-
- - - -
- - - -## Function `load_delegation` - - - -
fun load_delegation(delegations: &table::Table<object::Object<fungible_asset::Metadata>, table::Table<string::String, staking::Delegation>>, metadata: object::Object<fungible_asset::Metadata>, validator: string::String): &staking::Delegation
-
- - - -
-Implementation - - -
fun load_delegation (delegations: &Table<Object<Metadata>, Table<String, Delegation>>, metadata: Object<Metadata>, validator: String): &Delegation {
-    assert!(table::contains(delegations, metadata), error::not_found(EDELEGATION_NOT_FOUND));
-    let delegations = table::borrow(delegations, metadata);
-
-    assert!(table::contains(delegations, validator), error::not_found(EDELEGATION_NOT_FOUND));
-    table::borrow(delegations, validator)
-}
-
- - - -
- - - -## Function `load_delegation_mut` - - - -
fun load_delegation_mut(delegations: &mut table::Table<object::Object<fungible_asset::Metadata>, table::Table<string::String, staking::Delegation>>, metadata: object::Object<fungible_asset::Metadata>, validator: string::String): &mut staking::Delegation
-
- - - -
-Implementation - - -
fun load_delegation_mut (delegations: &mut Table<Object<Metadata>, Table<String, Delegation>>, metadata: Object<Metadata>, validator: String): &mut Delegation {
-    assert!(table::contains(delegations, metadata), error::not_found(EDELEGATION_NOT_FOUND));
-    let delegations = table::borrow_mut(delegations, metadata);
-
-    assert!(table::contains(delegations, validator), error::not_found(EDELEGATION_NOT_FOUND));
-    table::borrow_mut(delegations, validator)
-}
-
- - - -
- - - -## Function `load_unbonding` - - - -
fun load_unbonding(unbondings: &table::Table<object::Object<fungible_asset::Metadata>, table::Table<staking::UnbondingKey, staking::Unbonding>>, metadata: object::Object<fungible_asset::Metadata>, validator: string::String, release_time: u64): &staking::Unbonding
-
- - - -
-Implementation - - -
fun load_unbonding (unbondings: &Table<Object<Metadata>, Table<UnbondingKey, Unbonding>>, metadata: Object<Metadata>, validator: String, release_time: u64): &Unbonding {
-    assert!(table::contains(unbondings, metadata), error::not_found(EUNBONDING_NOT_FOUND));
-    let unbondings = table::borrow(unbondings, metadata);
-
-    let key = UnbondingKey { validator, release_time };
-    assert!(table::contains(unbondings, key), error::not_found(EUNBONDING_NOT_FOUND));
-    table::borrow(unbondings, key)
-}
-
- - - -
- - - -## Function `load_unbonding_mut` - - - -
fun load_unbonding_mut(unbondings: &mut table::Table<object::Object<fungible_asset::Metadata>, table::Table<staking::UnbondingKey, staking::Unbonding>>, metadata: object::Object<fungible_asset::Metadata>, validator: string::String, release_time: u64): &mut staking::Unbonding
-
- - - -
-Implementation - - -
fun load_unbonding_mut (unbondings: &mut Table<Object<Metadata>, Table<UnbondingKey, Unbonding>>, metadata: Object<Metadata>, validator: String, release_time: u64): &mut Unbonding {
-    assert!(table::contains(unbondings, metadata), error::not_found(EUNBONDING_NOT_FOUND));
-    let unbondings = table::borrow_mut(unbondings, metadata);
-
-    let key = UnbondingKey { validator, release_time };
-    assert!(table::contains(unbondings, key), error::not_found(EUNBONDING_NOT_FOUND));
-    table::borrow_mut(unbondings, key)
-}
-
- - - -
- ## Function `get_delegation_response_from_delegation` @@ -1114,16 +862,21 @@ util function to convert Delegation => DelegationResponse for third party querie -
-Implementation +##### Implementation -
public fun get_delegation_response_from_delegation(delegation: &Delegation): DelegationResponse acquires ModuleStore {
+
public fun get_delegation_response_from_delegation(
+    delegation: &Delegation
+): DelegationResponse acquires ModuleStore {
     let metadata = delegation.metadata;
     let validator = delegation.validator;
 
     let module_store = borrow_global<ModuleStore>(@initia_std);
-    let state = load_staking_state(&module_store.staking_states, metadata, validator);
+    let state = load_staking_state(
+        &module_store.staking_states,
+        metadata,
+        validator
+    );
 
     let reward = calculate_reward(delegation, state);
 
@@ -1131,15 +884,13 @@ util function to convert Delegation => DelegationResponse for third party querie
         metadata: delegation.metadata,
         validator: delegation.validator,
         share: delegation.share,
-        unclaimed_reward: reward,
+        unclaimed_reward: reward
     }
 }
 
-
- ## Function `get_unbonding_response_from_unbonding` @@ -1152,26 +903,25 @@ util function to convert Unbonding => UnbondingResponse for third party queriers -
-Implementation +##### Implementation -
public fun get_unbonding_response_from_unbonding(unbonding: &Unbonding): UnbondingResponse acquires ModuleStore{
+
public fun get_unbonding_response_from_unbonding(
+    unbonding: &Unbonding
+): UnbondingResponse acquires ModuleStore {
     let unbonding_amount = get_unbonding_amount_from_unbonding(unbonding);
 
     UnbondingResponse {
         metadata: unbonding.metadata,
         validator: unbonding.validator,
         unbonding_amount,
-        release_time: unbonding.release_time,
+        release_time: unbonding.release_time
     }
 }
 
-
- ## Function `get_delegation` @@ -1185,25 +935,31 @@ Get delegation info of specifed addr and validator -
-Implementation +##### Implementation
public fun get_delegation(
-    addr: address,
-    metadata: Object<Metadata>,
-    validator: String,
+    addr: address, metadata: Object<Metadata>, validator: String
 ): DelegationResponse acquires DelegationStore, ModuleStore {
     assert!(
         is_account_registered(addr),
-        error::not_found(EDELEGATION_STORE_NOT_EXISTS),
+        error::not_found(EDELEGATION_STORE_NOT_EXISTS)
     );
 
     let delegation_store = borrow_global<DelegationStore>(addr);
-    let delegation = load_delegation(&delegation_store.delegations, metadata, validator);
+    let delegation =
+        load_delegation(
+            &delegation_store.delegations,
+            metadata,
+            validator
+        );
 
     let module_store = borrow_global<ModuleStore>(@initia_std);
-    let state = load_staking_state(&module_store.staking_states, metadata, validator);
+    let state = load_staking_state(
+        &module_store.staking_states,
+        metadata,
+        validator
+    );
 
     let reward = calculate_reward(delegation, state);
 
@@ -1211,15 +967,13 @@ Get delegation info of specifed addr and validator
         metadata,
         validator,
         share: delegation.share,
-        unclaimed_reward: reward,
+        unclaimed_reward: reward
     }
 }
 
-
- ## Function `get_delegations` @@ -1233,15 +987,14 @@ Get all delegation info of an addr -
-Implementation +##### Implementation
public fun get_delegations(
     addr: address,
     metadata: Object<Metadata>,
     start_after: Option<String>,
-    limit: u8,
+    limit: u8
 ): vector<DelegationResponse> acquires DelegationStore, ModuleStore {
     if (limit > MAX_LIMIT) {
         limit = MAX_LIMIT;
@@ -1249,7 +1002,7 @@ Get all delegation info of an addr
 
     assert!(
         is_account_registered(addr),
-        error::not_found(EDELEGATION_STORE_NOT_EXISTS),
+        error::not_found(EDELEGATION_STORE_NOT_EXISTS)
     );
 
     let module_store = borrow_global<ModuleStore>(@initia_std);
@@ -1261,13 +1014,13 @@ Get all delegation info of an addr
         delegations,
         option::none(),
         start_after,
-        2,
+        2
     );
 
-    let prepare = table::prepare(&mut delegations_iter);
+    let prepare = table::prepare(delegations_iter);
     let res: vector<DelegationResponse> = vector[];
     while (vector::length(&res) < (limit as u64) && prepare) {
-        let (validator, delegation) = table::next(&mut delegations_iter);
+        let (validator, delegation) = table::next(delegations_iter);
         let state = table::borrow(staking_states, validator);
         let reward = calculate_reward(delegation, state);
         vector::push_back(
@@ -1276,10 +1029,10 @@ Get all delegation info of an addr
                 metadata: delegation.metadata,
                 validator: delegation.validator,
                 share: delegation.share,
-                unclaimed_reward: reward,
-            },
+                unclaimed_reward: reward
+            }
         );
-        prepare = table::prepare(&mut delegations_iter);
+        prepare = table::prepare(delegations_iter);
     };
 
     res
@@ -1288,8 +1041,6 @@ Get all delegation info of an addr
 
 
 
-
- ## Function `get_unbonding` @@ -1303,39 +1054,42 @@ Get unbonding info of (addr, metadata, validator, release time) -
-Implementation +##### Implementation
public fun get_unbonding(
     addr: address,
     metadata: Object<Metadata>,
     validator: String,
-    release_time: u64,
+    release_time: u64
 ): UnbondingResponse acquires DelegationStore, ModuleStore {
     assert!(
         is_account_registered(addr),
-        error::not_found(EDELEGATION_STORE_NOT_EXISTS),
+        error::not_found(EDELEGATION_STORE_NOT_EXISTS)
     );
 
     let delegation_store = borrow_global<DelegationStore>(addr);
 
-    let unbonding = load_unbonding(&delegation_store.unbondings, metadata, validator, release_time);
+    let unbonding =
+        load_unbonding(
+            &delegation_store.unbondings,
+            metadata,
+            validator,
+            release_time
+        );
     let unbonding_amount = get_unbonding_amount_from_unbonding(unbonding);
 
     UnbondingResponse {
         metadata: unbonding.metadata,
         validator: unbonding.validator,
         unbonding_amount,
-        release_time,
+        release_time
     }
 }
 
-
- ## Function `get_unbondings` @@ -1349,8 +1103,7 @@ Get all unbondings of (addr, validator) -
-Implementation +##### Implementation
public fun get_unbondings(
@@ -1358,7 +1111,7 @@ Get all unbondings of (addr, validator)
     metadata: Object<Metadata>,
     start_after_validator: Option<String>,
     start_after_release_time: Option<u64>,
-    limit: u8,
+    limit: u8
 ): vector<UnbondingResponse> acquires DelegationStore, ModuleStore {
     if (limit > MAX_LIMIT) {
         limit = MAX_LIMIT;
@@ -1366,38 +1119,41 @@ Get all unbondings of (addr, validator)
 
     assert!(
         is_account_registered(addr),
-        error::not_found(EDELEGATION_STORE_NOT_EXISTS),
+        error::not_found(EDELEGATION_STORE_NOT_EXISTS)
     );
 
     assert!(
-        option::is_some(&start_after_validator) == option::is_some(&start_after_release_time),
+        option::is_some(&start_after_validator)
+            == option::is_some(&start_after_release_time),
         error::invalid_argument(EINVALID_START_AFTER)
     );
 
     let delegation_store = borrow_global<DelegationStore>(addr);
     let unbondings = table::borrow(&delegation_store.unbondings, metadata);
 
-    let start_after = if (option::is_some(&start_after_validator)) {
-        option::some(UnbondingKey {
-            validator: *option::borrow(&start_after_validator),
-            release_time: *option::borrow(&start_after_release_time),
-        })
-    } else {
-        option::none()
-    };
+    let start_after =
+        if (option::is_some(&start_after_validator)) {
+            option::some(
+                UnbondingKey {
+                    validator: *option::borrow(&start_after_validator),
+                    release_time: *option::borrow(&start_after_release_time)
+                }
+            )
+        } else {
+            option::none()
+        };
 
     let unbondings_iter = table::iter(
         unbondings,
         option::none(),
         start_after,
-        2,
+        2
     );
 
     let res: vector<UnbondingResponse> = vector[];
-    while (vector::length(&res) < (limit as u64) && table::prepare<UnbondingKey, Unbonding>(
-        &mut unbondings_iter
-    )) {
-        let (_, unbonding) = table::next<UnbondingKey, Unbonding>(&mut unbondings_iter);
+    while (vector::length(&res) < (limit as u64)
+        && table::prepare<UnbondingKey, Unbonding>(unbondings_iter)) {
+        let (_, unbonding) = table::next<UnbondingKey, Unbonding>(unbondings_iter);
         let unbonding_amount = get_unbonding_amount_from_unbonding(unbonding);
         vector::push_back(
             &mut res,
@@ -1405,8 +1161,8 @@ Get all unbondings of (addr, validator)
                 metadata: unbonding.metadata,
                 validator: unbonding.validator,
                 unbonding_amount,
-                release_time: unbonding.release_time,
-            },
+                release_time: unbonding.release_time
+            }
         );
     };
 
@@ -1416,8 +1172,6 @@ Get all unbondings of (addr, validator)
 
 
 
-
- ## Function `get_metadata_from_delegation_response` @@ -1430,19 +1184,18 @@ get metadata from get_metadata_from_delegation_response(delegation_res: &DelegationResponse): Object<Metadata> { +
public fun get_metadata_from_delegation_response(
+    delegation_res: &DelegationResponse
+): Object<Metadata> {
     delegation_res.metadata
 }
 
- - ## Function `get_validator_from_delegation_response` @@ -1455,19 +1208,18 @@ get validator from get_validator_from_delegation_response(delegation_res: &DelegationResponse): String { +
public fun get_validator_from_delegation_response(
+    delegation_res: &DelegationResponse
+): String {
     delegation_res.validator
 }
 
- - ## Function `get_share_from_delegation_response` @@ -1475,24 +1227,23 @@ get validator from DelegationResponse -
public fun get_share_from_delegation_response(delegation_res: &staking::DelegationResponse): u64
+
public fun get_share_from_delegation_response(delegation_res: &staking::DelegationResponse): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation -
public fun get_share_from_delegation_response(delegation_res: &DelegationResponse): u64 {
+
public fun get_share_from_delegation_response(
+    delegation_res: &DelegationResponse
+): BigDecimal {
     delegation_res.share
 }
 
-
- ## Function `get_unclaimed_reward_from_delegation_response` @@ -1505,19 +1256,18 @@ get unclaimed_reward from get_unclaimed_reward_from_delegation_response(delegation_res: &DelegationResponse): u64 { +
public fun get_unclaimed_reward_from_delegation_response(
+    delegation_res: &DelegationResponse
+): u64 {
     delegation_res.unclaimed_reward
 }
 
- - ## Function `get_metadata_from_unbonding_response` @@ -1530,19 +1280,18 @@ get metadata from get_metadata_from_unbonding_response(unbonding_res: &UnbondingResponse): Object<Metadata> { +
public fun get_metadata_from_unbonding_response(
+    unbonding_res: &UnbondingResponse
+): Object<Metadata> {
     unbonding_res.metadata
 }
 
- - ## Function `get_validator_from_unbonding_response` @@ -1555,19 +1304,18 @@ get validator from get_validator_from_unbonding_response(unbonding_res: &UnbondingResponse): String { +
public fun get_validator_from_unbonding_response(
+    unbonding_res: &UnbondingResponse
+): String {
     unbonding_res.validator
 }
 
- - ## Function `get_release_time_from_unbonding_response` @@ -1580,19 +1328,18 @@ get release_time from get_release_time_from_unbonding_response(unbonding_res: &UnbondingResponse): u64 { +
public fun get_release_time_from_unbonding_response(
+    unbonding_res: &UnbondingResponse
+): u64 {
     unbonding_res.release_time
 }
 
- - ## Function `get_unbonding_amount_from_unbonding_response` @@ -1605,44 +1352,18 @@ get unbonding_amount from get_unbonding_amount_from_unbonding_response(unbonding_res: &UnbondingResponse): u64 { +
public fun get_unbonding_amount_from_unbonding_response(
+    unbonding_res: &UnbondingResponse
+): u64 {
     unbonding_res.unbonding_amount
 }
 
- - - - -## Function `check_chain_permission` - -Check signer is chain - - -
fun check_chain_permission(chain: &signer)
-
- - - -
-Implementation - - -
fun check_chain_permission(chain: &signer) {
-    assert!(signer::address_of(chain) == @initia_std, error::permission_denied(EUNAUTHORIZED_CHAIN_OPERATION));
-}
-
- - - -
- ## Function `initialize_for_chain` @@ -1655,24 +1376,33 @@ Initialize, Make staking store -
-Implementation +##### Implementation -
public entry fun initialize_for_chain(chain: &signer, metadata: Object<Metadata>) acquires ModuleStore {
+
public entry fun initialize_for_chain(
+    chain: &signer, metadata: Object<Metadata>
+) acquires ModuleStore {
     check_chain_permission(chain);
 
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
 
-    assert!(!table::contains(&module_store.staking_states, metadata), error::already_exists(ESTAKING_STATE_ALREADY_EXISTS));
-    table::add(&mut module_store.staking_states, metadata, table::new());
+    assert!(
+        !table::contains(
+            &module_store.staking_states,
+            metadata
+        ),
+        error::already_exists(ESTAKING_STATE_ALREADY_EXISTS)
+    );
+    table::add(
+        &mut module_store.staking_states,
+        metadata,
+        table::new()
+    );
 }
 
-
- ## Function `slash_unbonding_for_chain` @@ -1680,49 +1410,62 @@ Initialize, Make staking store Slash unbonding coin -
public entry fun slash_unbonding_for_chain(chain: &signer, metadata: object::Object<fungible_asset::Metadata>, validator: string::String, fraction: string::String)
+
public entry fun slash_unbonding_for_chain(chain: &signer, metadata: object::Object<fungible_asset::Metadata>, validator: string::String, fraction: bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation
public entry fun slash_unbonding_for_chain(
     chain: &signer,
     metadata: Object<Metadata>,
     validator: String,
-    fraction: String
+    fraction: BigDecimal
 ) acquires ModuleStore {
     check_chain_permission(chain);
 
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let state = load_staking_state_mut(&mut module_store.staking_states, metadata, validator);
-
-    let fraction = decimal128::from_string(&fraction);
+    let state =
+        load_staking_state_mut(
+            &mut module_store.staking_states,
+            metadata,
+            validator
+        );
 
     let unbonding_amount = fungible_asset::balance(state.unbonding_coin_store);
-    let slash_amount = decimal128::mul_u64(&fraction, unbonding_amount);
+    let slash_amount = bigdecimal::mul_by_u64_truncate(fraction, unbonding_amount);
 
     if (slash_amount > 0) {
-        let unbonding_coin_store_signer = &object::generate_signer_for_extending(&state.unbonding_coin_store_ref);
-        let slash_coin = fungible_asset::withdraw(unbonding_coin_store_signer, state.unbonding_coin_store, slash_amount);
+        let unbonding_coin_store_signer =
+            &object::generate_signer_for_extending(
+                &state.unbonding_coin_store_ref
+            );
+        let slash_coin =
+            fungible_asset::withdraw(
+                unbonding_coin_store_signer,
+                state.unbonding_coin_store,
+                slash_amount
+            );
 
         // deposit to relayer for fund community pool
-        coin::deposit(@relayer, slash_coin);
+        // relayer is module address, so we need to use sudo_deposit
+        coin::sudo_deposit(@relayer, slash_coin);
         let staking_module = create_signer(@relayer);
 
         // fund to community pool
-        cosmos::fund_community_pool(&staking_module, metadata, slash_amount);
+        cosmos::fund_community_pool(
+            &staking_module,
+            metadata,
+            slash_amount
+        );
     }
 }
 
-
- ## Function `deposit_unbonding_coin_for_chain` @@ -1735,8 +1478,7 @@ Deposit unbonding coin to global store -
-Implementation +##### Implementation
public entry fun deposit_unbonding_coin_for_chain(
@@ -1747,7 +1489,10 @@ Deposit unbonding coin to global store
 ) acquires ModuleStore {
     check_chain_permission(chain);
 
-    assert!(vector::length(&validators) == vector::length(&amounts), error::invalid_argument(ELENGTH_MISMATCH));
+    assert!(
+        vector::length(&validators) == vector::length(&amounts),
+        error::invalid_argument(ELENGTH_MISMATCH)
+    );
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
     let staking_module = create_signer(@relayer);
 
@@ -1755,21 +1500,34 @@ Deposit unbonding coin to global store
     while (index < vector::length(&validators)) {
         let validator = *vector::borrow(&validators, index);
         let amount = *vector::borrow(&amounts, index);
-        let state = load_staking_state_mut(&mut module_store.staking_states, metadata, validator);
+        let state =
+            load_staking_state_mut(
+                &mut module_store.staking_states,
+                metadata,
+                validator
+            );
 
         // calculate share
-        let total_unbonding_amount = fungible_asset::balance(state.unbonding_coin_store);
-        let share_amount_ratio = if (total_unbonding_amount == 0) {
-            decimal128::one()
-        } else {
-            decimal128::from_ratio(state.unbonding_share, (total_unbonding_amount as u128))
-        };
-
-        let share_diff = decimal128::mul_u64(&share_amount_ratio, amount);
-        state.unbonding_share = state.unbonding_share + (share_diff as u128);
+        let total_unbonding_amount =
+            fungible_asset::balance(state.unbonding_coin_store);
+        let share_amount_ratio =
+            if (total_unbonding_amount == 0) {
+                bigdecimal::one()
+            } else {
+                bigdecimal::div_by_u64(state.unbonding_share, total_unbonding_amount)
+            };
+
+        let share_diff =
+            bigdecimal::mul(
+                share_amount_ratio, bigdecimal::from_ratio_u64(amount, 1)
+            );
+        state.unbonding_share = bigdecimal::add(state.unbonding_share, share_diff);
 
         let unbonding_coin = coin::withdraw(&staking_module, metadata, amount);
-        fungible_asset::deposit(state.unbonding_coin_store, unbonding_coin);
+        fungible_asset::deposit(
+            state.unbonding_coin_store,
+            unbonding_coin
+        );
 
         index = index + 1;
     }
@@ -1778,8 +1536,6 @@ Deposit unbonding coin to global store
 
 
 
-
- ## Function `deposit_reward_for_chain` @@ -1792,19 +1548,21 @@ Deposit staking reward, and update reward_index -
-Implementation +##### Implementation
public entry fun deposit_reward_for_chain(
     chain: &signer,
     metadata: Object<Metadata>,
     validators: vector<String>,
-    reward_amounts: vector<u64>,
+    reward_amounts: vector<u64>
 ) acquires ModuleStore {
     check_chain_permission(chain);
 
-    assert!(vector::length(&validators) == vector::length(&reward_amounts), error::invalid_argument(ELENGTH_MISMATCH));
+    assert!(
+        vector::length(&validators) == vector::length(&reward_amounts),
+        error::invalid_argument(ELENGTH_MISMATCH)
+    );
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
     let staking_module = create_signer(@relayer);
     let reward_metadata = reward_metadata();
@@ -1813,12 +1571,21 @@ Deposit staking reward, and update reward_index
     while (index < vector::length(&validators)) {
         let validator = *vector::borrow(&validators, index);
         let reward_amount = *vector::borrow(&reward_amounts, index);
-        let reward = coin::withdraw(&staking_module, reward_metadata, reward_amount);
+        let reward = coin::withdraw(
+            &staking_module,
+            reward_metadata,
+            reward_amount
+        );
 
-        let state = load_staking_state_mut(&mut module_store.staking_states, metadata, validator);
-        state.reward_index = decimal128::add(
-            &state.reward_index,
-            &decimal128::from_ratio((reward_amount as u128), state.total_share),
+        let state =
+            load_staking_state_mut(
+                &mut module_store.staking_states,
+                metadata,
+                validator
+            );
+        state.reward_index = bigdecimal::add(
+            state.reward_index,
+            bigdecimal::rev(bigdecimal::div_by_u64(state.total_share, reward_amount))
         );
 
         fungible_asset::deposit(state.reward_coin_store, reward);
@@ -1830,8 +1597,6 @@ Deposit staking reward, and update reward_index
 
 
 
-
- ## Function `is_account_registered` @@ -1844,8 +1609,7 @@ Check the DelegationStore is already exist -
-Implementation +##### Implementation
public fun is_account_registered(account_addr: address): bool {
@@ -1855,8 +1619,6 @@ Check the DelegationStore is already exist
 
 
 
-
- ## Function `register` @@ -1869,20 +1631,19 @@ Register an account delegation store -
-Implementation +##### Implementation
public entry fun register(account: &signer) {
     let account_addr = signer::address_of(account);
     assert!(
         !is_account_registered(account_addr),
-        error::already_exists(EDELEGATION_STORE_ALREADY_EXISTS),
+        error::already_exists(EDELEGATION_STORE_ALREADY_EXISTS)
     );
 
     let delegation_store = DelegationStore {
         delegations: table::new<Object<Metadata>, Table<String, Delegation>>(),
-        unbondings: table::new<Object<Metadata>, Table<UnbondingKey, Unbonding>>(),
+        unbondings: table::new<Object<Metadata>, Table<UnbondingKey, Unbonding>>()
     };
 
     move_to(account, delegation_store);
@@ -1891,8 +1652,6 @@ Register an account delegation store
 
 
 
-
- ## Function `delegate_script` @@ -1905,15 +1664,14 @@ Delegate coin to a validator and deposit reward to signer. -
-Implementation +##### Implementation
public entry fun delegate_script(
     account: &signer,
     metadata: Object<Metadata>,
     validator: String,
-    amount: u64,
+    amount: u64
 ) acquires DelegationStore, ModuleStore {
     let account_addr = signer::address_of(account);
     if (!is_account_registered(account_addr)) {
@@ -1929,7 +1687,7 @@ Delegate coin to a validator and deposit reward to signer.
         RewardEvent {
             account: account_addr,
             metadata,
-            amount: fungible_asset::amount(&reward),
+            amount: fungible_asset::amount(&reward)
         }
     );
 
@@ -1939,8 +1697,6 @@ Delegate coin to a validator and deposit reward to signer.
 
 
 
-
- ## Function `delegate` @@ -1953,64 +1709,92 @@ Delegate a fa to a validator. -
-Implementation +##### Implementation
public fun delegate(validator: String, fa: FungibleAsset): Delegation acquires ModuleStore {
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
     let metadata = fungible_asset::asset_metadata(&fa);
 
-    assert!(table::contains(&module_store.staking_states, metadata), error::not_found(ESTAKING_STATE_NOT_EXISTS));
+    assert!(
+        table::contains(
+            &module_store.staking_states,
+            metadata
+        ),
+        error::not_found(ESTAKING_STATE_NOT_EXISTS)
+    );
     let states = table::borrow_mut(&mut module_store.staking_states, metadata);
 
     if (!table::contains(states, validator)) {
         let reward_coin_store_ref = &object::create_object(@initia_std, false);
         let unbonding_coin_store_ref = &object::create_object(@initia_std, false);
 
-        let reward_coin_store_address = object::address_from_constructor_ref(reward_coin_store_ref);
-        let reward_coin_store = primary_fungible_store::create_primary_store(reward_coin_store_address, reward_metadata());
+        let reward_coin_store_address =
+            object::address_from_constructor_ref(reward_coin_store_ref);
+        let reward_coin_store =
+            primary_fungible_store::create_primary_store(
+                reward_coin_store_address,
+                reward_metadata()
+            );
+
+        let unbonding_coin_store_address =
+            object::address_from_constructor_ref(unbonding_coin_store_ref);
+        let unbonding_coin_store =
+            primary_fungible_store::create_primary_store(
+                unbonding_coin_store_address,
+                metadata
+            );
 
-        let unbonding_coin_store_address = object::address_from_constructor_ref(unbonding_coin_store_ref);
-        let unbonding_coin_store = primary_fungible_store::create_primary_store(unbonding_coin_store_address, metadata);
-
-        table::add (
+        table::add(
             states,
             validator,
             StakingState {
                 metadata,
                 validator,
-                total_share: 0,
-                unbonding_share: 0,
-                reward_index: decimal128::zero(),
-                reward_coin_store_ref: object::generate_extend_ref(reward_coin_store_ref),
-                unbonding_coin_store_ref: object::generate_extend_ref(unbonding_coin_store_ref),
+                total_share: bigdecimal::zero(),
+                unbonding_share: bigdecimal::zero(),
+                reward_index: bigdecimal::zero(),
+                reward_coin_store_ref: object::generate_extend_ref(
+                    reward_coin_store_ref
+                ),
+                unbonding_coin_store_ref: object::generate_extend_ref(
+                    unbonding_coin_store_ref
+                ),
                 reward_coin_store,
-                unbonding_coin_store,
+                unbonding_coin_store
             }
         )
     };
 
-    let share_diff = delegate_internal(*string::bytes(&validator), &metadata, fungible_asset::amount(&fa));
-    let state = load_staking_state_mut(&mut module_store.staking_states, metadata, validator);
-    state.total_share = state.total_share + (share_diff as u128);
+    let share_diff =
+        delegate_internal(
+            *string::bytes(&validator),
+            &metadata,
+            fungible_asset::amount(&fa)
+        );
+    let state =
+        load_staking_state_mut(
+            &mut module_store.staking_states,
+            metadata,
+            validator
+        );
+    state.total_share = bigdecimal::add(state.total_share, share_diff);
 
     // deposit to relayer
-    coin::deposit(@relayer, fa);
+    // relayer is module address, so we need to use sudo_deposit
+    coin::sudo_deposit(@relayer, fa);
 
     Delegation {
         metadata,
         validator,
         share: share_diff,
-        reward_index: state.reward_index,
+        reward_index: state.reward_index
     }
 }
 
-
- ## Function `undelegate_script` @@ -2024,24 +1808,29 @@ unbonding amount can be slightly different with input amount due to round error. -
-Implementation +##### Implementation
public entry fun undelegate_script(
     account: &signer,
     metadata: Object<Metadata>,
     validator: String,
-    amount: u64,
+    amount: u64
 ) acquires DelegationStore, ModuleStore {
+
     let account_addr = signer::address_of(account);
 
     assert!(
         is_account_registered(account_addr),
-        error::not_found(EDELEGATION_STORE_NOT_EXISTS),
+        error::not_found(EDELEGATION_STORE_NOT_EXISTS)
+    );
+
+    let share = amount_to_share(
+        *string::bytes(&validator),
+        &metadata,
+        amount
     );
 
-    let share = amount_to_share(*string::bytes(&validator), &metadata, amount);
     let delegation = withdraw_delegation(account, metadata, validator, share);
     let (reward, unbonding) = undelegate(delegation);
 
@@ -2049,7 +1838,7 @@ unbonding amount can be slightly different with input amount due to round error.
         RewardEvent {
             account: account_addr,
             metadata,
-            amount: fungible_asset::amount(&reward),
+            amount: fungible_asset::amount(&reward)
         }
     );
 
@@ -2060,8 +1849,6 @@ unbonding amount can be slightly different with input amount due to round error.
 
 
 
-
- ## Function `undelegate` @@ -2073,27 +1860,42 @@ unbonding amount can be slightly different with input amount due to round error. -
-Implementation +##### Implementation -
public fun undelegate(
-    delegation: Delegation,
-): (FungibleAsset, Unbonding) acquires ModuleStore {
+
public fun undelegate(delegation: Delegation): (FungibleAsset, Unbonding) acquires ModuleStore {
     let share = delegation.share;
     let validator = delegation.validator;
     let metadata = delegation.metadata;
 
-    let (unbonding_amount, release_time) = undelegate_internal(*string::bytes(&validator), &metadata, share);
+    let (unbonding_amount, release_time) =
+        undelegate_internal(
+            *string::bytes(&validator),
+            &metadata,
+            &share
+        );
     let reward = destroy_delegation_and_extract_reward(delegation);
 
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let state = load_staking_state_mut(&mut module_store.staking_states, metadata, validator);
+    let state =
+        load_staking_state_mut(
+            &mut module_store.staking_states,
+            metadata,
+            validator
+        );
 
-    assert!(state.total_share >= (share as u128), error::invalid_state(EINSUFFICIENT_UNBONDING_DELEGATION_TOTAL_SHARE));
-    state.total_share = state.total_share - (share as u128);
+    assert!(
+        bigdecimal::ge(state.total_share, share),
+        error::invalid_state(EINSUFFICIENT_UNBONDING_DELEGATION_TOTAL_SHARE)
+    );
+    state.total_share = bigdecimal::sub(state.total_share, share);
 
-    let unbonding_share = unbonding_share_from_amount(metadata, validator, unbonding_amount);
+    let unbonding_share =
+        unbonding_share_from_amount(
+            metadata,
+            validator,
+            unbonding_amount
+        );
     let unbonding = Unbonding { metadata, validator, unbonding_share, release_time };
 
     (reward, unbonding)
@@ -2102,8 +1904,6 @@ unbonding amount can be slightly different with input amount due to round error.
 
 
 
-
- ## Function `claim_unbonding_script` @@ -2116,8 +1916,7 @@ Claim unbonding_coin from expired unbonding. -
-Implementation +##### Implementation
public entry fun claim_unbonding_script(
@@ -2130,12 +1929,24 @@ Claim unbonding_coin from expired unbonding.
 
     assert!(
         is_account_registered(account_addr),
-        error::not_found(EDELEGATION_STORE_NOT_EXISTS),
+        error::not_found(EDELEGATION_STORE_NOT_EXISTS)
     );
 
     // withdraw unbonding all
-    let unbonding_info = get_unbonding(account_addr, metadata, validator, release_time);
-    let unbonding = withdraw_unbonding(account, metadata, validator, release_time, unbonding_info.unbonding_amount);
+    let unbonding_info = get_unbonding(
+        account_addr,
+        metadata,
+        validator,
+        release_time
+    );
+    let unbonding =
+        withdraw_unbonding(
+            account,
+            metadata,
+            validator,
+            release_time,
+            unbonding_info.unbonding_amount
+        );
     let unbonding_coin = claim_unbonding(unbonding);
     coin::deposit(account_addr, unbonding_coin)
 }
@@ -2143,8 +1954,6 @@ Claim unbonding_coin from expired unbonding.
 
 
 
-
- ## Function `claim_reward_script` @@ -2156,31 +1965,33 @@ Claim unbonding_coin from expired unbonding. -
-Implementation +##### Implementation
public entry fun claim_reward_script(
-    account: &signer,
-    metadata: Object<Metadata>,
-    validator: String
+    account: &signer, metadata: Object<Metadata>, validator: String
 ) acquires DelegationStore, ModuleStore {
     let account_addr = signer::address_of(account);
 
     assert!(
         is_account_registered(account_addr),
-        error::not_found(EDELEGATION_STORE_NOT_EXISTS),
+        error::not_found(EDELEGATION_STORE_NOT_EXISTS)
     );
 
     let delegation_store = borrow_global_mut<DelegationStore>(account_addr);
-    let delegation = load_delegation_mut(&mut delegation_store.delegations, metadata, validator);
+    let delegation =
+        load_delegation_mut(
+            &mut delegation_store.delegations,
+            metadata,
+            validator
+        );
     let reward = claim_reward(delegation);
 
     event::emit(
         RewardEvent {
             account: account_addr,
             metadata,
-            amount: fungible_asset::amount(&reward),
+            amount: fungible_asset::amount(&reward)
         }
     );
 
@@ -2190,8 +2001,6 @@ Claim unbonding_coin from expired unbonding.
 
 
 
-
- ## Function `claim_reward` @@ -2204,26 +2013,35 @@ Claim staking reward from the specified validator. -
-Implementation +##### Implementation -
public fun claim_reward(
-    delegation: &mut Delegation
-): FungibleAsset acquires ModuleStore {
+
public fun claim_reward(delegation: &mut Delegation): FungibleAsset acquires ModuleStore {
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
 
     let metadata = delegation.metadata;
     let validator = delegation.validator;
-    let state = load_staking_state(&module_store.staking_states, metadata, validator);
+    let state = load_staking_state(
+        &module_store.staking_states,
+        metadata,
+        validator
+    );
 
     let reward_amount = calculate_reward(delegation, state);
-    let reward = if (reward_amount == 0)  {
-        fungible_asset::zero(reward_metadata())
-    } else {
-        let reward_coin_store_signer = &object::generate_signer_for_extending(&state.reward_coin_store_ref);
-        fungible_asset::withdraw(reward_coin_store_signer, state.reward_coin_store, reward_amount)
-    };
+    let reward =
+        if (reward_amount == 0) {
+            fungible_asset::zero(reward_metadata())
+        } else {
+            let reward_coin_store_signer =
+                &object::generate_signer_for_extending(
+                    &state.reward_coin_store_ref
+                );
+            fungible_asset::withdraw(
+                reward_coin_store_signer,
+                state.reward_coin_store,
+                reward_amount
+            )
+        };
 
     delegation.reward_index = state.reward_index;
 
@@ -2233,39 +2051,6 @@ Claim staking reward from the specified validator.
 
 
 
-
- - - -## Function `calculate_reward` - -Calculate unclaimed reward - - -
fun calculate_reward(delegation: &staking::Delegation, state: &staking::StakingState): u64
-
- - - -
-Implementation - - -
fun calculate_reward(delegation: &Delegation, state: &StakingState): u64 {
-    assert!(
-        delegation.metadata == state.metadata,
-        error::invalid_argument(EMETADATA_MISMATCH),
-    );
-
-    let index_diff = decimal128::sub(&state.reward_index, &delegation.reward_index);
-    decimal128::mul_u64(&index_diff, delegation.share)
-}
-
- - - -
- ## Function `empty_delegation` @@ -2279,24 +2064,23 @@ return empty delegation resource -
-Implementation +##### Implementation -
public fun empty_delegation(metadata: Object<Metadata>, validator: String): Delegation {
+
public fun empty_delegation(
+    metadata: Object<Metadata>, validator: String
+): Delegation {
     Delegation {
         metadata,
         validator,
-        share: 0,
-        reward_index: decimal128::zero(),
+        share: bigdecimal::zero(),
+        reward_index: bigdecimal::zero()
     }
 }
 
-
- ## Function `get_metadata_from_delegation` @@ -2309,8 +2093,7 @@ Get metadata from -Implementation +##### Implementation
public fun get_metadata_from_delegation(delegation: &Delegation): Object<Metadata> {
@@ -2320,8 +2103,6 @@ Get metadata from 
-
 
 
 ## Function `get_validator_from_delegation`
@@ -2334,8 +2115,7 @@ Get validator from get_validator_from_delegation(delegation: &Delegation): String {
@@ -2345,8 +2125,6 @@ Get validator from 
 
 ## Function `get_share_from_delegation`
@@ -2354,24 +2132,21 @@ Get validator from Delegation
 
 
-
public fun get_share_from_delegation(delegation: &staking::Delegation): u64
+
public fun get_share_from_delegation(delegation: &staking::Delegation): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation -
public fun get_share_from_delegation(delegation: &Delegation): u64 {
+
public fun get_share_from_delegation(delegation: &Delegation): BigDecimal {
     delegation.share
 }
 
-
- ## Function `destroy_empty_delegation` @@ -2384,20 +2159,21 @@ Destory empty delegation -
-Implementation +##### Implementation
public fun destroy_empty_delegation(delegation: Delegation) {
-    assert!(delegation.share == 0, error::invalid_argument(ENOT_EMPTY));
-    let Delegation { metadata: _, validator: _, share: _, reward_index: _ } = delegation;
+    assert!(
+        bigdecimal::is_zero(delegation.share),
+        error::invalid_argument(ENOT_EMPTY)
+    );
+    let Delegation { metadata: _, validator: _, share: _, reward_index: _ } =
+        delegation;
 }
 
-
- ## Function `deposit_delegation` @@ -2410,17 +2186,15 @@ Deposit the delegation into recipient's account. -
-Implementation +##### Implementation
public fun deposit_delegation(
-    account_addr: address,
-    delegation: Delegation,
+    account_addr: address, delegation: Delegation
 ): FungibleAsset acquires DelegationStore, ModuleStore {
     assert!(
         is_account_registered(account_addr),
-        error::not_found(EDELEGATION_STORE_NOT_EXISTS),
+        error::not_found(EDELEGATION_STORE_NOT_EXISTS)
     );
 
     let metadata = delegation.metadata;
@@ -2428,27 +2202,40 @@ Deposit the delegation into recipient's account.
 
     let delegation_store = borrow_global_mut<DelegationStore>(account_addr);
     if (!table::contains(&delegation_store.delegations, metadata)) {
-        table::add(&mut delegation_store.delegations, metadata, table::new());
+        table::add(
+            &mut delegation_store.delegations,
+            metadata,
+            table::new()
+        );
     };
 
     let delegations = table::borrow_mut(&mut delegation_store.delegations, metadata);
     if (!table::contains(delegations, validator)) {
         table::add(
-            delegations, validator,
-            empty_delegation(delegation.metadata, delegation.validator),
+            delegations,
+            validator,
+            empty_delegation(
+                delegation.metadata,
+                delegation.validator
+            )
         );
     };
 
-    event::emit (
+    event::emit(
         DelegationDepositEvent {
             account: account_addr,
             metadata: delegation.metadata,
             share: delegation.share,
-            validator: delegation.validator,
+            validator: delegation.validator
         }
     );
 
-    let dst_delegation = load_delegation_mut(&mut delegation_store.delegations, metadata, validator);
+    let dst_delegation =
+        load_delegation_mut(
+            &mut delegation_store.delegations,
+            metadata,
+            validator
+        );
 
     merge_delegation(dst_delegation, delegation)
 }
@@ -2456,8 +2243,6 @@ Deposit the delegation into recipient's account.
 
 
 
-
- ## Function `withdraw_delegation` @@ -2465,43 +2250,46 @@ Deposit the delegation into recipient's account. Withdraw specified share from delegation. -
public fun withdraw_delegation(account: &signer, metadata: object::Object<fungible_asset::Metadata>, validator: string::String, share: u64): staking::Delegation
+
public fun withdraw_delegation(account: &signer, metadata: object::Object<fungible_asset::Metadata>, validator: string::String, share: bigdecimal::BigDecimal): staking::Delegation
 
-
-Implementation +##### Implementation
public fun withdraw_delegation(
     account: &signer,
     metadata: Object<Metadata>,
     validator: String,
-    share: u64,
+    share: BigDecimal
 ): Delegation acquires DelegationStore {
     let account_addr = signer::address_of(account);
 
     assert!(
         is_account_registered(account_addr),
-        error::not_found(EDELEGATION_STORE_NOT_EXISTS),
+        error::not_found(EDELEGATION_STORE_NOT_EXISTS)
     );
 
     let delegation_store = borrow_global_mut<DelegationStore>(account_addr);
-    let delegation = load_delegation_mut(&mut delegation_store.delegations, metadata, validator);
+    let delegation =
+        load_delegation_mut(
+            &mut delegation_store.delegations,
+            metadata,
+            validator
+        );
 
     event::emit(
-        DelegationWithdrawEvent {
-            account: account_addr,
-            metadata,
-            share,
-            validator,
-        }
+        DelegationWithdrawEvent { account: account_addr, metadata, share, validator }
     );
 
     // If withdraw all, remove delegation
     if (delegation.share == share) {
-        let delegations = table::borrow_mut(&mut delegation_store.delegations, metadata);
+        let delegations =
+            table::borrow_mut(
+                &mut delegation_store.delegations,
+                metadata
+            );
         table::remove(delegations, validator)
         // Else extract
     } else {
@@ -2512,8 +2300,6 @@ Withdraw specified share from delegation.
 
 
 
-
- ## Function `extract_delegation` @@ -2521,33 +2307,35 @@ Withdraw specified share from delegation. Extracts specified share of delegatiion from the passed-in delegation. -
public fun extract_delegation(delegation: &mut staking::Delegation, share: u64): staking::Delegation
+
public fun extract_delegation(delegation: &mut staking::Delegation, share: bigdecimal::BigDecimal): staking::Delegation
 
-
-Implementation +##### Implementation -
public fun extract_delegation(delegation: &mut Delegation, share: u64): Delegation {
-    assert!(delegation.share >= share, error::invalid_argument(EINSUFFICIENT_AMOUNT));
+
public fun extract_delegation(
+    delegation: &mut Delegation, share: BigDecimal
+): Delegation {
+    assert!(
+        bigdecimal::ge(delegation.share, share),
+        error::invalid_argument(EINSUFFICIENT_AMOUNT)
+    );
 
     // Total share is invariant and reward_indexes are same btw given and new one so no need to update `reward_index`.
-    delegation.share = delegation.share - share;
+    delegation.share = bigdecimal::sub(delegation.share, share);
     Delegation {
         metadata: delegation.metadata,
         validator: delegation.validator,
         reward_index: delegation.reward_index,
-        share,
+        share
     }
 }
 
-
- ## Function `merge_delegation` @@ -2561,30 +2349,26 @@ to the sum of the two shares (dst_delegation and source_deleg -
-Implementation +##### Implementation
public fun merge_delegation(
-    dst_delegation: &mut Delegation,
-    source_delegation: Delegation
+    dst_delegation: &mut Delegation, source_delegation: Delegation
 ): FungibleAsset acquires ModuleStore {
     assert!(
         dst_delegation.metadata == source_delegation.metadata,
-        error::invalid_argument(EMETADATA_MISMATCH),
+        error::invalid_argument(EMETADATA_MISMATCH)
     );
     assert!(
         dst_delegation.validator == source_delegation.validator,
-        error::invalid_argument(EVALIDATOR_MISMATCH),
+        error::invalid_argument(EVALIDATOR_MISMATCH)
     );
 
-    spec {
-        assume dst_delegation.share + source_delegation.share <= MAX_U64;
-    };
-
     let reward = claim_reward(dst_delegation);
 
-    dst_delegation.share = dst_delegation.share + source_delegation.share;
+    dst_delegation.share = bigdecimal::add(
+        dst_delegation.share, source_delegation.share
+    );
     let source_reward = destroy_delegation_and_extract_reward(source_delegation);
 
     fungible_asset::merge(&mut reward, source_reward);
@@ -2595,121 +2379,6 @@ to the sum of the two shares (dst_delegation and source_deleg
 
 
 
-
- - - -## Function `destroy_delegation_and_extract_reward` - -Destroy delegation and extract reward from delegation - - -
fun destroy_delegation_and_extract_reward(delegation: staking::Delegation): fungible_asset::FungibleAsset
-
- - - -
-Implementation - - -
fun destroy_delegation_and_extract_reward (
-    delegation: Delegation
-): FungibleAsset acquires ModuleStore {
-    let metadata = delegation.metadata;
-    let validator = delegation.validator;
-
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let state = load_staking_state(&module_store.staking_states, metadata, validator);
-
-    let reward_amount = calculate_reward(&delegation, state);
-    let reward = if (reward_amount == 0) {
-        fungible_asset::zero(reward_metadata())
-    } else {
-        let reward_coin_store_signer = &object::generate_signer_for_extending(&state.reward_coin_store_ref);
-        fungible_asset::withdraw(reward_coin_store_signer, state.reward_coin_store, reward_amount)
-    };
-
-    let Delegation { metadata: _, share: _, validator: _, reward_index: _ } = delegation;
-
-    reward
-}
-
- - - -
- - - -## Function `unbonding_share_from_amount` - -For unbonding object - - - -
fun unbonding_share_from_amount(metadata: object::Object<fungible_asset::Metadata>, validator: string::String, unbonding_amount: u64): u64
-
- - - -
-Implementation - - -
fun unbonding_share_from_amount(metadata: Object<Metadata>, validator: String, unbonding_amount: u64): u64 acquires ModuleStore {
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let state = load_staking_state(&module_store.staking_states, metadata, validator);
-
-    let total_unbonding_amount = fungible_asset::balance(state.unbonding_coin_store);
-    let share_amount_ratio = if (total_unbonding_amount == 0) {
-        decimal128::one()
-    } else {
-        decimal128::from_ratio(state.unbonding_share, (total_unbonding_amount as u128))
-    };
-
-    decimal128::mul_u64(&share_amount_ratio, unbonding_amount)
-}
-
- - - -
- - - -## Function `unbonding_amount_from_share` - - - -
fun unbonding_amount_from_share(metadata: object::Object<fungible_asset::Metadata>, validator: string::String, unbonding_share: u64): u64
-
- - - -
-Implementation - - -
fun unbonding_amount_from_share(metadata: Object<Metadata>, validator: String, unbonding_share: u64): u64 acquires ModuleStore {
-    let module_store = borrow_global<ModuleStore>(@initia_std);
-    let state = load_staking_state(&module_store.staking_states, metadata, validator);
-
-    let total_unbonding_amount = fungible_asset::balance(state.unbonding_coin_store);
-    let amount_share_ratio = if (state.unbonding_share == 0) {
-        decimal128::one()
-    } else {
-        decimal128::from_ratio((total_unbonding_amount as u128), state.unbonding_share)
-    };
-
-    decimal128::mul_u64(&amount_share_ratio, unbonding_share)
-}
-
- - - -
- ## Function `empty_unbonding` @@ -2722,24 +2391,23 @@ return empty unbonding resource -
-Implementation +##### Implementation -
public fun empty_unbonding(metadata: Object<Metadata>, validator: String, release_time: u64): Unbonding {
+
public fun empty_unbonding(
+    metadata: Object<Metadata>, validator: String, release_time: u64
+): Unbonding {
     Unbonding {
         metadata,
         validator,
-        unbonding_share: 0,
-        release_time,
+        unbonding_share: bigdecimal::zero(),
+        release_time
     }
 }
 
-
- ## Function `get_metadata_from_unbonding` @@ -2752,8 +2420,7 @@ Get metadata from -
-Implementation +##### Implementation
public fun get_metadata_from_unbonding(unbonding: &Unbonding): Object<Metadata> {
@@ -2763,8 +2430,6 @@ Get metadata from 
 
 
 
-
- ## Function `get_validator_from_unbonding` @@ -2777,8 +2442,7 @@ Get validator from -Implementation +##### Implementation
public fun get_validator_from_unbonding(unbonding: &Unbonding): String {
@@ -2788,8 +2452,6 @@ Get validator from 
-
 
 
 ## Function `get_release_time_from_unbonding`
@@ -2802,8 +2464,7 @@ Get release_time from get_release_time_from_unbonding(unbonding: &Unbonding): u64 {
@@ -2813,8 +2474,6 @@ Get release_time from 
 
 ## Function `get_unbonding_share_from_unbonding`
@@ -2822,24 +2481,21 @@ Get release_time from Unbonding
 
 
-
public fun get_unbonding_share_from_unbonding(unbonding: &staking::Unbonding): u64
+
public fun get_unbonding_share_from_unbonding(unbonding: &staking::Unbonding): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation -
public fun get_unbonding_share_from_unbonding(unbonding: &Unbonding): u64 {
+
public fun get_unbonding_share_from_unbonding(unbonding: &Unbonding): BigDecimal {
     unbonding.unbonding_share
 }
 
-
- ## Function `get_unbonding_amount_from_unbonding` @@ -2852,21 +2508,20 @@ Get unbonding_amount from get_unbonding_amount_from_unbonding( - unbonding: &Unbonding -): u64 acquires ModuleStore { - unbonding_amount_from_share(unbonding.metadata, unbonding.validator, unbonding.unbonding_share) +
public fun get_unbonding_amount_from_unbonding(unbonding: &Unbonding): u64 acquires ModuleStore {
+    unbonding_amount_from_share(
+        unbonding.metadata,
+        unbonding.validator,
+        unbonding.unbonding_share
+    )
 }
 
- - ## Function `destroy_empty_unbonding` @@ -2879,20 +2534,21 @@ Destory empty unbonding -
-Implementation +##### Implementation
public fun destroy_empty_unbonding(unbonding: Unbonding) {
-    assert!(unbonding.unbonding_share == 0, error::invalid_argument(ENOT_EMPTY));
-    let Unbonding { metadata: _, validator: _, unbonding_share: _, release_time: _ } = unbonding;
+    assert!(
+        bigdecimal::is_zero(unbonding.unbonding_share),
+        error::invalid_argument(ENOT_EMPTY)
+    );
+    let Unbonding { metadata: _, validator: _, unbonding_share: _, release_time: _ } =
+        unbonding;
 }
 
-
- ## Function `deposit_unbonding` @@ -2905,36 +2561,39 @@ Deposit the unbonding into recipient's account. -
-Implementation +##### Implementation
public fun deposit_unbonding(
-    account_addr: address,
-    unbonding: Unbonding
+    account_addr: address, unbonding: Unbonding
 ) acquires DelegationStore {
     assert!(
         is_account_registered(account_addr),
-        error::not_found(EDELEGATION_STORE_NOT_EXISTS),
+        error::not_found(EDELEGATION_STORE_NOT_EXISTS)
     );
 
     let metadata = unbonding.metadata;
     let validator = unbonding.validator;
     let release_time = unbonding.release_time;
 
-    let key = UnbondingKey {
-        validator,
-        release_time,
-    };
+    let key = UnbondingKey { validator, release_time };
 
     let delegation_store = borrow_global_mut<DelegationStore>(account_addr);
     if (!table::contains(&delegation_store.unbondings, metadata)) {
-        table::add(&mut delegation_store.unbondings, metadata, table::new());
+        table::add(
+            &mut delegation_store.unbondings,
+            metadata,
+            table::new()
+        );
     };
 
     let unbondings = table::borrow_mut(&mut delegation_store.unbondings, metadata);
     if (!table::contains(unbondings, key)) {
-        table::add(unbondings, key, empty_unbonding(metadata, validator, release_time));
+        table::add(
+            unbondings,
+            key,
+            empty_unbonding(metadata, validator, release_time)
+        );
     };
 
     event::emit(
@@ -2943,7 +2602,7 @@ Deposit the unbonding into recipient's account.
             metadata,
             validator,
             share: unbonding.unbonding_share,
-            release_time,
+            release_time
         }
     );
 
@@ -2954,8 +2613,6 @@ Deposit the unbonding into recipient's account.
 
 
 
-
- ## Function `withdraw_unbonding` @@ -2968,8 +2625,7 @@ Withdraw specifed amount of unbonding_amount from the unbonding. -
-Implementation +##### Implementation
public fun withdraw_unbonding(
@@ -2977,17 +2633,23 @@ Withdraw specifed amount of unbonding_amount from the unbonding.
     metadata: Object<Metadata>,
     validator: String,
     release_time: u64,
-    amount: u64,
+    amount: u64
 ): Unbonding acquires DelegationStore, ModuleStore {
     let account_addr = signer::address_of(account);
 
     assert!(
         is_account_registered(account_addr),
-        error::not_found(EDELEGATION_STORE_NOT_EXISTS),
+        error::not_found(EDELEGATION_STORE_NOT_EXISTS)
     );
 
     let delegation_store = borrow_global_mut<DelegationStore>(account_addr);
-    let unbonding = load_unbonding_mut(&mut delegation_store.unbondings, metadata, validator, release_time);
+    let unbonding =
+        load_unbonding_mut(
+            &mut delegation_store.unbondings,
+            metadata,
+            validator,
+            release_time
+        );
 
     event::emit(
         UnbondingWithdrawEvent {
@@ -2995,19 +2657,22 @@ Withdraw specifed amount of unbonding_amount from the unbonding.
             metadata,
             validator,
             share: unbonding.unbonding_share,
-            release_time: unbonding.release_time,
+            release_time: unbonding.release_time
         }
     );
 
     let share = unbonding_share_from_amount(metadata, validator, amount);
     if (unbonding.unbonding_share == share) {
         // If withdraw all, remove unbonding
-        let unbondings = table::borrow_mut(&mut delegation_store.unbondings, metadata);
+        let unbondings = table::borrow_mut(
+            &mut delegation_store.unbondings,
+            metadata
+        );
 
-        table::remove(unbondings, UnbondingKey {
-            validator,
-            release_time,
-        })
+        table::remove(
+            unbondings,
+            UnbondingKey { validator, release_time }
+        )
     } else {
         // Else extract
         extract_unbonding(unbonding, share)
@@ -3017,8 +2682,6 @@ Withdraw specifed amount of unbonding_amount from the unbonding.
 
 
 
-
- ## Function `extract_unbonding` @@ -3026,30 +2689,34 @@ Withdraw specifed amount of unbonding_amount from the unbonding. Extracts specified amount of unbonding from the passed-in unbonding. -
public fun extract_unbonding(unbonding: &mut staking::Unbonding, share: u64): staking::Unbonding
+
public fun extract_unbonding(unbonding: &mut staking::Unbonding, share: bigdecimal::BigDecimal): staking::Unbonding
 
-
-Implementation +##### Implementation -
public fun extract_unbonding(unbonding: &mut Unbonding, share: u64): Unbonding {
+
public fun extract_unbonding(
+    unbonding: &mut Unbonding, share: BigDecimal
+): Unbonding {
     assert!(
-        unbonding.unbonding_share >= share,
-        error::invalid_argument(EINSUFFICIENT_AMOUNT),
+        bigdecimal::ge(unbonding.unbonding_share, share),
+        error::invalid_argument(EINSUFFICIENT_AMOUNT)
     );
 
-    unbonding.unbonding_share = unbonding.unbonding_share - share;
-    Unbonding { metadata: unbonding.metadata, validator: unbonding.validator, unbonding_share: share, release_time: unbonding.release_time }
+    unbonding.unbonding_share = bigdecimal::sub(unbonding.unbonding_share, share);
+    Unbonding {
+        metadata: unbonding.metadata,
+        validator: unbonding.validator,
+        unbonding_share: share,
+        release_time: unbonding.release_time
+    }
 }
 
-
- ## Function `merge_unbonding` @@ -3064,31 +2731,35 @@ will be merged into the unbonding_coin of the dst_unbonding. -
-Implementation +##### Implementation
public fun merge_unbonding(
-    dst_unbonding: &mut Unbonding,
-    source_unbonding: Unbonding
+    dst_unbonding: &mut Unbonding, source_unbonding: Unbonding
 ) {
-    assert!(dst_unbonding.metadata == source_unbonding.metadata, error::invalid_argument(EMETADATA_MISMATCH));
-    assert!(dst_unbonding.validator == source_unbonding.validator, error::invalid_argument(EVALIDATOR_MISMATCH));
-    assert!(dst_unbonding.release_time >= source_unbonding.release_time, error::invalid_argument(ERELEASE_TIME));
-
-    spec {
-        assume dst_unbonding.unbonding_share + source_unbonding.unbonding_share <= MAX_U64;
-    };
+    assert!(
+        dst_unbonding.metadata == source_unbonding.metadata,
+        error::invalid_argument(EMETADATA_MISMATCH)
+    );
+    assert!(
+        dst_unbonding.validator == source_unbonding.validator,
+        error::invalid_argument(EVALIDATOR_MISMATCH)
+    );
+    assert!(
+        dst_unbonding.release_time >= source_unbonding.release_time,
+        error::invalid_argument(ERELEASE_TIME)
+    );
 
-    dst_unbonding.unbonding_share = dst_unbonding.unbonding_share + source_unbonding.unbonding_share;
-    let Unbonding { metadata: _, validator: _, unbonding_share: _, release_time: _ } = source_unbonding;
+    dst_unbonding.unbonding_share = bigdecimal::add(
+        dst_unbonding.unbonding_share, source_unbonding.unbonding_share
+    );
+    let Unbonding { metadata: _, validator: _, unbonding_share: _, release_time: _ } =
+        source_unbonding;
 }
 
-
- ## Function `claim_unbonding` @@ -3101,13 +2772,15 @@ Claim unbonding_coin from expired unbonding. -
-Implementation +##### Implementation
public fun claim_unbonding(unbonding: Unbonding): FungibleAsset acquires ModuleStore {
-    let (_, timestamp) = block::get_block_info();
-    assert!(unbonding.release_time <= timestamp, error::invalid_state(ENOT_RELEASED));
+    let (_, timestamp) = block::get_block_info();
+    assert!(
+        unbonding.release_time <= timestamp,
+        error::invalid_state(ENOT_RELEASED)
+    );
 
     let unbonding_amount = get_unbonding_amount_from_unbonding(&unbonding);
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
@@ -3115,19 +2788,35 @@ Claim unbonding_coin from expired unbonding.
     let validator = unbonding.validator;
 
     // extract coin
-    let state = load_staking_state_mut(&mut module_store.staking_states, metadata, validator);
-    let unbonding_coin = if (unbonding_amount == 0) {
-        fungible_asset::zero(metadata)
-    } else {
-        let unbonding_coin_store_signer = &object::generate_signer_for_extending(&state.unbonding_coin_store_ref);
-        fungible_asset::withdraw(unbonding_coin_store_signer, state.unbonding_coin_store, unbonding_amount)
-    };
+    let state =
+        load_staking_state_mut(
+            &mut module_store.staking_states,
+            metadata,
+            validator
+        );
+    let unbonding_coin =
+        if (unbonding_amount == 0) {
+            fungible_asset::zero(metadata)
+        } else {
+            let unbonding_coin_store_signer =
+                &object::generate_signer_for_extending(
+                    &state.unbonding_coin_store_ref
+                );
+            fungible_asset::withdraw(
+                unbonding_coin_store_signer,
+                state.unbonding_coin_store,
+                unbonding_amount
+            )
+        };
 
     // decrease share
-    state.unbonding_share = state.unbonding_share - (unbonding.unbonding_share as u128);
+    state.unbonding_share = bigdecimal::sub(
+        state.unbonding_share, unbonding.unbonding_share
+    );
 
     // destroy empty
-    let Unbonding { metadata: _, validator: _, unbonding_share: _, release_time: _ } = unbonding;
+    let Unbonding { metadata: _, validator: _, unbonding_share: _, release_time: _ } =
+        unbonding;
 
     unbonding_coin
 }
@@ -3135,100 +2824,42 @@ Claim unbonding_coin from expired unbonding.
 
 
 
-
- - - -## Function `delegate_internal` - - - -
fun delegate_internal(validator: vector<u8>, metadata: &object::Object<fungible_asset::Metadata>, amount: u64): u64
-
- - - -
-Implementation - - -
native fun delegate_internal(
-    validator: vector<u8>,
-    metadata: &Object<Metadata>,
-    amount: u64,
-): u64 /* share amount */;
-
- - - -
- - - -## Function `undelegate_internal` - - - -
fun undelegate_internal(validator: vector<u8>, metadata: &object::Object<fungible_asset::Metadata>, share: u64): (u64, u64)
-
- - - -
-Implementation - - -
native fun undelegate_internal(
-    validator: vector<u8>,
-    metadata: &Object<Metadata>,
-    share: u64
-): (u64 /* unbonding amount */, u64 /* unbond timestamp */);
-
- - - -
- ## Function `share_to_amount` -
public fun share_to_amount(validator: vector<u8>, metadata: &object::Object<fungible_asset::Metadata>, share: u64): u64
+
public fun share_to_amount(validator: vector<u8>, metadata: &object::Object<fungible_asset::Metadata>, share: &bigdecimal::BigDecimal): u64
 
-
-Implementation +##### Implementation -
native public fun share_to_amount(validator: vector<u8>, metadata: &Object<Metadata>, share: u64): u64 /* delegation amount */;
+
native public fun share_to_amount(
+    validator: vector<u8>, metadata: &Object<Metadata>, share: &BigDecimal
+): u64 /* delegation amount */;
 
-
- ## Function `amount_to_share` -
public fun amount_to_share(validator: vector<u8>, metadata: &object::Object<fungible_asset::Metadata>, amount: u64): u64
+
public fun amount_to_share(validator: vector<u8>, metadata: &object::Object<fungible_asset::Metadata>, amount: u64): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation -
native public fun amount_to_share(validator: vector<u8>, metadata: &Object<Metadata>, amount: u64): u64 /* share amount */;
+
native public fun amount_to_share(
+    validator: vector<u8>, metadata: &Object<Metadata>, amount: u64
+): BigDecimal /* share amount */;
 
- - - -
diff --git a/initia_stdlib/doc/string_utils.md b/initia_stdlib/doc/string_utils.md index a084698..274f922 100644 --- a/initia_stdlib/doc/string_utils.md +++ b/initia_stdlib/doc/string_utils.md @@ -19,14 +19,6 @@ A module for formatting move values as strings. - [Function `format2`](#0x1_string_utils_format2) - [Function `format3`](#0x1_string_utils_format3) - [Function `format4`](#0x1_string_utils_format4) -- [Function `cons`](#0x1_string_utils_cons) -- [Function `nil`](#0x1_string_utils_nil) -- [Function `list1`](#0x1_string_utils_list1) -- [Function `list2`](#0x1_string_utils_list2) -- [Function `list3`](#0x1_string_utils_list3) -- [Function `list4`](#0x1_string_utils_list4) -- [Function `native_format`](#0x1_string_utils_native_format) -- [Function `native_format_list`](#0x1_string_utils_native_format_list)
use 0x1::string;
@@ -45,8 +37,7 @@ A module for formatting move values as strings.
 
 
 
-
-Fields +##### Fields
@@ -65,8 +56,6 @@ A module for formatting move values as strings.
-
- ## Struct `NIL` @@ -78,8 +67,7 @@ A module for formatting move values as strings. -
-Fields +##### Fields
@@ -92,8 +80,6 @@ A module for formatting move values as strings.
-
- ## Struct `FakeCons` @@ -110,8 +96,7 @@ A module for formatting move values as strings. -
-Fields +##### Fields
@@ -130,8 +115,6 @@ A module for formatting move values as strings.
-
- ## Constants @@ -185,8 +168,7 @@ For std::string::String the output is the string itself including quotes, eg. -
-Implementation +##### Implementation
public fun to_string<T>(s: &T): String {
@@ -196,8 +178,6 @@ For std::string::String the output is the string itself including quotes, eg.
 
 
 
-
- ## Function `to_string_with_canonical_addresses` @@ -210,8 +190,7 @@ Format addresses as 64 zero-padded hexadecimals. -
-Implementation +##### Implementation
public fun to_string_with_canonical_addresses<T>(s: &T): String {
@@ -221,8 +200,6 @@ Format addresses as 64 zero-padded hexadecimals.
 
 
 
-
- ## Function `to_string_with_integer_types` @@ -235,19 +212,16 @@ Format emitting integers with types ie. 6u8 or 128u32. -
-Implementation +##### Implementation
public fun to_string_with_integer_types<T>(s: &T): String {
-    native_format(s, false, true, true, false)
+    native_format(s, false, true, true, true)
 }
 
-
- ## Function `debug_string` @@ -260,8 +234,7 @@ Format vectors and structs with newlines and indentation. -
-Implementation +##### Implementation
public fun debug_string<T>(s: &T): String {
@@ -271,8 +244,6 @@ Format vectors and structs with newlines and indentation.
 
 
 
-
- ## Function `format1` @@ -285,8 +256,7 @@ Formatting with a rust-like format string, eg. format1<T0: drop>(fmt: &vector<u8>, a: T0): String { @@ -296,8 +266,6 @@ Formatting with a rust-like format string, eg. ## Function `format2` @@ -309,8 +277,7 @@ Formatting with a rust-like format string, eg. format2<T0: drop, T1: drop>(fmt: &vector<u8>, a: T0, b: T1): String { @@ -320,8 +287,6 @@ Formatting with a rust-like format string, eg. ## Function `format3` @@ -333,19 +298,18 @@ Formatting with a rust-like format string, eg. format3<T0: drop, T1: drop, T2: drop>(fmt: &vector<u8>, a: T0, b: T1, c: T2): String { +
public fun format3<T0: drop, T1: drop, T2: drop>(
+    fmt: &vector<u8>, a: T0, b: T1, c: T2
+): String {
     native_format_list(fmt, &list3(a, b, c))
 }
 
- - ## Function `format4` @@ -357,191 +321,16 @@ Formatting with a rust-like format string, eg. format4<T0: drop, T1: drop, T2: drop, T3: drop>(fmt: &vector<u8>, a: T0, b: T1, c: T2, d: T3): String { +
public fun format4<T0: drop, T1: drop, T2: drop, T3: drop>(
+    fmt: &vector<u8>,
+    a: T0,
+    b: T1,
+    c: T2,
+    d: T3
+): String {
     native_format_list(fmt, &list4(a, b, c, d))
 }
 
- - - - - - - -## Function `cons` - - - -
fun cons<T, N>(car: T, cdr: N): string_utils::Cons<T, N>
-
- - - -
-Implementation - - -
fun cons<T, N>(car: T, cdr: N): Cons<T, N> { Cons { car, cdr } }
-
- - - -
- - - -## Function `nil` - - - -
fun nil(): string_utils::NIL
-
- - - -
-Implementation - - -
fun nil(): NIL { NIL {} }
-
- - - -
- - - -## Function `list1` - - - -
fun list1<T0>(a: T0): string_utils::Cons<T0, string_utils::NIL>
-
- - - -
-Implementation - - -
inline fun list1<T0>(a: T0): Cons<T0, NIL> { cons(a, nil()) }
-
- - - -
- - - -## Function `list2` - - - -
fun list2<T0, T1>(a: T0, b: T1): string_utils::Cons<T0, string_utils::Cons<T1, string_utils::NIL>>
-
- - - -
-Implementation - - -
inline fun list2<T0, T1>(a: T0, b: T1): Cons<T0, Cons<T1, NIL>> { cons(a, list1(b)) }
-
- - - -
- - - -## Function `list3` - - - -
fun list3<T0, T1, T2>(a: T0, b: T1, c: T2): string_utils::Cons<T0, string_utils::Cons<T1, string_utils::Cons<T2, string_utils::NIL>>>
-
- - - -
-Implementation - - -
inline fun list3<T0, T1, T2>(a: T0, b: T1, c: T2): Cons<T0, Cons<T1, Cons<T2, NIL>>> { cons(a, list2(b, c)) }
-
- - - -
- - - -## Function `list4` - - - -
fun list4<T0, T1, T2, T3>(a: T0, b: T1, c: T2, d: T3): string_utils::Cons<T0, string_utils::Cons<T1, string_utils::Cons<T2, string_utils::Cons<T3, string_utils::NIL>>>>
-
- - - -
-Implementation - - -
inline fun list4<T0, T1, T2, T3>(a: T0, b: T1, c: T2, d: T3): Cons<T0, Cons<T1, Cons<T2, Cons<T3, NIL>>>> { cons(a, list3(b, c, d)) }
-
- - - -
- - - -## Function `native_format` - - - -
fun native_format<T>(s: &T, type_tag: bool, canonicalize: bool, single_line: bool, include_int_types: bool): string::String
-
- - - -
-Implementation - - -
native fun native_format<T>(s: &T, type_tag: bool, canonicalize: bool, single_line: bool, include_int_types: bool): String;
-
- - - -
- - - -## Function `native_format_list` - - - -
fun native_format_list<T>(fmt: &vector<u8>, val: &T): string::String
-
- - - -
-Implementation - - -
native fun native_format_list<T>(fmt: &vector<u8>, val: &T): String;
-
- - - -
diff --git a/initia_stdlib/doc/table.md b/initia_stdlib/doc/table.md index 1822bf0..c2b6b3d 100644 --- a/initia_stdlib/doc/table.md +++ b/initia_stdlib/doc/table.md @@ -8,7 +8,6 @@ Type of large-scale storage tables. - [Struct `Table`](#0x1_table_Table) - [Struct `TableIter`](#0x1_table_TableIter) -- [Struct `TableIterMut`](#0x1_table_TableIterMut) - [Resource `Box`](#0x1_table_Box) - [Constants](#@Constants_0) - [Function `new`](#0x1_table_new) @@ -30,20 +29,6 @@ Type of large-scale storage tables. - [Function `iter_mut`](#0x1_table_iter_mut) - [Function `prepare_mut`](#0x1_table_prepare_mut) - [Function `next_mut`](#0x1_table_next_mut) -- [Function `new_table_handle`](#0x1_table_new_table_handle) -- [Function `add_box`](#0x1_table_add_box) -- [Function `borrow_box`](#0x1_table_borrow_box) -- [Function `borrow_box_mut`](#0x1_table_borrow_box_mut) -- [Function `contains_box`](#0x1_table_contains_box) -- [Function `remove_box`](#0x1_table_remove_box) -- [Function `destroy_empty_box`](#0x1_table_destroy_empty_box) -- [Function `drop_unchecked_box`](#0x1_table_drop_unchecked_box) -- [Function `new_table_iter`](#0x1_table_new_table_iter) -- [Function `new_table_iter_mut`](#0x1_table_new_table_iter_mut) -- [Function `next_box`](#0x1_table_next_box) -- [Function `prepare_box`](#0x1_table_prepare_box) -- [Function `next_box_mut`](#0x1_table_next_box_mut) -- [Function `prepare_box_mut`](#0x1_table_prepare_box_mut)
use 0x1::account;
@@ -66,8 +51,7 @@ Type of tables
 
 
 
-
-Fields +##### Fields
@@ -86,8 +70,6 @@ Type of tables
-
- ## Struct `TableIter` @@ -100,8 +82,7 @@ Type of table iterators -
-Fields +##### Fields
@@ -114,36 +95,6 @@ Type of table iterators
-
- - - -## Struct `TableIterMut` - -Type of mutable table iterators - - -
struct TableIterMut<K: copy, drop, V> has drop
-
- - - -
-Fields - - -
-
-iterator_id: u64 -
-
- -
-
- - -
- ## Resource `Box` @@ -156,8 +107,7 @@ Wrapper for values. Required for making values appear as resources in the implem -
-Fields +##### Fields
@@ -170,8 +120,6 @@ Wrapper for values. Required for making values appear as resources in the implem
-
- ## Constants @@ -216,24 +164,18 @@ Create a new Table. -
-Implementation +##### Implementation
public fun new<K: copy + drop, V: store>(): Table<K, V> {
     let handle = new_table_handle<K, V>();
     account::create_table_account(handle);
-    Table {
-        handle,
-        length: 0,
-    }
+    Table { handle, length: 0 }
 }
 
-
- ## Function `destroy_empty` @@ -246,12 +188,14 @@ Destroy a table. The table must be empty to succeed. -
-Implementation +##### Implementation
public fun destroy_empty<K: copy + drop, V>(table: Table<K, V>) {
-    assert!(table.length == 0, error::invalid_state(ENOT_EMPTY));
+    assert!(
+        table.length == 0,
+        error::invalid_state(ENOT_EMPTY)
+    );
     destroy_empty_box<K, V, Box<V>>(&table);
     drop_unchecked_box<K, V, Box<V>>(table)
 }
@@ -259,8 +203,6 @@ Destroy a table. The table must be empty to succeed.
 
 
 
-
- ## Function `handle` @@ -273,8 +215,7 @@ Return a table handle address. -
-Implementation +##### Implementation
public fun handle<K: copy + drop, V>(table: &Table<K, V>): address {
@@ -284,8 +225,6 @@ Return a table handle address.
 
 
 
-
- ## Function `add` @@ -300,8 +239,7 @@ table, and cannot be discovered from it. -
-Implementation +##### Implementation
public fun add<K: copy + drop, V>(table: &mut Table<K, V>, key: K, val: V) {
@@ -312,8 +250,6 @@ table, and cannot be discovered from it.
 
 
 
-
- ## Function `borrow` @@ -327,8 +263,7 @@ Aborts if there is no entry for key. -
-Implementation +##### Implementation
public fun borrow<K: copy + drop, V>(table: &Table<K, V>, key: K): &V {
@@ -338,8 +273,6 @@ Aborts if there is no entry for key.
 
 
 
-
- ## Function `borrow_with_default` @@ -353,11 +286,12 @@ Returns specified default value if there is no entry for key. -
-Implementation +##### Implementation -
public fun borrow_with_default<K: copy + drop, V>(table: &Table<K, V>, key: K, default: &V): &V {
+
public fun borrow_with_default<K: copy + drop, V>(
+    table: &Table<K, V>, key: K, default: &V
+): &V {
     if (!contains(table, copy key)) {
         default
     } else {
@@ -368,8 +302,6 @@ Returns specified default value if there is no entry for key.
 
 
 
-
- ## Function `borrow_mut` @@ -383,8 +315,7 @@ Aborts if there is no entry for key. -
-Implementation +##### Implementation
public fun borrow_mut<K: copy + drop, V>(table: &mut Table<K, V>, key: K): &mut V {
@@ -394,8 +325,6 @@ Aborts if there is no entry for key.
 
 
 
-
- ## Function `length` @@ -408,8 +337,7 @@ Returns the length of the table, i.e. the number of entries. -
-Implementation +##### Implementation
public fun length<K: copy + drop, V>(table: &Table<K, V>): u64 {
@@ -419,8 +347,6 @@ Returns the length of the table, i.e. the number of entries.
 
 
 
-
- ## Function `empty` @@ -433,8 +359,7 @@ Returns true if this table is empty. -
-Implementation +##### Implementation
public fun empty<K: copy + drop, V>(table: &Table<K, V>): bool {
@@ -444,8 +369,6 @@ Returns true if this table is empty.
 
 
 
-
- ## Function `borrow_mut_with_default` @@ -459,11 +382,14 @@ Insert the pair (key, default) first if there is no en -
-Implementation +##### Implementation -
public fun borrow_mut_with_default<K: copy + drop, V: drop>(table: &mut Table<K, V>, key: K, default: V): &mut V {
+
public fun borrow_mut_with_default<K: copy + drop, V: drop>(
+    table: &mut Table<K, V>,
+    key: K,
+    default: V
+): &mut V {
     if (!contains(table, copy key)) {
         add(table, copy key, default)
     };
@@ -473,8 +399,6 @@ Insert the pair (key, default) first if there is no en
 
 
 
-
- ## Function `upsert` @@ -488,11 +412,14 @@ update the value of the entry for key to value otherwi -
-Implementation +##### Implementation -
public fun upsert<K: copy + drop, V: drop>(table: &mut Table<K, V>, key: K, value: V) {
+
public fun upsert<K: copy + drop, V: drop>(
+    table: &mut Table<K, V>,
+    key: K,
+    value: V
+) {
     if (!contains(table, copy key)) {
         add(table, copy key, value)
     } else {
@@ -504,8 +431,6 @@ update the value of the entry for key to value otherwi
 
 
 
-
- ## Function `remove` @@ -519,8 +444,7 @@ Aborts if there is no entry for key. -
-Implementation +##### Implementation
public fun remove<K: copy + drop, V>(table: &mut Table<K, V>, key: K): V {
@@ -532,8 +456,6 @@ Aborts if there is no entry for key.
 
 
 
-
- ## Function `contains` @@ -546,8 +468,7 @@ Returns true iff table contains an -
-Implementation +##### Implementation
public fun contains<K: copy + drop, V>(table: &Table<K, V>, key: K): bool {
@@ -557,8 +478,6 @@ Returns true iff table contains an
 
 
 
-
- ## Function `iter` @@ -581,85 +500,76 @@ the numeric order, use iter<K: copy, drop, V>(table: &table::Table<K, V>, start: option::Option<K>, end: option::Option<K>, order: u8): table::TableIter<K, V> +
public fun iter<K: copy, drop, V>(table: &table::Table<K, V>, start: option::Option<K>, end: option::Option<K>, order: u8): &table::TableIter<K, V>
 
-
-Implementation +##### Implementation
public fun iter<K: copy + drop, V>(
     table: &Table<K, V>,
     start: Option<K>, /* inclusive */
     end: Option<K>, /* exclusive */
-    order: u8 /* 1: Ascending, 2: Descending */,
-): TableIter<K, V> {
-    let start_bytes: vector<u8> = if (option::is_some(&start)) {
-        bcs::to_bytes<K>(&option::extract(&mut start))
-    } else {
-        vector::empty()
-    };
-
-    let end_bytes: vector<u8> = if (option::is_some(&end)) {
-        bcs::to_bytes<K>(&option::extract(&mut end))
-    } else {
-        vector::empty()
-    };
-
-    let iterator_id = new_table_iter<K, V, Box<V>>(table, start_bytes, end_bytes, order);
-    TableIter {
-        iterator_id,
-    }
+    order: u8 /* 1: Ascending, 2: Descending */
+): &TableIter<K, V> {
+    let start_bytes: vector<u8> =
+        if (option::is_some(&start)) {
+            bcs::to_bytes<K>(&option::extract(&mut start))
+        } else {
+            vector::empty()
+        };
+
+    let end_bytes: vector<u8> =
+        if (option::is_some(&end)) {
+            bcs::to_bytes<K>(&option::extract(&mut end))
+        } else {
+            vector::empty()
+        };
+
+    new_table_iter<K, V, Box<V>>(table, start_bytes, end_bytes, order)
 }
 
-
- ## Function `prepare` -
public fun prepare<K: copy, drop, V>(table_iter: &mut table::TableIter<K, V>): bool
+
public fun prepare<K: copy, drop, V>(table_iter: &table::TableIter<K, V>): bool
 
-
-Implementation +##### Implementation -
public fun prepare<K: copy + drop, V>(table_iter: &mut TableIter<K, V>): bool {
+
public fun prepare<K: copy + drop, V>(table_iter: &TableIter<K, V>): bool {
     prepare_box<K, V, Box<V>>(table_iter)
 }
 
-
- ## Function `next` -
public fun next<K: copy, drop, V>(table_iter: &mut table::TableIter<K, V>): (K, &V)
+
public fun next<K: copy, drop, V>(table_iter: &table::TableIter<K, V>): (K, &V)
 
-
-Implementation +##### Implementation -
public fun next<K: copy + drop, V>(table_iter: &mut TableIter<K, V>): (K, &V) {
+
public fun next<K: copy + drop, V>(table_iter: &TableIter<K, V>): (K, &V) {
     let (key, box) = next_box<K, V, Box<V>>(table_iter);
     (key, &box.val)
 }
@@ -667,8 +577,6 @@ functions to obtain the Big Endian key bytes of a number.
 
 
 
-
- ## Function `iter_mut` @@ -676,13 +584,13 @@ functions to obtain the Big Endian key bytes of a number. Create mutable iterator for table. A user has to check prepare before calling next to prevent abort. -let iter = table::iter_mut(&t, start, end, order); +let iter = table::iter_mut(&mut t, start, end, order); loop { -if (!table::prepare_mut(&mut iter)) { +if (!table::prepare_mut(iter)) { break; } -let (key, value) = table::next_mut(&mut iter); +let (key, value) = table::next_mut(iter); } NOTE: The default BCS number encoding follows the Little Endian method. @@ -691,408 +599,79 @@ the numeric order, use iter_mut<K: copy, drop, V>(table: &mut table::Table<K, V>, start: option::Option<K>, end: option::Option<K>, order: u8): table::TableIterMut<K, V> +
public fun iter_mut<K: copy, drop, V>(table: &mut table::Table<K, V>, start: option::Option<K>, end: option::Option<K>, order: u8): &mut table::TableIter<K, V>
 
-
-Implementation +##### Implementation
public fun iter_mut<K: copy + drop, V>(
     table: &mut Table<K, V>,
     start: Option<K>, /* inclusive */
     end: Option<K>, /* exclusive */
-    order: u8 /* 1: Ascending, 2: Descending */,
-): TableIterMut<K, V> {
-    let start_bytes: vector<u8> = if (option::is_some(&start)) {
-        bcs::to_bytes<K>(&option::extract(&mut start))
-    } else {
-        vector::empty()
-    };
-
-    let end_bytes: vector<u8> = if (option::is_some(&end)) {
-        bcs::to_bytes<K>(&option::extract(&mut end))
-    } else {
-        vector::empty()
-    };
-
-    let iterator_id = new_table_iter_mut<K, V, Box<V>>(table, start_bytes, end_bytes, order);
-    TableIterMut {
-        iterator_id,
-    }
+    order: u8 /* 1: Ascending, 2: Descending */
+): &mut TableIter<K, V> {
+    let start_bytes: vector<u8> =
+        if (option::is_some(&start)) {
+            bcs::to_bytes<K>(&option::extract(&mut start))
+        } else {
+            vector::empty()
+        };
+
+    let end_bytes: vector<u8> =
+        if (option::is_some(&end)) {
+            bcs::to_bytes<K>(&option::extract(&mut end))
+        } else {
+            vector::empty()
+        };
+
+    new_table_iter_mut<K, V, Box<V>>(table, start_bytes, end_bytes, order)
 }
 
-
- ## Function `prepare_mut` -
public fun prepare_mut<K: copy, drop, V>(table_iter: &mut table::TableIterMut<K, V>): bool
+
public fun prepare_mut<K: copy, drop, V>(table_iter: &mut table::TableIter<K, V>): bool
 
-
-Implementation +##### Implementation -
public fun prepare_mut<K: copy + drop, V>(table_iter: &mut TableIterMut<K, V>): bool {
+
public fun prepare_mut<K: copy + drop, V>(
+    table_iter: &mut TableIter<K, V>
+): bool {
     prepare_box_mut<K, V, Box<V>>(table_iter)
 }
 
-
- ## Function `next_mut` -
public fun next_mut<K: copy, drop, V>(table_iter: &mut table::TableIterMut<K, V>): (K, &mut V)
+
public fun next_mut<K: copy, drop, V>(table_iter: &mut table::TableIter<K, V>): (K, &mut V)
 
-
-Implementation +##### Implementation -
public fun next_mut<K: copy + drop, V>(table_iter: &mut TableIterMut<K, V>): (K, &mut V) {
+
public fun next_mut<K: copy + drop, V>(table_iter: &mut TableIter<K, V>): (K, &mut V) {
     let (key, box) = next_box_mut<K, V, Box<V>>(table_iter);
     (key, &mut box.val)
 }
 
- - - -
- - - -## Function `new_table_handle` - - - -
fun new_table_handle<K, V>(): address
-
- - - -
-Implementation - - -
native fun new_table_handle<K, V>(): address;
-
- - - -
- - - -## Function `add_box` - - - -
fun add_box<K: copy, drop, V, B>(table: &mut table::Table<K, V>, key: K, val: table::Box<V>)
-
- - - -
-Implementation - - -
native fun add_box<K: copy + drop, V, B>(table: &mut Table<K, V>, key: K, val: Box<V>);
-
- - - -
- - - -## Function `borrow_box` - - - -
fun borrow_box<K: copy, drop, V, B>(table: &table::Table<K, V>, key: K): &table::Box<V>
-
- - - -
-Implementation - - -
native fun borrow_box<K: copy + drop, V, B>(table: &Table<K, V>, key: K): &Box<V>;
-
- - - -
- - - -## Function `borrow_box_mut` - - - -
fun borrow_box_mut<K: copy, drop, V, B>(table: &mut table::Table<K, V>, key: K): &mut table::Box<V>
-
- - - -
-Implementation - - -
native fun borrow_box_mut<K: copy + drop, V, B>(table: &mut Table<K, V>, key: K): &mut Box<V>;
-
- - - -
- - - -## Function `contains_box` - - - -
fun contains_box<K: copy, drop, V, B>(table: &table::Table<K, V>, key: K): bool
-
- - - -
-Implementation - - -
native fun contains_box<K: copy + drop, V, B>(table: &Table<K, V>, key: K): bool;
-
- - - -
- - - -## Function `remove_box` - - - -
fun remove_box<K: copy, drop, V, B>(table: &mut table::Table<K, V>, key: K): table::Box<V>
-
- - - -
-Implementation - - -
native fun remove_box<K: copy + drop, V, B>(table: &mut Table<K, V>, key: K): Box<V>;
-
- - - -
- - - -## Function `destroy_empty_box` - - - -
fun destroy_empty_box<K: copy, drop, V, B>(table: &table::Table<K, V>)
-
- - - -
-Implementation - - -
native fun destroy_empty_box<K: copy + drop, V, B>(table: &Table<K, V>);
-
- - - -
- - - -## Function `drop_unchecked_box` - - - -
fun drop_unchecked_box<K: copy, drop, V, B>(table: table::Table<K, V>)
-
- - - -
-Implementation - - -
native fun drop_unchecked_box<K: copy + drop, V, B>(table: Table<K, V>);
-
- - - -
- - - -## Function `new_table_iter` - - - -
fun new_table_iter<K: copy, drop, V, B>(table: &table::Table<K, V>, start: vector<u8>, end: vector<u8>, order: u8): u64
-
- - - -
-Implementation - - -
native fun new_table_iter<K: copy + drop, V, B>(
-    table: &Table<K, V>,
-    start: vector<u8>,
-    end: vector<u8>,
-    order: u8
-): u64;
-
- - - -
- - - -## Function `new_table_iter_mut` - - - -
fun new_table_iter_mut<K: copy, drop, V, B>(table: &mut table::Table<K, V>, start: vector<u8>, end: vector<u8>, order: u8): u64
-
- - - -
-Implementation - - -
native fun new_table_iter_mut<K: copy + drop, V, B>(
-    table: &mut Table<K, V>,
-    start: vector<u8>,
-    end: vector<u8>,
-    order: u8
-): u64;
-
- - - -
- - - -## Function `next_box` - - - -
fun next_box<K: copy, drop, V, B>(table_iter: &mut table::TableIter<K, V>): (K, &mut table::Box<V>)
-
- - - -
-Implementation - - -
native fun next_box<K: copy + drop, V, B>(table_iter: &mut TableIter<K, V>): (K, &mut Box<V>);
-
- - - -
- - - -## Function `prepare_box` - - - -
fun prepare_box<K: copy, drop, V, B>(table_iter: &mut table::TableIter<K, V>): bool
-
- - - -
-Implementation - - -
native fun prepare_box<K: copy + drop, V, B>(table_iter: &mut TableIter<K, V>): bool;
-
- - - -
- - - -## Function `next_box_mut` - - - -
fun next_box_mut<K: copy, drop, V, B>(table_iter: &mut table::TableIterMut<K, V>): (K, &mut table::Box<V>)
-
- - - -
-Implementation - - -
native fun next_box_mut<K: copy + drop, V, B>(table_iter: &mut TableIterMut<K, V>): (K, &mut Box<V>);
-
- - - -
- - - -## Function `prepare_box_mut` - - - -
fun prepare_box_mut<K: copy, drop, V, B>(table_iter: &mut table::TableIterMut<K, V>): bool
-
- - - -
-Implementation - - -
native fun prepare_box_mut<K: copy + drop, V, B>(table_iter: &mut TableIterMut<K, V>): bool;
-
- - - -
diff --git a/initia_stdlib/doc/table_key.md b/initia_stdlib/doc/table_key.md index bf6122b..1cd1c31 100644 --- a/initia_stdlib/doc/table_key.md +++ b/initia_stdlib/doc/table_key.md @@ -32,8 +32,7 @@ return big endian bytes of u64 -
-Implementation +##### Implementation
public fun encode_u64(key: u64): vector<u8> {
@@ -46,8 +45,6 @@ return big endian bytes of u64
 
 
 
-
- ## Function `decode_u64` @@ -60,8 +57,7 @@ return u64 from the big endian key bytes -
-Implementation +##### Implementation
public fun decode_u64(key_bytes: vector<u8>): u64 {
@@ -72,8 +68,6 @@ return u64 from the big endian key bytes
 
 
 
-
- ## Function `encode_u128` @@ -86,8 +80,7 @@ return big endian bytes of u128 -
-Implementation +##### Implementation
public fun encode_u128(key: u128): vector<u8> {
@@ -100,8 +93,6 @@ return big endian bytes of u128
 
 
 
-
- ## Function `decode_u128` @@ -114,8 +105,7 @@ return u128 from the big endian key bytes -
-Implementation +##### Implementation
public fun decode_u128(key_bytes: vector<u8>): u128 {
@@ -126,8 +116,6 @@ return u128 from the big endian key bytes
 
 
 
-
- ## Function `encode_u256` @@ -140,8 +128,7 @@ return big endian bytes of u256 -
-Implementation +##### Implementation
public fun encode_u256(key: u256): vector<u8> {
@@ -154,8 +141,6 @@ return big endian bytes of u256
 
 
 
-
- ## Function `decode_u256` @@ -168,8 +153,7 @@ return u256 from the big endian key bytes -
-Implementation +##### Implementation
public fun decode_u256(key_bytes: vector<u8>): u256 {
@@ -177,7 +161,3 @@ return u256 from the big endian key bytes
     from_bcs::to_u256(key_bytes)
 }
 
- - - -
diff --git a/initia_stdlib/doc/timestamp.md b/initia_stdlib/doc/timestamp.md new file mode 100644 index 0000000..5029854 --- /dev/null +++ b/initia_stdlib/doc/timestamp.md @@ -0,0 +1,98 @@ + + + +# Module `0x1::timestamp` + +Timestamp module exists to provide compatibility with aptos. + + +- [Constants](#@Constants_0) +- [Function `now_microseconds`](#0x1_timestamp_now_microseconds) +- [Function `now_seconds`](#0x1_timestamp_now_seconds) + + +
use 0x1::block;
+
+ + + + + +## Constants + + + + +An invalid timestamp was provided + + +
const EINVALID_TIMESTAMP: u64 = 2;
+
+ + + + + +The blockchain is not in an operating state yet + + +
const ENOT_OPERATING: u64 = 1;
+
+ + + + + +Conversion factor between seconds and microseconds + + +
const MICRO_CONVERSION_FACTOR: u64 = 1000000;
+
+ + + + + +## Function `now_microseconds` + +Gets the current time in microseconds. + + +
#[view]
+public fun now_microseconds(): u64
+
+ + + +##### Implementation + + +
public fun now_microseconds(): u64 {
+    let timestamp = now_seconds();
+    timestamp * MICRO_CONVERSION_FACTOR
+}
+
+ + + + + +## Function `now_seconds` + +Gets the current time in seconds. + + +
#[view]
+public fun now_seconds(): u64
+
+ + + +##### Implementation + + +
public fun now_seconds(): u64 {
+    let (_, timestamp) = get_block_info();
+    timestamp
+}
+
diff --git a/initia_stdlib/doc/transaction_context.md b/initia_stdlib/doc/transaction_context.md index d7155aa..26fd1ba 100644 --- a/initia_stdlib/doc/transaction_context.md +++ b/initia_stdlib/doc/transaction_context.md @@ -25,8 +25,7 @@ Return a transaction hash of this execution. -
-Implementation +##### Implementation
native public fun get_transaction_hash(): vector<u8>;
@@ -34,8 +33,6 @@ Return a transaction hash of this execution.
 
 
 
-
- ## Function `generate_unique_address` @@ -52,13 +49,8 @@ the sequence number and generates a new unique address. -
-Implementation +##### Implementation
native public fun generate_unique_address(): address;
 
- - - -
diff --git a/initia_stdlib/doc/type_info.md b/initia_stdlib/doc/type_info.md index 22b489f..a1e9258 100644 --- a/initia_stdlib/doc/type_info.md +++ b/initia_stdlib/doc/type_info.md @@ -29,8 +29,7 @@ -
-Fields +##### Fields
@@ -55,8 +54,6 @@
-
- ## Function `account_address` @@ -68,8 +65,7 @@ -
-Implementation +##### Implementation
public fun account_address(type_info: &TypeInfo): address {
@@ -79,8 +75,6 @@
 
 
 
-
- ## Function `module_name` @@ -92,8 +86,7 @@ -
-Implementation +##### Implementation
public fun module_name(type_info: &TypeInfo): vector<u8> {
@@ -103,8 +96,6 @@
 
 
 
-
- ## Function `struct_name` @@ -116,8 +107,7 @@ -
-Implementation +##### Implementation
public fun struct_name(type_info: &TypeInfo): vector<u8> {
@@ -127,8 +117,6 @@
 
 
 
-
- ## Function `type_of` @@ -140,17 +128,14 @@ -
-Implementation +##### Implementation -
public native fun type_of<T>(): TypeInfo;
+
native public fun type_of<T>(): TypeInfo;
 
-
- ## Function `type_name` @@ -162,13 +147,8 @@ -
-Implementation +##### Implementation -
public native fun type_name<T>(): string::String;
+
native public fun type_name<T>(): string::String;
 
- - - -
diff --git a/initia_stdlib/doc/vault.md b/initia_stdlib/doc/vault.md deleted file mode 100644 index 03c7f2a..0000000 --- a/initia_stdlib/doc/vault.md +++ /dev/null @@ -1,386 +0,0 @@ - - - -# Module `0x1::vip_vault` - - - -- [Resource `ModuleStore`](#0x1_vip_vault_ModuleStore) -- [Constants](#@Constants_0) -- [Function `init_module`](#0x1_vip_vault_init_module) -- [Function `check_chain_permission`](#0x1_vip_vault_check_chain_permission) -- [Function `generate_vault_store_seed`](#0x1_vip_vault_generate_vault_store_seed) -- [Function `get_vault_store_address`](#0x1_vip_vault_get_vault_store_address) -- [Function `claim`](#0x1_vip_vault_claim) -- [Function `deposit`](#0x1_vip_vault_deposit) -- [Function `update_reward_per_stage`](#0x1_vip_vault_update_reward_per_stage) -- [Function `balance`](#0x1_vip_vault_balance) -- [Function `reward_per_stage`](#0x1_vip_vault_reward_per_stage) - - -
use 0x1::error;
-use 0x1::fungible_asset;
-use 0x1::object;
-use 0x1::primary_fungible_store;
-use 0x1::signer;
-use 0x1::vip_reward;
-
- - - - - -## Resource `ModuleStore` - - - -
struct ModuleStore has key
-
- - - -
-Fields - - -
-
-extend_ref: object::ExtendRef -
-
- -
-
-claimable_stage: u64 -
-
- -
-
-reward_per_stage: u64 -
-
- -
-
-vault_store_addr: address -
-
- -
-
- - -
- - - -## Constants - - - - - - -
const EUNAUTHORIZED: u64 = 3;
-
- - - - - - - -
const REWARD_SYMBOL: vector<u8> = [117, 105, 110, 105, 116];
-
- - - - - - - -
const EINVALID_AMOUNT: u64 = 1;
-
- - - - - - - -
const EINVALID_REWARD_PER_STAGE: u64 = 4;
-
- - - - - - - -
const EINVALID_STAGE: u64 = 2;
-
- - - - - - - -
const VAULT_PREFIX: u8 = 241;
-
- - - - - -## Function `init_module` - - - -
fun init_module(chain: &signer)
-
- - - -
-Implementation - - -
fun init_module(chain: &signer) {
-    let seed = generate_vault_store_seed();
-    let vault_store_addr = object::create_object_address(signer::address_of(chain), seed);
-
-    let constructor_ref = object::create_named_object(chain, seed, false);
-    let extend_ref = object::generate_extend_ref(&constructor_ref);
-
-    move_to(chain, ModuleStore {
-        extend_ref,
-        claimable_stage: 1,
-        reward_per_stage: 0, // set zero for safety
-        vault_store_addr
-    });
-}
-
- - - -
- - - -## Function `check_chain_permission` - - - -
fun check_chain_permission(chain: &signer)
-
- - - -
-Implementation - - -
fun check_chain_permission(chain: &signer) {
-    assert!(signer::address_of(chain) == @initia_std, error::permission_denied(EUNAUTHORIZED));
-}
-
- - - -
- - - -## Function `generate_vault_store_seed` - - - -
fun generate_vault_store_seed(): vector<u8>
-
- - - -
-Implementation - - -
fun generate_vault_store_seed(): vector<u8> {
-    let seed = vector[VAULT_PREFIX];
-    return seed
-}
-
- - - -
- - - -## Function `get_vault_store_address` - - - -
public(friend) fun get_vault_store_address(): address
-
- - - -
-Implementation - - -
public(friend) fun get_vault_store_address(): address acquires ModuleStore{
-    borrow_global<ModuleStore>(@initia_std).vault_store_addr
-}
-
- - - -
- - - -## Function `claim` - - - -
public(friend) fun claim(stage: u64): fungible_asset::FungibleAsset
-
- - - -
-Implementation - - -
public(friend) fun claim(
-    stage: u64,
-): FungibleAsset acquires ModuleStore {
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    assert!(stage == module_store.claimable_stage, error::invalid_argument(EINVALID_STAGE));
-    assert!(module_store.reward_per_stage > 0, error::invalid_state(EINVALID_REWARD_PER_STAGE));
-
-    module_store.claimable_stage = stage + 1;
-    let vault_signer = object::generate_signer_for_extending(&module_store.extend_ref);
-    let vault_store = primary_fungible_store::ensure_primary_store_exists(module_store.vault_store_addr, vip_reward::reward_metadata());
-    fungible_asset::withdraw(&vault_signer, vault_store, module_store.reward_per_stage)
-}
-
- - - -
- - - -## Function `deposit` - - - -
public entry fun deposit(funder: &signer, amount: u64)
-
- - - -
-Implementation - - -
public entry fun deposit(
-    funder: &signer,
-    amount: u64
-) acquires ModuleStore {
-    let vault_store_addr = get_vault_store_address();
-    assert!(amount > 0, error::invalid_argument(EINVALID_AMOUNT));
-    primary_fungible_store::transfer(funder, vip_reward::reward_metadata(), vault_store_addr, amount);
-}
-
- - - -
- - - -## Function `update_reward_per_stage` - - - -
public entry fun update_reward_per_stage(chain: &signer, reward_per_stage: u64)
-
- - - -
-Implementation - - -
public entry fun update_reward_per_stage(
-    chain: &signer,
-    reward_per_stage: u64
-) acquires ModuleStore {
-    check_chain_permission(chain);
-
-    let vault_store = borrow_global_mut<ModuleStore>(@initia_std);
-    assert!(reward_per_stage > 0, error::invalid_argument(EINVALID_REWARD_PER_STAGE));
-    vault_store.reward_per_stage = reward_per_stage;
-}
-
- - - -
- - - -## Function `balance` - - - -
#[view]
-public fun balance(): u64
-
- - - -
-Implementation - - -
public fun balance(): u64 acquires ModuleStore  {
-    let vault_store_addr = get_vault_store_address();
-    primary_fungible_store::balance(vault_store_addr, vip_reward::reward_metadata())
-}
-
- - - -
- - - -## Function `reward_per_stage` - - - -
#[view]
-public fun reward_per_stage(): u64
-
- - - -
-Implementation - - -
public fun reward_per_stage(): u64 acquires ModuleStore {
-    let vault_store = borrow_global<ModuleStore>(@initia_std);
-    vault_store.reward_per_stage
-}
-
- - - -
diff --git a/initia_stdlib/doc/vesting.md b/initia_stdlib/doc/vesting.md deleted file mode 100644 index 947ff1e..0000000 --- a/initia_stdlib/doc/vesting.md +++ /dev/null @@ -1,2388 +0,0 @@ - - - -# Module `0x1::vip_vesting` - - - -- [Resource `VestingStore`](#0x1_vip_vesting_VestingStore) -- [Struct `UserVesting`](#0x1_vip_vesting_UserVesting) -- [Struct `OperatorVesting`](#0x1_vip_vesting_OperatorVesting) -- [Struct `VestingChange`](#0x1_vip_vesting_VestingChange) -- [Struct `UserVestingCreateEvent`](#0x1_vip_vesting_UserVestingCreateEvent) -- [Struct `OperatorVestingCreateEvent`](#0x1_vip_vesting_OperatorVestingCreateEvent) -- [Struct `UserVestingFinalizedEvent`](#0x1_vip_vesting_UserVestingFinalizedEvent) -- [Struct `OperatorVestingFinalizedEvent`](#0x1_vip_vesting_OperatorVestingFinalizedEvent) -- [Struct `UserVestingClaimEvent`](#0x1_vip_vesting_UserVestingClaimEvent) -- [Struct `OperatorVestingClaimEvent`](#0x1_vip_vesting_OperatorVestingClaimEvent) -- [Constants](#@Constants_0) -- [Function `register_vesting_store`](#0x1_vip_vesting_register_vesting_store) -- [Function `generate_vesting_store_seed`](#0x1_vip_vesting_generate_vesting_store_seed) -- [Function `add_vesting`](#0x1_vip_vesting_add_vesting) -- [Function `finalize_vesting`](#0x1_vip_vesting_finalize_vesting) -- [Function `create_vesting_store_address`](#0x1_vip_vesting_create_vesting_store_address) -- [Function `get_vesting_store_address`](#0x1_vip_vesting_get_vesting_store_address) -- [Function `calculate_operator_vest`](#0x1_vip_vesting_calculate_operator_vest) -- [Function `calculate_user_vest`](#0x1_vip_vesting_calculate_user_vest) -- [Function `get_vesting`](#0x1_vip_vesting_get_vesting) -- [Function `get_vesting_finalized`](#0x1_vip_vesting_get_vesting_finalized) -- [Function `get_last_claimed_stage`](#0x1_vip_vesting_get_last_claimed_stage) -- [Function `vest_user_reward`](#0x1_vip_vesting_vest_user_reward) -- [Function `vest_operator_reward`](#0x1_vip_vesting_vest_operator_reward) -- [Function `claim_previous_operator_vestings`](#0x1_vip_vesting_claim_previous_operator_vestings) -- [Function `claim_previous_user_vestings`](#0x1_vip_vesting_claim_previous_user_vestings) -- [Function `add_user_vesting`](#0x1_vip_vesting_add_user_vesting) -- [Function `add_operator_vesting`](#0x1_vip_vesting_add_operator_vesting) -- [Function `register_user_vesting_store`](#0x1_vip_vesting_register_user_vesting_store) -- [Function `register_operator_vesting_store`](#0x1_vip_vesting_register_operator_vesting_store) -- [Function `is_user_vesting_store_registered`](#0x1_vip_vesting_is_user_vesting_store_registered) -- [Function `is_operator_vesting_store_registered`](#0x1_vip_vesting_is_operator_vesting_store_registered) -- [Function `is_user_reward_store_registered`](#0x1_vip_vesting_is_user_reward_store_registered) -- [Function `is_operator_reward_store_registered`](#0x1_vip_vesting_is_operator_reward_store_registered) -- [Function `register_user_reward_store`](#0x1_vip_vesting_register_user_reward_store) -- [Function `register_operator_reward_store`](#0x1_vip_vesting_register_operator_reward_store) -- [Function `supply_reward_on_user`](#0x1_vip_vesting_supply_reward_on_user) -- [Function `supply_reward_on_operator`](#0x1_vip_vesting_supply_reward_on_operator) -- [Function `claim_user_reward`](#0x1_vip_vesting_claim_user_reward) -- [Function `claim_operator_reward`](#0x1_vip_vesting_claim_operator_reward) -- [Function `zapping_vesting`](#0x1_vip_vesting_zapping_vesting) -- [Function `get_user_reward_store_address`](#0x1_vip_vesting_get_user_reward_store_address) -- [Function `get_user_last_claimed_stage`](#0x1_vip_vesting_get_user_last_claimed_stage) -- [Function `get_user_claimed_stages`](#0x1_vip_vesting_get_user_claimed_stages) -- [Function `get_user_vesting`](#0x1_vip_vesting_get_user_vesting) -- [Function `get_user_vesting_finalized`](#0x1_vip_vesting_get_user_vesting_finalized) -- [Function `get_user_locked_reward`](#0x1_vip_vesting_get_user_locked_reward) -- [Function `get_user_unlocked_reward`](#0x1_vip_vesting_get_user_unlocked_reward) -- [Function `get_user_vesting_initial_reward`](#0x1_vip_vesting_get_user_vesting_initial_reward) -- [Function `get_user_vesting_remaining_reward`](#0x1_vip_vesting_get_user_vesting_remaining_reward) -- [Function `get_user_vesting_minimum_score`](#0x1_vip_vesting_get_user_vesting_minimum_score) -- [Function `get_operator_reward_store_address`](#0x1_vip_vesting_get_operator_reward_store_address) -- [Function `get_operator_last_claimed_stage`](#0x1_vip_vesting_get_operator_last_claimed_stage) -- [Function `get_operator_claimed_stages`](#0x1_vip_vesting_get_operator_claimed_stages) -- [Function `get_operator_vesting`](#0x1_vip_vesting_get_operator_vesting) -- [Function `get_operator_vesting_finalized`](#0x1_vip_vesting_get_operator_vesting_finalized) -- [Function `get_operator_locked_reward`](#0x1_vip_vesting_get_operator_locked_reward) -- [Function `get_operator_unlocked_reward`](#0x1_vip_vesting_get_operator_unlocked_reward) -- [Function `get_operator_vesting_initial_reward`](#0x1_vip_vesting_get_operator_vesting_initial_reward) -- [Function `get_operator_vesting_remaining_reward`](#0x1_vip_vesting_get_operator_vesting_remaining_reward) - - -
use 0x1::bcs;
-use 0x1::decimal256;
-use 0x1::error;
-use 0x1::event;
-use 0x1::fungible_asset;
-use 0x1::object;
-use 0x1::option;
-use 0x1::primary_fungible_store;
-use 0x1::signer;
-use 0x1::string;
-use 0x1::table;
-use 0x1::table_key;
-use 0x1::type_info;
-use 0x1::vector;
-use 0x1::vip_reward;
-
- - - - - -## Resource `VestingStore` - - - -
struct VestingStore<Vesting: copy, drop, store> has key
-
- - - -
-Fields - - -
-
-claimed_stages: table::Table<vector<u8>, bool> -
-
- -
-
-vestings: table::Table<vector<u8>, Vesting> -
-
- -
-
-vestings_finalized: table::Table<vector<u8>, Vesting> -
-
- -
-
- - -
- - - -## Struct `UserVesting` - - - -
struct UserVesting has copy, drop, store
-
- - - -
-Fields - - -
-
-initial_reward: u64 -
-
- -
-
-remaining_reward: u64 -
-
- -
-
-start_stage: u64 -
-
- -
-
-end_stage: u64 -
-
- -
-
-l2_score: u64 -
-
- -
-
-minimum_score: u64 -
-
- -
-
- - -
- - - -## Struct `OperatorVesting` - - - -
struct OperatorVesting has copy, drop, store
-
- - - -
-Fields - - -
-
-initial_reward: u64 -
-
- -
-
-remaining_reward: u64 -
-
- -
-
-start_stage: u64 -
-
- -
-
-end_stage: u64 -
-
- -
-
- - -
- - - -## Struct `VestingChange` - - - -
struct VestingChange has drop, store
-
- - - -
-Fields - - -
-
-vesting_start_stage: u64 -
-
- -
-
-initial_reward: u64 -
-
- -
-
-remaining_reward: u64 -
-
- -
-
- - -
- - - -## Struct `UserVestingCreateEvent` - - - -
#[event]
-struct UserVestingCreateEvent has drop, store
-
- - - -
-Fields - - -
-
-account: address -
-
- -
-
-bridge_id: u64 -
-
- -
-
-start_stage: u64 -
-
- -
-
-end_stage: u64 -
-
- -
-
-l2_score: u64 -
-
- -
-
-minimum_score: u64 -
-
- -
-
-initial_reward: u64 -
-
- -
-
- - -
- - - -## Struct `OperatorVestingCreateEvent` - - - -
#[event]
-struct OperatorVestingCreateEvent has drop, store
-
- - - -
-Fields - - -
-
-account: address -
-
- -
-
-bridge_id: u64 -
-
- -
-
-start_stage: u64 -
-
- -
-
-end_stage: u64 -
-
- -
-
-initial_reward: u64 -
-
- -
-
- - -
- - - -## Struct `UserVestingFinalizedEvent` - - - -
#[event]
-struct UserVestingFinalizedEvent has drop, store
-
- - - -
-Fields - - -
-
-account: address -
-
- -
-
-bridge_id: u64 -
-
- -
-
-stage: u64 -
-
- -
-
-remaining_reward: u64 -
-
- -
-
- - -
- - - -## Struct `OperatorVestingFinalizedEvent` - - - -
#[event]
-struct OperatorVestingFinalizedEvent has drop, store
-
- - - -
-Fields - - -
-
-account: address -
-
- -
-
-bridge_id: u64 -
-
- -
-
-stage: u64 -
-
- -
-
-remaining_reward: u64 -
-
- -
-
- - -
- - - -## Struct `UserVestingClaimEvent` - - - -
#[event]
-struct UserVestingClaimEvent has drop, store
-
- - - -
-Fields - - -
-
-account: address -
-
- -
-
-bridge_id: u64 -
-
- -
-
-stage: u64 -
-
- -
-
-vesting_reward_amount: u64 -
-
- -
-
-vested_reward_amount: u64 -
-
- -
-
-vesting_changes: vector<vip_vesting::VestingChange> -
-
- -
-
- - -
- - - -## Struct `OperatorVestingClaimEvent` - - - -
#[event]
-struct OperatorVestingClaimEvent has drop, store
-
- - - -
-Fields - - -
-
-account: address -
-
- -
-
-bridge_id: u64 -
-
- -
-
-stage: u64 -
-
- -
-
-vesting_reward_amount: u64 -
-
- -
-
-vested_reward_amount: u64 -
-
- -
-
-vesting_changes: vector<vip_vesting::VestingChange> -
-
- -
-
- - -
- - - -## Constants - - - - - - -
const REWARD_SYMBOL: vector<u8> = [117, 105, 110, 105, 116];
-
- - - - - - - -
const EREWARD_NOT_ENOUGH: u64 = 7;
-
- - - - - - - -
const ESTAGE_ALREADY_CLAIMED: u64 = 6;
-
- - - - - - - -
const EVESTING_ALREADY_CLAIMED: u64 = 3;
-
- - - - - - - -
const EVESTING_NOT_CLAIMED: u64 = 5;
-
- - - - - - - -
const EVESTING_NOT_FOUND: u64 = 4;
-
- - - - - - - -
const EVESTING_STORE_ALREADY_EXISTS: u64 = 1;
-
- - - - - - - -
const EVESTING_STORE_NOT_FOUND: u64 = 2;
-
- - - - - - - -
const OPERATOR_VESTING_PREFIX: u8 = 245;
-
- - - - - - - -
const USER_VESTING_PREFIX: u8 = 244;
-
- - - - - -## Function `register_vesting_store` - - - -
fun register_vesting_store<Vesting: copy, drop, store>(account: &signer, bridge_id: u64)
-
- - - -
-Implementation - - -
fun register_vesting_store<Vesting: copy + drop + store> (
-    account: &signer,
-    bridge_id: u64
-) {
-    let seed = generate_vesting_store_seed<Vesting>(bridge_id);
-    let vesting_addr = object::create_object_address(signer::address_of(account), seed);
-    assert!(!exists<VestingStore<Vesting>>(vesting_addr), error::already_exists(EVESTING_STORE_ALREADY_EXISTS));
-
-    let constructor_ref = object::create_named_object(account, seed, false);
-    let transfer_ref = object::generate_transfer_ref(&constructor_ref);
-    object::disable_ungated_transfer(&transfer_ref);
-    let object = object::generate_signer(&constructor_ref);
-
-    let vesting_store = VestingStore {
-        claimed_stages: table::new<vector<u8>, bool>(),
-        vestings: table::new<vector<u8>, Vesting>(),
-        vestings_finalized: table::new<vector<u8>, Vesting>(),
-    };
-    move_to(&object, vesting_store);
-}
-
- - - -
- - - -## Function `generate_vesting_store_seed` - - - -
fun generate_vesting_store_seed<Vesting: copy, drop, store>(bridge_id: u64): vector<u8>
-
- - - -
-Implementation - - -
fun generate_vesting_store_seed<Vesting: copy + drop + store>(bridge_id: u64): vector<u8>{
-    let seed = if (type_info::type_name<Vesting>() == string::utf8(b"0x1::vip_vesting::OperatorVesting")) {
-        vector[OPERATOR_VESTING_PREFIX]
-    } else {
-        vector[USER_VESTING_PREFIX]
-    };
-    vector::append(&mut seed, bcs::to_bytes(&bridge_id));
-    return seed
-}
-
- - - -
- - - -## Function `add_vesting` - - - -
fun add_vesting<Vesting: copy, drop, store>(account_addr: address, bridge_id: u64, stage: u64, vesting: Vesting)
-
- - - -
-Implementation - - -
fun add_vesting<Vesting: copy + drop + store>(
-    account_addr: address,
-    bridge_id: u64,
-    stage: u64,
-    vesting: Vesting
-) acquires VestingStore {
-    let vesting_store_addr = get_vesting_store_address<Vesting>(account_addr, bridge_id);
-    let vesting_store = borrow_global_mut<VestingStore<Vesting>>(vesting_store_addr);
-    assert!(!table::contains(&vesting_store.claimed_stages, table_key::encode_u64(stage)), error::already_exists(EVESTING_ALREADY_CLAIMED));
-
-    table::add(&mut vesting_store.claimed_stages, table_key::encode_u64(stage), true);
-    table::add(&mut vesting_store.vestings, table_key::encode_u64(stage), vesting);
-}
-
- - - -
- - - -## Function `finalize_vesting` - - - -
fun finalize_vesting<Vesting: copy, drop, store>(account_addr: address, bridge_id: u64, stage: u64)
-
- - - -
-Implementation - - -
fun finalize_vesting<Vesting: copy + drop + store>(
-    account_addr: address,
-    bridge_id: u64,
-    stage: u64,
-) acquires VestingStore {
-    let vesting_store_addr = get_vesting_store_address<Vesting>(account_addr, bridge_id);
-    let vesting_store = borrow_global_mut<VestingStore<Vesting>>(vesting_store_addr);
-    assert!(table::contains(&vesting_store.claimed_stages, table_key::encode_u64(stage)), error::unavailable(EVESTING_NOT_CLAIMED));
-
-    let vesting = table::remove(&mut vesting_store.vestings, table_key::encode_u64(stage));
-    table::add(&mut vesting_store.vestings_finalized, table_key::encode_u64(stage), vesting);
-}
-
- - - -
- - - -## Function `create_vesting_store_address` - - - -
fun create_vesting_store_address<Vesting: copy, drop, store>(account: address, bridge_id: u64): address
-
- - - -
-Implementation - - -
fun create_vesting_store_address<Vesting: copy + drop + store>(account: address, bridge_id: u64): address {
-    let seed = generate_vesting_store_seed<Vesting>(bridge_id);
-    object::create_object_address(account, seed)
-}
-
- - - -
- - - -## Function `get_vesting_store_address` - - - -
fun get_vesting_store_address<Vesting: copy, drop, store>(account_addr: address, bridge_id: u64): address
-
- - - -
-Implementation - - -
fun get_vesting_store_address<Vesting: copy + drop + store>(account_addr: address, bridge_id: u64): address {
-    let vesting_addr = create_vesting_store_address<Vesting>(account_addr, bridge_id);
-    assert!(exists<VestingStore<Vesting>>(vesting_addr), error::not_found(EVESTING_STORE_NOT_FOUND));
-    vesting_addr
-}
-
- - - -
- - - -## Function `calculate_operator_vest` - - - -
fun calculate_operator_vest(value: &vip_vesting::OperatorVesting): u64
-
- - - -
-Implementation - - -
fun calculate_operator_vest(
-    value: &OperatorVesting,
-): u64 {
-    // vest_ratio = 1 / vesting_period
-    // vest_amount = value.initial_reward * vest_ratio
-    let vesting_period = value.end_stage - value.start_stage;
-    let vest_ratio = decimal256::div_u64(&decimal256::one(), vesting_period);
-    let vest_amount = decimal256::mul_u64(&vest_ratio, value.initial_reward);
-
-    if (vest_amount > value.remaining_reward) {
-        vest_amount = value.remaining_reward;
-    };
-
-    vest_amount
-}
-
- - - -
- - - -## Function `calculate_user_vest` - - - -
fun calculate_user_vest(value: &vip_vesting::UserVesting, l2_score: u64): u64
-
- - - -
-Implementation - - -
fun calculate_user_vest(
-    value: &UserVesting,
-    l2_score: u64,
-): u64 {
-    // vesting_period is the number of stages to vest the reward tokens.
-    // so we need to divide the vest_ratio by vesting_period to get proper
-    // vest amount of a stage.
-
-    // score_ratio = s_j > minimum_score ? 1 : (s_j / minimu_score) where s_j is current l2_score
-    // max_ratio = 1 / vesting_period
-    //
-    // vest_ratio = max_ratio * score_ratio
-    // vest_amount = value.initial_reward * vest_ratio
-    let score_ratio = if (l2_score >= value.minimum_score) {
-        decimal256::one()
-    } else {
-        decimal256::from_ratio_u64(l2_score, value.minimum_score)
-    };
-
-    let vesting_period = value.end_stage - value.start_stage;
-    let max_ratio = decimal256::div_u64(&decimal256::one(), vesting_period);
-    let vest_ratio = decimal256::mul(&max_ratio, &score_ratio);
-    let vest_amount = decimal256::mul_u64(&vest_ratio, value.initial_reward);
-
-    if (vest_amount > value.remaining_reward) {
-        vest_amount = value.remaining_reward;
-    };
-
-    vest_amount
-}
-
- - - -
- - - -## Function `get_vesting` - - - -
fun get_vesting<Vesting: copy, drop, store>(account_addr: address, bridge_id: u64, stage: u64): Vesting
-
- - - -
-Implementation - - -
fun get_vesting<Vesting: copy + drop + store>(account_addr: address, bridge_id: u64, stage: u64): Vesting acquires VestingStore {
-    let vesting_store_addr = get_vesting_store_address<Vesting>(account_addr, bridge_id);
-    let vesting_store = borrow_global_mut<VestingStore<Vesting>>(vesting_store_addr);
-
-    assert!(table::contains(&mut vesting_store.vestings, table_key::encode_u64(stage)), error::not_found(EVESTING_NOT_FOUND));
-    let vesting = table::borrow(&vesting_store.vestings, table_key::encode_u64(stage));
-
-    *vesting
-}
-
- - - -
- - - -## Function `get_vesting_finalized` - - - -
fun get_vesting_finalized<Vesting: copy, drop, store>(account_addr: address, bridge_id: u64, stage: u64): Vesting
-
- - - -
-Implementation - - -
fun get_vesting_finalized<Vesting: copy + drop + store>(account_addr: address, bridge_id: u64, stage: u64): Vesting acquires VestingStore {
-    let vesting_store_addr = get_vesting_store_address<Vesting>(account_addr, bridge_id);
-    let vesting_store = borrow_global_mut<VestingStore<Vesting>>(vesting_store_addr);
-
-    assert!(table::contains(&mut vesting_store.vestings_finalized, table_key::encode_u64(stage)), error::not_found(EVESTING_NOT_FOUND));
-    let vesting_finalized = table::borrow(&vesting_store.vestings_finalized, table_key::encode_u64(stage));
-
-    *vesting_finalized
-}
-
- - - -
- - - -## Function `get_last_claimed_stage` - - - -
fun get_last_claimed_stage<Vesting: copy, drop, store>(account_addr: address, bridge_id: u64): u64
-
- - - -
-Implementation - - -
fun get_last_claimed_stage<Vesting: copy + drop + store>(account_addr: address, bridge_id: u64): u64 acquires VestingStore {
-    let vesting_store_addr = get_vesting_store_address<Vesting>(account_addr, bridge_id);
-    let vesting_store = borrow_global_mut<VestingStore<Vesting>>(vesting_store_addr);
-
-    let iter = table::iter(&mut vesting_store.claimed_stages, option::none(), option::none(), 2);
-    if (!table::prepare<vector<u8>, bool>(&mut iter)) {
-        return 0
-    };
-    let (key, _) = table::next<vector<u8>, bool>(&mut iter);
-    table_key::decode_u64(key)
-}
-
- - - -
- - - -## Function `vest_user_reward` - - - -
fun vest_user_reward(account_addr: address, bridge_id: u64, stage: u64, l2_score: u64): (u64, vector<vip_vesting::VestingChange>)
-
- - - -
-Implementation - - -
fun vest_user_reward(
-    account_addr: address,
-    bridge_id: u64,
-    stage: u64,
-    l2_score: u64,
-) : (u64, vector<VestingChange>) acquires VestingStore {
-    let vested_reward = 0u64;
-    let vesting_changes = vector::empty<VestingChange>();
-    let vesting_store_addr = get_vesting_store_address<UserVesting>(account_addr, bridge_id);
-    let vesting_store = borrow_global_mut<VestingStore<UserVesting>>(vesting_store_addr);
-    let iter = table::iter_mut(&mut vesting_store.vestings, option::none(), option::none(), 1);
-    loop {
-        if (!table::prepare_mut<vector<u8>, UserVesting>(&mut iter)) {
-            break
-        };
-
-        let (_, value) = table::next_mut<vector<u8>, UserVesting>(&mut iter);
-
-        // move vesting if end stage is over or the left reward is empty
-        if ( stage > value.end_stage || value.remaining_reward == 0) {
-            event::emit(
-                UserVestingFinalizedEvent {
-                    account: account_addr,
-                    bridge_id,
-                    stage: value.start_stage,
-                    remaining_reward: value.remaining_reward,
-                }
-            );
-            finalize_vesting<UserVesting>(account_addr, bridge_id, value.start_stage);
-            continue
-        };
-
-        let vest_amount = calculate_user_vest(value, l2_score);
-
-        vested_reward = vested_reward + vest_amount;
-        value.remaining_reward = value.remaining_reward - vest_amount;
-
-        vector::push_back(&mut vesting_changes, VestingChange {
-            vesting_start_stage: value.start_stage,
-            initial_reward: value.initial_reward,
-            remaining_reward: value.remaining_reward,
-        });
-    };
-
-    (vested_reward, vesting_changes)
-}
-
- - - -
- - - -## Function `vest_operator_reward` - - - -
fun vest_operator_reward(account_addr: address, bridge_id: u64, stage: u64): (u64, vector<vip_vesting::VestingChange>)
-
- - - -
-Implementation - - -
fun vest_operator_reward(
-    account_addr: address,
-    bridge_id: u64,
-    stage: u64,
-) : (u64, vector<VestingChange>) acquires VestingStore {
-    let vested_reward = 0u64;
-    let vesting_changes = vector::empty<VestingChange>();
-    let vesting_store_addr = get_vesting_store_address<OperatorVesting>(account_addr, bridge_id);
-    let vesting_store = borrow_global_mut<VestingStore<OperatorVesting>>(vesting_store_addr);
-    let iter = table::iter_mut(&mut vesting_store.vestings, option::none(), option::none(), 1);
-    loop {
-        if (!table::prepare_mut<vector<u8>, OperatorVesting>(&mut iter)) {
-            break
-        };
-
-        let (_, value) = table::next_mut<vector<u8>, OperatorVesting>(&mut iter);
-
-        // move vesting if end stage is over or the left reward is empty
-        if ( stage > value.end_stage || value.remaining_reward == 0) {
-            event::emit(
-                OperatorVestingFinalizedEvent {
-                    account: account_addr,
-                    bridge_id,
-                    stage: value.start_stage,
-                    remaining_reward: value.remaining_reward,
-                }
-            );
-            finalize_vesting<OperatorVesting>(account_addr, bridge_id, value.start_stage);
-            continue
-        };
-
-        let vest_amount = calculate_operator_vest(value);
-
-        vested_reward = vested_reward + vest_amount;
-        value.remaining_reward = value.remaining_reward - vest_amount;
-
-        vector::push_back(&mut vesting_changes, VestingChange {
-            vesting_start_stage: value.start_stage,
-            initial_reward: value.initial_reward,
-            remaining_reward: value.remaining_reward,
-        });
-    };
-
-    (vested_reward, vesting_changes)
-}
-
- - - -
- - - -## Function `claim_previous_operator_vestings` - - - -
fun claim_previous_operator_vestings(account_addr: address, bridge_id: u64, stage: u64): (fungible_asset::FungibleAsset, vector<vip_vesting::VestingChange>)
-
- - - -
-Implementation - - -
fun claim_previous_operator_vestings (
-    account_addr: address,
-    bridge_id: u64,
-    stage: u64,
-): (FungibleAsset, vector<VestingChange>) acquires VestingStore {
-    assert!(get_last_claimed_stage<OperatorVesting>(account_addr, bridge_id) < stage, error::invalid_argument(ESTAGE_ALREADY_CLAIMED));
-
-    // vest previous vesting rewards until the stage
-    let (amount, vesting_changes) = vest_operator_reward(
-        account_addr,
-        bridge_id,
-        stage,
-    );
-    let reward_store_addr = get_operator_reward_store_address(bridge_id);
-    let vested_reward = vip_reward::withdraw(reward_store_addr, amount);
-
-    (vested_reward, vesting_changes)
-}
-
- - - -
- - - -## Function `claim_previous_user_vestings` - - - -
fun claim_previous_user_vestings(account_addr: address, bridge_id: u64, stage: u64, l2_score: u64): (fungible_asset::FungibleAsset, vector<vip_vesting::VestingChange>)
-
- - - -
-Implementation - - -
fun claim_previous_user_vestings (
-    account_addr: address,
-    bridge_id: u64,
-    stage: u64,
-    l2_score: u64,
-): (FungibleAsset, vector<VestingChange>) acquires VestingStore {
-    assert!(get_last_claimed_stage<UserVesting>(account_addr, bridge_id) < stage, error::invalid_argument(ESTAGE_ALREADY_CLAIMED));
-
-    // vest previous vesting rewards until the stage
-    let (amount, vesting_changes) = vest_user_reward(
-        account_addr,
-        bridge_id,
-        stage,
-        l2_score,
-    );
-    let reward_store_addr = get_user_reward_store_address(bridge_id);
-    let vested_reward = vip_reward::withdraw(reward_store_addr, amount);
-
-    (vested_reward, vesting_changes)
-}
-
- - - -
- - - -## Function `add_user_vesting` - - - -
fun add_user_vesting(account_addr: address, bridge_id: u64, start_stage: u64, end_stage: u64, l2_score: u64, total_l2_score: u64, proportion: decimal256::Decimal256): u64
-
- - - -
-Implementation - - -
fun add_user_vesting(
-    account_addr: address,
-    bridge_id: u64,
-    start_stage: u64,
-    end_stage: u64,
-    l2_score: u64,
-    total_l2_score: u64,
-    proportion: Decimal256,
-): u64 acquires VestingStore {
-    let reward_store_addr = get_user_reward_store_address(bridge_id);
-    let stage_reward = vip_reward::get_stage_reward(reward_store_addr, start_stage);
-    let score_ratio = decimal256::from_ratio_u64(l2_score, total_l2_score);
-    let vesting_reward_amount = decimal256::mul_u64(&score_ratio, stage_reward);
-    let minimum_score = decimal256::mul_u64(&proportion, l2_score);
-
-    add_vesting<UserVesting>(account_addr, bridge_id, start_stage, UserVesting{
-        initial_reward: vesting_reward_amount,
-        remaining_reward: vesting_reward_amount,
-        start_stage,
-        end_stage,
-        l2_score,
-        minimum_score,
-    });
-
-    event::emit(
-        UserVestingCreateEvent {
-            account: account_addr,
-            bridge_id,
-            start_stage,
-            end_stage,
-            l2_score,
-            minimum_score,
-            initial_reward: vesting_reward_amount,
-        }
-    );
-
-    vesting_reward_amount
-}
-
- - - -
- - - -## Function `add_operator_vesting` - - - -
fun add_operator_vesting(account_addr: address, bridge_id: u64, start_stage: u64, end_stage: u64): u64
-
- - - -
-Implementation - - -
fun add_operator_vesting(
-    account_addr: address,
-    bridge_id: u64,
-    start_stage: u64,
-    end_stage: u64,
-): u64 acquires VestingStore {
-    let reward_store_addr = get_operator_reward_store_address(bridge_id);
-    let stage_reward = vip_reward::get_stage_reward(reward_store_addr, start_stage);
-
-    add_vesting<OperatorVesting>(account_addr, bridge_id, start_stage, OperatorVesting{
-        initial_reward: stage_reward,
-        remaining_reward: stage_reward,
-        start_stage,
-        end_stage,
-    });
-
-    event::emit(
-        OperatorVestingCreateEvent {
-            account: account_addr,
-            bridge_id,
-            start_stage,
-            end_stage,
-            initial_reward: stage_reward,
-        }
-    );
-
-    stage_reward
-}
-
- - - -
- - - -## Function `register_user_vesting_store` - - - -
public fun register_user_vesting_store(account: &signer, bridge_id: u64)
-
- - - -
-Implementation - - -
public fun register_user_vesting_store(
-    account: &signer,
-    bridge_id: u64
-) {
-    register_vesting_store<UserVesting>(account, bridge_id);
-}
-
- - - -
- - - -## Function `register_operator_vesting_store` - - - -
public fun register_operator_vesting_store(account: &signer, bridge_id: u64)
-
- - - -
-Implementation - - -
public fun register_operator_vesting_store(
-    account: &signer,
-    bridge_id: u64
-) {
-    register_vesting_store<OperatorVesting>(account, bridge_id);
-}
-
- - - -
- - - -## Function `is_user_vesting_store_registered` - - - -
public fun is_user_vesting_store_registered(addr: address, bridge_id: u64): bool
-
- - - -
-Implementation - - -
public fun is_user_vesting_store_registered(
-    addr: address,
-    bridge_id: u64
-): bool {
-    exists<VestingStore<UserVesting>>(create_vesting_store_address<UserVesting>(addr, bridge_id))
-}
-
- - - -
- - - -## Function `is_operator_vesting_store_registered` - - - -
public fun is_operator_vesting_store_registered(addr: address, bridge_id: u64): bool
-
- - - -
-Implementation - - -
public fun is_operator_vesting_store_registered(
-    addr: address,
-    bridge_id: u64
-): bool {
-    exists<VestingStore<OperatorVesting>>(create_vesting_store_address<OperatorVesting>(addr, bridge_id))
-}
-
- - - -
- - - -## Function `is_user_reward_store_registered` - - - -
public fun is_user_reward_store_registered(bridge_id: u64): bool
-
- - - -
-Implementation - - -
public fun is_user_reward_store_registered(bridge_id: u64): bool {
-    vip_reward::is_reward_store_registered<UserVesting>(bridge_id)
-}
-
- - - -
- - - -## Function `is_operator_reward_store_registered` - - - -
public fun is_operator_reward_store_registered(bridge_id: u64): bool
-
- - - -
-Implementation - - -
public fun is_operator_reward_store_registered(bridge_id: u64): bool {
-    vip_reward::is_reward_store_registered<OperatorVesting>(bridge_id)
-}
-
- - - -
- - - -## Function `register_user_reward_store` - - - -
public(friend) fun register_user_reward_store(chain: &signer, bridge_id: u64)
-
- - - -
-Implementation - - -
public(friend) fun register_user_reward_store(
-    chain: &signer,
-    bridge_id: u64,
-) {
-    vip_reward::register_reward_store<UserVesting>(chain, bridge_id)
-}
-
- - - -
- - - -## Function `register_operator_reward_store` - - - -
public(friend) fun register_operator_reward_store(chain: &signer, bridge_id: u64)
-
- - - -
-Implementation - - -
public(friend) fun register_operator_reward_store(
-    chain: &signer,
-    bridge_id: u64,
-) {
-    vip_reward::register_reward_store<OperatorVesting>(chain, bridge_id)
-}
-
- - - -
- - - -## Function `supply_reward_on_user` - - - -
public(friend) fun supply_reward_on_user(bridge_id: u64, stage: u64, reward: fungible_asset::FungibleAsset)
-
- - - -
-Implementation - - -
public(friend) fun supply_reward_on_user(
-    bridge_id: u64,
-    stage: u64,
-    reward: FungibleAsset,
-) {
-    let reward_store_addr = get_user_reward_store_address(bridge_id);
-    vip_reward::add_reward_per_stage(reward_store_addr, stage, fungible_asset::amount(&reward));
-    primary_fungible_store::deposit(reward_store_addr, reward);
-}
-
- - - -
- - - -## Function `supply_reward_on_operator` - - - -
public(friend) fun supply_reward_on_operator(bridge_id: u64, stage: u64, reward: fungible_asset::FungibleAsset)
-
- - - -
-Implementation - - -
public(friend) fun supply_reward_on_operator(
-    bridge_id: u64,
-    stage: u64,
-    reward: FungibleAsset,
-) {
-    let reward_store_addr = get_operator_reward_store_address(bridge_id);
-    vip_reward::add_reward_per_stage(reward_store_addr, stage, fungible_asset::amount(&reward));
-    primary_fungible_store::deposit(reward_store_addr, reward);
-}
-
- - - -
- - - -## Function `claim_user_reward` - - - -
public(friend) fun claim_user_reward(account_addr: address, bridge_id: u64, start_stage: u64, end_stage: u64, l2_score: u64, total_l2_score: u64, proportion: decimal256::Decimal256): fungible_asset::FungibleAsset
-
- - - -
-Implementation - - -
public(friend) fun claim_user_reward(
-    account_addr: address,
-    bridge_id: u64,
-    start_stage: u64,
-    end_stage: u64,
-    l2_score: u64,
-    total_l2_score: u64,
-    proportion: Decimal256,
-): FungibleAsset acquires VestingStore{
-    let (vested_reward, vesting_changes) = claim_previous_user_vestings(
-        account_addr,
-        bridge_id,
-        start_stage,
-        l2_score,
-    );
-
-
-    let vesting_reward_amount = 0;
-
-    // if l2_score is less than 0, do not create new position
-    if (l2_score >= 0) {
-        vesting_reward_amount = add_user_vesting(
-            account_addr,
-            bridge_id,
-            start_stage,
-            end_stage,
-            l2_score,
-            total_l2_score,
-            proportion
-        );
-    };
-
-    event::emit(
-        UserVestingClaimEvent {
-            account: account_addr,
-            bridge_id,
-            stage: start_stage,
-            vesting_reward_amount,
-            vested_reward_amount: fungible_asset::amount(&vested_reward),
-            vesting_changes,
-        }
-    );
-
-    vested_reward
-}
-
- - - -
- - - -## Function `claim_operator_reward` - - - -
public(friend) fun claim_operator_reward(account_addr: address, bridge_id: u64, start_stage: u64, end_stage: u64): fungible_asset::FungibleAsset
-
- - - -
-Implementation - - -
public(friend) fun claim_operator_reward(
-    account_addr: address,
-    bridge_id: u64,
-    start_stage: u64,
-    end_stage: u64,
-): FungibleAsset acquires VestingStore {
-    let (vested_reward, vesting_changes) = claim_previous_operator_vestings(
-        account_addr,
-        bridge_id,
-        start_stage,
-    );
-
-    let vesting_reward_amount = add_operator_vesting(
-        account_addr,
-        bridge_id,
-        start_stage,
-        end_stage,
-    );
-
-    event::emit(
-        OperatorVestingClaimEvent {
-            account: account_addr,
-            bridge_id,
-            stage: start_stage,
-            vesting_reward_amount,
-            vested_reward_amount: fungible_asset::amount(&vested_reward),
-            vesting_changes,
-        }
-    );
-
-    vested_reward
-}
-
- - - -
- - - -## Function `zapping_vesting` - - - -
public(friend) fun zapping_vesting(account_addr: address, bridge_id: u64, stage: u64, zapping_amount: u64): fungible_asset::FungibleAsset
-
- - - -
-Implementation - - -
public(friend) fun zapping_vesting(
-    account_addr: address,
-    bridge_id: u64,
-    stage: u64,
-    zapping_amount: u64
-): FungibleAsset acquires VestingStore {
-    let vesting_store_addr = get_vesting_store_address<UserVesting>(account_addr, bridge_id);
-    let vesting_store = borrow_global_mut<VestingStore<UserVesting>>(vesting_store_addr);
-    assert!(table::contains(&vesting_store.vestings, table_key::encode_u64(stage)), error::not_found(EVESTING_NOT_FOUND));
-
-    let vesting = table::borrow_mut(&mut vesting_store.vestings, table_key::encode_u64(stage));
-    assert!(vesting.remaining_reward >= zapping_amount, error::invalid_argument(EREWARD_NOT_ENOUGH));
-    vesting.remaining_reward = vesting.remaining_reward - zapping_amount;
-
-    let reward_store_addr = get_user_reward_store_address(bridge_id);
-    vip_reward::withdraw(reward_store_addr, zapping_amount)
-}
-
- - - -
- - - -## Function `get_user_reward_store_address` - - - -
#[view]
-public fun get_user_reward_store_address(bridge_id: u64): address
-
- - - -
-Implementation - - -
public fun get_user_reward_store_address(bridge_id: u64): address {
-    vip_reward::get_reward_store_address<UserVesting>(bridge_id)
-}
-
- - - -
- - - -## Function `get_user_last_claimed_stage` - - - -
#[view]
-public fun get_user_last_claimed_stage(account_addr: address, bridge_id: u64): u64
-
- - - -
-Implementation - - -
public fun get_user_last_claimed_stage(
-    account_addr: address,
-    bridge_id: u64,
-): u64 acquires VestingStore {
-    get_last_claimed_stage<UserVesting>(account_addr, bridge_id)
-}
-
- - - -
- - - -## Function `get_user_claimed_stages` - - - -
#[view]
-public fun get_user_claimed_stages(account_addr: address, bridge_id: u64): vector<u64>
-
- - - -
-Implementation - - -
public fun get_user_claimed_stages(
-    account_addr: address,
-    bridge_id: u64,
-): vector<u64> acquires VestingStore {
-    let claimed_stages = vector::empty<u64>();
-    let vesting_store_addr = get_vesting_store_address<UserVesting>(account_addr, bridge_id);
-    let vesting_store = borrow_global_mut<VestingStore<UserVesting>>(vesting_store_addr);
-    let iter = table::iter(&mut vesting_store.claimed_stages, option::none(), option::none(), 1);
-    loop {
-        if (!table::prepare<vector<u8>, bool>(&mut iter)) {
-            break
-        };
-
-        let (key, _) = table::next<vector<u8>, bool>(&mut iter);
-        vector::push_back(&mut claimed_stages, table_key::decode_u64(key));
-    };
-    claimed_stages
-}
-
- - - -
- - - -## Function `get_user_vesting` - - - -
#[view]
-public fun get_user_vesting(account_addr: address, bridge_id: u64, stage: u64): vip_vesting::UserVesting
-
- - - -
-Implementation - - -
public fun get_user_vesting(
-    account_addr: address,
-    bridge_id: u64,
-    stage: u64,
-): UserVesting acquires VestingStore {
-    get_vesting<UserVesting>(account_addr, bridge_id, stage)
-}
-
- - - -
- - - -## Function `get_user_vesting_finalized` - - - -
#[view]
-public fun get_user_vesting_finalized(account_addr: address, bridge_id: u64, stage: u64): vip_vesting::UserVesting
-
- - - -
-Implementation - - -
public fun get_user_vesting_finalized(
-    account_addr: address,
-    bridge_id: u64,
-    stage: u64,
-): UserVesting acquires VestingStore {
-    get_vesting_finalized<UserVesting>(account_addr, bridge_id, stage)
-}
-
- - - -
- - - -## Function `get_user_locked_reward` - - - -
#[view]
-public fun get_user_locked_reward(account_addr: address, bridge_id: u64, stage: u64): u64
-
- - - -
-Implementation - - -
public fun get_user_locked_reward(account_addr: address, bridge_id: u64, stage: u64): u64 acquires VestingStore {
-    let locked_reward = 0u64;
-    let vesting_store_addr = get_vesting_store_address<UserVesting>(account_addr, bridge_id);
-    let vesting_store = borrow_global_mut<VestingStore<UserVesting>>(vesting_store_addr);
-    let iter = table::iter(&mut vesting_store.vestings, option::none(), option::some(table_key::encode_u64(stage + 1)), 1);
-    loop {
-        if (!table::prepare<vector<u8>, UserVesting>(&mut iter)) {
-            break
-        };
-
-        let (_, value) = table::next<vector<u8>, UserVesting>(&mut iter);
-        locked_reward = locked_reward + value.remaining_reward;
-    };
-
-    locked_reward
-}
-
- - - -
- - - -## Function `get_user_unlocked_reward` - - - -
#[view]
-public fun get_user_unlocked_reward(account_addr: address, bridge_id: u64, stage: u64, l2_score: u64): u64
-
- - - -
-Implementation - - -
public fun get_user_unlocked_reward(account_addr: address, bridge_id: u64, stage: u64, l2_score:u64): u64 acquires VestingStore {
-    let vested_reward = 0u64;
-    let vesting_store_addr = get_vesting_store_address<UserVesting>(account_addr, bridge_id);
-    let vesting_store = borrow_global_mut<VestingStore<UserVesting>>(vesting_store_addr);
-    let iter = table::iter_mut(&mut vesting_store.vestings, option::none(), option::some(table_key::encode_u64(stage)), 1);
-    loop {
-        if (!table::prepare_mut<vector<u8>, UserVesting>(&mut iter)) {
-            break
-        };
-
-        let (_, value) = table::next_mut<vector<u8>, UserVesting>(&mut iter);
-
-        let vest_amount = calculate_user_vest(value, l2_score);
-        vested_reward = vested_reward + vest_amount;
-    };
-    vested_reward
-}
-
- - - -
- - - -## Function `get_user_vesting_initial_reward` - - - -
#[view]
-public fun get_user_vesting_initial_reward(account_addr: address, bridge_id: u64, stage: u64): u64
-
- - - -
-Implementation - - -
public fun get_user_vesting_initial_reward(account_addr: address, bridge_id: u64, stage: u64): u64 acquires VestingStore {
-    let vesting = get_vesting<UserVesting>(account_addr, bridge_id, stage);
-    vesting.initial_reward
-}
-
- - - -
- - - -## Function `get_user_vesting_remaining_reward` - - - -
#[view]
-public fun get_user_vesting_remaining_reward(account_addr: address, bridge_id: u64, stage: u64): u64
-
- - - -
-Implementation - - -
public fun get_user_vesting_remaining_reward(account_addr: address, bridge_id: u64, stage: u64): u64 acquires VestingStore {
-    let vesting = get_vesting<UserVesting>(account_addr, bridge_id, stage);
-    vesting.remaining_reward
-}
-
- - - -
- - - -## Function `get_user_vesting_minimum_score` - - - -
#[view]
-public fun get_user_vesting_minimum_score(account_addr: address, bridge_id: u64, stage: u64): u64
-
- - - -
-Implementation - - -
public fun get_user_vesting_minimum_score(account_addr: address, bridge_id: u64, stage: u64): u64 acquires VestingStore {
-    let vesting = get_vesting<UserVesting>(account_addr, bridge_id, stage);
-    vesting.minimum_score
-}
-
- - - -
- - - -## Function `get_operator_reward_store_address` - - - -
#[view]
-public fun get_operator_reward_store_address(bridge_id: u64): address
-
- - - -
-Implementation - - -
public fun get_operator_reward_store_address(bridge_id: u64): address {
-    vip_reward::get_reward_store_address<OperatorVesting>(bridge_id)
-}
-
- - - -
- - - -## Function `get_operator_last_claimed_stage` - - - -
#[view]
-public fun get_operator_last_claimed_stage(account_addr: address, bridge_id: u64): u64
-
- - - -
-Implementation - - -
public fun get_operator_last_claimed_stage(
-    account_addr: address,
-    bridge_id: u64,
-): u64 acquires VestingStore {
-    get_last_claimed_stage<OperatorVesting>(account_addr, bridge_id)
-}
-
- - - -
- - - -## Function `get_operator_claimed_stages` - - - -
#[view]
-public fun get_operator_claimed_stages(account_addr: address, bridge_id: u64): vector<u64>
-
- - - -
-Implementation - - -
public fun get_operator_claimed_stages(
-    account_addr: address,
-    bridge_id: u64,
-): vector<u64> acquires VestingStore {
-    let claimed_stages = vector::empty<u64>();
-    let vesting_store_addr = get_vesting_store_address<OperatorVesting>(account_addr, bridge_id);
-    let vesting_store = borrow_global_mut<VestingStore<OperatorVesting>>(vesting_store_addr);
-    let iter = table::iter(&mut vesting_store.claimed_stages, option::none(), option::none(), 1);
-    loop {
-        if (!table::prepare<vector<u8>, bool>(&mut iter)) {
-            break
-        };
-
-        let (key, _) = table::next<vector<u8>, bool>(&mut iter);
-        vector::push_back(&mut claimed_stages, table_key::decode_u64(key));
-    };
-    claimed_stages
-}
-
- - - -
- - - -## Function `get_operator_vesting` - - - -
#[view]
-public fun get_operator_vesting(account_addr: address, bridge_id: u64, stage: u64): vip_vesting::OperatorVesting
-
- - - -
-Implementation - - -
public fun get_operator_vesting(
-    account_addr: address,
-    bridge_id: u64,
-    stage: u64,
-): OperatorVesting acquires VestingStore {
-    get_vesting<OperatorVesting>(account_addr, bridge_id, stage)
-}
-
- - - -
- - - -## Function `get_operator_vesting_finalized` - - - -
#[view]
-public fun get_operator_vesting_finalized(account_addr: address, bridge_id: u64, stage: u64): vip_vesting::OperatorVesting
-
- - - -
-Implementation - - -
public fun get_operator_vesting_finalized(
-    account_addr: address,
-    bridge_id: u64,
-    stage: u64,
-): OperatorVesting acquires VestingStore {
-    get_vesting_finalized<OperatorVesting>(account_addr, bridge_id, stage)
-}
-
- - - -
- - - -## Function `get_operator_locked_reward` - - - -
#[view]
-public fun get_operator_locked_reward(account_addr: address, bridge_id: u64, stage: u64): u64
-
- - - -
-Implementation - - -
public fun get_operator_locked_reward(account_addr: address, bridge_id: u64, stage: u64): u64 acquires VestingStore {
-    let locked_reward = 0u64;
-    let vesting_store_addr = get_vesting_store_address<OperatorVesting>(account_addr, bridge_id);
-    let vesting_store = borrow_global_mut<VestingStore<OperatorVesting>>(vesting_store_addr);
-    let iter = table::iter(&mut vesting_store.vestings, option::none(), option::some(table_key::encode_u64(stage + 1)), 1);
-    loop {
-        if (!table::prepare<vector<u8>, OperatorVesting>(&mut iter)) {
-            break
-        };
-
-        let (_, value) = table::next<vector<u8>, OperatorVesting>(&mut iter);
-        locked_reward = locked_reward + value.remaining_reward;
-    };
-
-    locked_reward
-}
-
- - - -
- - - -## Function `get_operator_unlocked_reward` - - - -
#[view]
-public fun get_operator_unlocked_reward(account_addr: address, bridge_id: u64, stage: u64): u64
-
- - - -
-Implementation - - -
public fun get_operator_unlocked_reward(account_addr: address, bridge_id: u64, stage: u64): u64 acquires VestingStore {
-    let vested_reward = 0u64;
-    let vesting_store_addr = get_vesting_store_address<OperatorVesting>(account_addr, bridge_id);
-    let vesting_store = borrow_global_mut<VestingStore<OperatorVesting>>(vesting_store_addr);
-    let iter = table::iter_mut(&mut vesting_store.vestings, option::none(), option::some(table_key::encode_u64(stage)), 1);
-    loop {
-        if (!table::prepare_mut<vector<u8>, OperatorVesting>(&mut iter)) {
-            break
-        };
-
-        let (_, value) = table::next_mut<vector<u8>, OperatorVesting>(&mut iter);
-
-        let vest_amount = calculate_operator_vest(value);
-        vested_reward = vested_reward + vest_amount;
-    };
-    vested_reward
-}
-
- - - -
- - - -## Function `get_operator_vesting_initial_reward` - - - -
#[view]
-public fun get_operator_vesting_initial_reward(account_addr: address, bridge_id: u64, stage: u64): u64
-
- - - -
-Implementation - - -
public fun get_operator_vesting_initial_reward(account_addr: address, bridge_id: u64, stage: u64): u64 acquires VestingStore {
-    let vesting = get_vesting<OperatorVesting>(account_addr, bridge_id, stage);
-    vesting.initial_reward
-}
-
- - - -
- - - -## Function `get_operator_vesting_remaining_reward` - - - -
#[view]
-public fun get_operator_vesting_remaining_reward(account_addr: address, bridge_id: u64, stage: u64): u64
-
- - - -
-Implementation - - -
public fun get_operator_vesting_remaining_reward(account_addr: address, bridge_id: u64, stage: u64): u64 acquires VestingStore {
-    let vesting = get_vesting<OperatorVesting>(account_addr, bridge_id, stage);
-    vesting.remaining_reward
-}
-
- - - -
diff --git a/initia_stdlib/doc/vip.md b/initia_stdlib/doc/vip.md deleted file mode 100644 index 08026a9..0000000 --- a/initia_stdlib/doc/vip.md +++ /dev/null @@ -1,2853 +0,0 @@ - - - -# Module `0x1::vip` - - - -- [Resource `ModuleStore`](#0x1_vip_ModuleStore) -- [Struct `StageData`](#0x1_vip_StageData) -- [Struct `Snapshot`](#0x1_vip_Snapshot) -- [Struct `Bridge`](#0x1_vip_Bridge) -- [Struct `RewardDistribution`](#0x1_vip_RewardDistribution) -- [Struct `ModuleResponse`](#0x1_vip_ModuleResponse) -- [Struct `SnapshotResponse`](#0x1_vip_SnapshotResponse) -- [Struct `StageDataResponse`](#0x1_vip_StageDataResponse) -- [Struct `BridgeResponse`](#0x1_vip_BridgeResponse) -- [Struct `FundEvent`](#0x1_vip_FundEvent) -- [Struct `StageAdvanceEvent`](#0x1_vip_StageAdvanceEvent) -- [Constants](#@Constants_0) -- [Function `init_module`](#0x1_vip_init_module) -- [Function `bytes_cmp`](#0x1_vip_bytes_cmp) -- [Function `score_hash`](#0x1_vip_score_hash) -- [Function `assert_merkle_proofs`](#0x1_vip_assert_merkle_proofs) -- [Function `check_chain_permission`](#0x1_vip_check_chain_permission) -- [Function `check_agent_permission`](#0x1_vip_check_agent_permission) -- [Function `load_bridge`](#0x1_vip_load_bridge) -- [Function `load_bridge_mut`](#0x1_vip_load_bridge_mut) -- [Function `claim_user_reward`](#0x1_vip_claim_user_reward) -- [Function `zapping`](#0x1_vip_zapping) -- [Function `extract_commission`](#0x1_vip_extract_commission) -- [Function `split_reward`](#0x1_vip_split_reward) -- [Function `split_reward_with_share`](#0x1_vip_split_reward_with_share) -- [Function `split_reward_with_share_internal`](#0x1_vip_split_reward_with_share_internal) -- [Function `fund_reward`](#0x1_vip_fund_reward) -- [Function `calculate_balance_share`](#0x1_vip_calculate_balance_share) -- [Function `calculate_weight_share`](#0x1_vip_calculate_weight_share) -- [Function `claim_operator_reward`](#0x1_vip_claim_operator_reward) -- [Function `register`](#0x1_vip_register) -- [Function `deregister`](#0x1_vip_deregister) -- [Function `update_agent`](#0x1_vip_update_agent) -- [Function `fund_reward_script`](#0x1_vip_fund_reward_script) -- [Function `submit_snapshot`](#0x1_vip_submit_snapshot) -- [Function `update_snapshot`](#0x1_vip_update_snapshot) -- [Function `claim_operator_reward_script`](#0x1_vip_claim_operator_reward_script) -- [Function `claim_user_reward_script`](#0x1_vip_claim_user_reward_script) -- [Function `batch_claim_operator_reward_script`](#0x1_vip_batch_claim_operator_reward_script) -- [Function `batch_claim_user_reward_script`](#0x1_vip_batch_claim_user_reward_script) -- [Function `update_vip_weight`](#0x1_vip_update_vip_weight) -- [Function `update_vesting_period`](#0x1_vip_update_vesting_period) -- [Function `update_minimum_tvl`](#0x1_vip_update_minimum_tvl) -- [Function `update_maximum_tvl`](#0x1_vip_update_maximum_tvl) -- [Function `update_proportion`](#0x1_vip_update_proportion) -- [Function `update_pool_split_ratio`](#0x1_vip_update_pool_split_ratio) -- [Function `zapping_script`](#0x1_vip_zapping_script) -- [Function `batch_zapping_script`](#0x1_vip_batch_zapping_script) -- [Function `update_operator_commission`](#0x1_vip_update_operator_commission) -- [Function `get_snapshot`](#0x1_vip_get_snapshot) -- [Function `get_expected_reward`](#0x1_vip_get_expected_reward) -- [Function `get_stage_data`](#0x1_vip_get_stage_data) -- [Function `get_bridge_info`](#0x1_vip_get_bridge_info) -- [Function `get_next_stage`](#0x1_vip_get_next_stage) -- [Function `get_module_store`](#0x1_vip_get_module_store) -- [Function `batch_simulate_user_claim_reward`](#0x1_vip_batch_simulate_user_claim_reward) -- [Function `simulate_user_claim_reward`](#0x1_vip_simulate_user_claim_reward) - - -
use 0x1::bcs;
-use 0x1::block;
-use 0x1::coin;
-use 0x1::decimal256;
-use 0x1::error;
-use 0x1::event;
-use 0x1::fungible_asset;
-use 0x1::hash;
-use 0x1::object;
-use 0x1::option;
-use 0x1::primary_fungible_store;
-use 0x1::signer;
-use 0x1::simple_map;
-use 0x1::string;
-use 0x1::table;
-use 0x1::table_key;
-use 0x1::vector;
-use 0x1::vip_operator;
-use 0x1::vip_reward;
-use 0x1::vip_vault;
-use 0x1::vip_vesting;
-use 0x1::vip_zapping;
-
- - - - - -## Resource `ModuleStore` - - - -
struct ModuleStore has key
-
- - - -
-Fields - - -
-
-stage: u64 -
-
- -
-
-user_vesting_period: u64 -
-
- -
-
-operator_vesting_period: u64 -
-
- -
-
-agent: address -
-
- -
-
-proportion: decimal256::Decimal256 -
-
- -
-
-pool_split_ratio: decimal256::Decimal256 -
-
- -
-
-maximum_tvl: u64 -
-
- -
-
-minimum_tvl: u64 -
-
- -
-
-stage_data: table::Table<vector<u8>, vip::StageData> -
-
- -
-
-bridges: table::Table<vector<u8>, vip::Bridge> -
-
- -
-
- - -
- - - -## Struct `StageData` - - - -
struct StageData has store
-
- - - -
-Fields - - -
-
-pool_split_ratio: decimal256::Decimal256 -
-
- -
-
-total_operator_funded_reward: u64 -
-
- -
-
-total_user_funded_reward: u64 -
-
- -
-
-user_vesting_period: u64 -
-
- -
-
-operator_vesting_period: u64 -
-
- -
-
-user_vesting_release_time: u64 -
-
- -
-
-operator_vesting_release_time: u64 -
-
- -
-
-proportion: decimal256::Decimal256 -
-
- -
-
-snapshots: table::Table<vector<u8>, vip::Snapshot> -
-
- -
-
- - -
- - - -## Struct `Snapshot` - - - -
struct Snapshot has store
-
- - - -
-Fields - - -
-
-merkle_root: vector<u8> -
-
- -
-
-total_l2_score: u64 -
-
- -
-
- - -
- - - -## Struct `Bridge` - - - -
struct Bridge has drop, store
-
- - - -
-Fields - - -
-
-bridge_addr: address -
-
- -
-
-operator_addr: address -
-
- -
-
-vip_weight: u64 -
-
- -
-
-operator_reward_store_addr: address -
-
- -
-
-user_reward_store_addr: address -
-
- -
-
- - -
- - - -## Struct `RewardDistribution` - - - -
struct RewardDistribution has drop, store
-
- - - -
-Fields - - -
-
-bridge_id: u64 -
-
- -
-
-user_reward_store_addr: address -
-
- -
-
-operator_reward_store_addr: address -
-
- -
-
-user_reward_amount: u64 -
-
- -
-
-operator_reward_amount: u64 -
-
- -
-
- - -
- - - -## Struct `ModuleResponse` - - - -
struct ModuleResponse has drop
-
- - - -
-Fields - - -
-
-stage: u64 -
-
- -
-
-agent: address -
-
- -
-
-proportion: decimal256::Decimal256 -
-
- -
-
-pool_split_ratio: decimal256::Decimal256 -
-
- -
-
-user_vesting_period: u64 -
-
- -
-
-operator_vesting_period: u64 -
-
- -
-
-minimum_tvl: u64 -
-
- -
-
-maximum_tvl: u64 -
-
- -
-
- - -
- - - -## Struct `SnapshotResponse` - - - -
struct SnapshotResponse has drop
-
- - - -
-Fields - - -
-
-merkle_root: vector<u8> -
-
- -
-
-total_l2_score: u64 -
-
- -
-
- - -
- - - -## Struct `StageDataResponse` - - - -
struct StageDataResponse has drop
-
- - - -
-Fields - - -
-
-pool_split_ratio: decimal256::Decimal256 -
-
- -
-
-total_operator_funded_reward: u64 -
-
- -
-
-total_user_funded_reward: u64 -
-
- -
-
-user_vesting_period: u64 -
-
- -
-
-operator_vesting_period: u64 -
-
- -
-
-user_vesting_release_time: u64 -
-
- -
-
-operator_vesting_release_time: u64 -
-
- -
-
-proportion: decimal256::Decimal256 -
-
- -
-
- - -
- - - -## Struct `BridgeResponse` - - - -
struct BridgeResponse has drop
-
- - - -
-Fields - - -
-
-bridge_addr: address -
-
- -
-
-operator_addr: address -
-
- -
-
-vip_weight: u64 -
-
- -
-
-user_reward_store_addr: address -
-
- -
-
-operator_reward_store_addr: address -
-
- -
-
- - -
- - - -## Struct `FundEvent` - - - -
#[event]
-struct FundEvent has drop, store
-
- - - -
-Fields - - -
-
-stage: u64 -
-
- -
-
-total_operator_funded_reward: u64 -
-
- -
-
-total_user_funded_reward: u64 -
-
- -
-
-reward_distribution: vector<vip::RewardDistribution> -
-
- -
-
- - -
- - - -## Struct `StageAdvanceEvent` - - - -
#[event]
-struct StageAdvanceEvent has drop, store
-
- - - -
-Fields - - -
-
-stage: u64 -
-
- -
-
-pool_split_ratio: decimal256::Decimal256 -
-
- -
-
-total_operator_funded_reward: u64 -
-
- -
-
-total_user_funded_reward: u64 -
-
- -
-
-user_vesting_period: u64 -
-
- -
-
-operator_vesting_period: u64 -
-
- -
-
-user_vesting_release_time: u64 -
-
- -
-
-operator_vesting_release_time: u64 -
-
- -
-
-proportion: decimal256::Decimal256 -
-
- -
-
- - -
- - - -## Constants - - - - - - -
const EUNAUTHORIZED: u64 = 5;
-
- - - - - - - -
const REWARD_SYMBOL: vector<u8> = [117, 105, 110, 105, 116];
-
- - - - - - - -
const DEFAULT_MAXIMUM_TVL: u64 = 100000000000000000;
-
- - - - - - - -
const DEFAULT_MINIMUM_TVL: u64 = 0;
-
- - - - - - - -
const DEFAULT_OPERATOR_VESTING_PERIOD: u64 = 52;
-
- - - - - - - -
const DEFAULT_POOL_SPLIT_RATIO: vector<u8> = [48, 46, 52];
-
- - - - - - - -
const DEFAULT_PROPORTION_RATIO: vector<u8> = [48, 46, 53];
-
- - - - - - - -
const DEFAULT_USER_VESTING_PERIOD: u64 = 52;
-
- - - - - - - -
const DEFAULT_VIP_START_STAGE: u64 = 1;
-
- - - - - - - -
const EALREADY_FUNDED: u64 = 10;
-
- - - - - - - -
const EALREADY_REGISTERED: u64 = 13;
-
- - - - - - - -
const EALREADY_RELEASED: u64 = 20;
-
- - - - - - - -
const EBRIDGE_NOT_FOUND: u64 = 14;
-
- - - - - - - -
const EINVALID_BATCH_ARGUMENT: u64 = 17;
-
- - - - - - - -
const EINVALID_FUND_STAGE: u64 = 11;
-
- - - - - - - -
const EINVALID_MAX_TVL: u64 = 7;
-
- - - - - - - -
const EINVALID_MERKLE_PROOFS: u64 = 2;
-
- - - - - - - -
const EINVALID_MIN_TVL: u64 = 6;
-
- - - - - - - -
const EINVALID_PROOF_LENGTH: u64 = 3;
-
- - - - - - - -
const EINVALID_PROPORTION: u64 = 8;
-
- - - - - - - -
const EINVALID_TOTAL_REWARD: u64 = 18;
-
- - - - - - - -
const EINVALID_TOTAL_SHARE: u64 = 9;
-
- - - - - - - -
const EINVALID_VEST_PERIOD: u64 = 4;
-
- - - - - - - -
const ESNAPSHOT_ALREADY_EXISTS: u64 = 16;
-
- - - - - - - -
const ESNAPSHOT_NOT_EXISTS: u64 = 19;
-
- - - - - - - -
const ESTAGE_DATA_NOT_FOUND: u64 = 1;
-
- - - - - - - -
const EVESTING_IN_PROGRESS: u64 = 15;
-
- - - - - - - -
const EZAPPING_STAKELISTED_NOT_ENOUGH: u64 = 12;
-
- - - - - - - -
const PROOF_LENGTH: u64 = 32;
-
- - - - - -## Function `init_module` - - - -
fun init_module(chain: &signer)
-
- - - -
-Implementation - - -
fun init_module(chain: &signer) {
-    move_to(chain, ModuleStore {
-        stage: DEFAULT_VIP_START_STAGE,
-        user_vesting_period: DEFAULT_USER_VESTING_PERIOD,
-        operator_vesting_period: DEFAULT_OPERATOR_VESTING_PERIOD,
-        proportion: decimal256::from_string(&string::utf8(DEFAULT_PROPORTION_RATIO)),
-        pool_split_ratio: decimal256::from_string(&string::utf8(DEFAULT_POOL_SPLIT_RATIO)),
-        agent: signer::address_of(chain),
-        maximum_tvl: DEFAULT_MAXIMUM_TVL,
-        minimum_tvl: DEFAULT_MINIMUM_TVL,
-        stage_data: table::new<vector<u8>, StageData>(),
-        bridges: table::new<vector<u8>, Bridge>(),
-    });
-}
-
- - - -
- - - -## Function `bytes_cmp` - - - -
fun bytes_cmp(v1: &vector<u8>, v2: &vector<u8>): u8
-
- - - -
-Implementation - - -
fun bytes_cmp(v1: &vector<u8>, v2: &vector<u8>): u8 {
-    assert!(vector::length(v1) == PROOF_LENGTH, error::invalid_argument(EINVALID_PROOF_LENGTH));
-    assert!(vector::length(v2) == PROOF_LENGTH, error::invalid_argument(EINVALID_PROOF_LENGTH));
-
-    let i = 0;
-    while (i < 32 ) {
-        let e1 = *vector::borrow(v1, i);
-        let e2 = *vector::borrow(v2, i);
-        if (e1 > e2) {
-            return 1
-        } else if (e2 > e1) {
-            return 2
-        };
-        i = i + 1;
-    };
-
-    0
-}
-
- - - -
- - - -## Function `score_hash` - - - -
fun score_hash(bridge_id: u64, stage: u64, account_addr: address, l2_score: u64, total_l2_score: u64): vector<u8>
-
- - - -
-Implementation - - -
fun score_hash(
-    bridge_id: u64,
-    stage: u64,
-    account_addr: address,
-    l2_score: u64,
-    total_l2_score: u64,
-): vector<u8> {
-    let target_hash = {
-        let score_data = vector::empty<u8>();
-        vector::append(&mut score_data, bcs::to_bytes(&bridge_id));
-        vector::append(&mut score_data, bcs::to_bytes(&stage));
-        vector::append(&mut score_data, bcs::to_bytes(&account_addr));
-        vector::append(&mut score_data, bcs::to_bytes(&l2_score));
-        vector::append(&mut score_data, bcs::to_bytes(&total_l2_score));
-
-        sha3_256(score_data)
-    };
-    target_hash
-}
-
- - - -
- - - -## Function `assert_merkle_proofs` - - - -
fun assert_merkle_proofs(merkle_proofs: vector<vector<u8>>, merkle_root: vector<u8>, target_hash: vector<u8>)
-
- - - -
-Implementation - - -
fun assert_merkle_proofs(
-    merkle_proofs: vector<vector<u8>>,
-    merkle_root: vector<u8>,
-    target_hash: vector<u8>,
-) {
-    // must use sorted merkle tree
-    let i = 0;
-    let len = vector::length(&merkle_proofs);
-    let root_seed = target_hash;
-
-    while (i < len) {
-        let proof = vector::borrow(&merkle_proofs, i);
-
-        let cmp = bytes_cmp(&root_seed, proof);
-        root_seed = if (cmp == 2 /* less */) {
-            let tmp = vector::empty();
-            vector::append(&mut tmp, root_seed);
-            vector::append(&mut tmp, *proof);
-
-            sha3_256(tmp)
-        } else /* greator or equals */ {
-            let tmp = vector::empty();
-            vector::append(&mut tmp, *proof);
-            vector::append(&mut tmp, root_seed);
-
-            sha3_256(tmp)
-        };
-
-        i = i + 1;
-    };
-    let root_hash = root_seed;
-    assert!(merkle_root == root_hash, error::invalid_argument(EINVALID_MERKLE_PROOFS));
-}
-
- - - -
- - - -## Function `check_chain_permission` - - - -
fun check_chain_permission(chain: &signer)
-
- - - -
-Implementation - - -
fun check_chain_permission(chain: &signer) {
-    assert!(signer::address_of(chain) == @initia_std, error::permission_denied(EUNAUTHORIZED));
-}
-
- - - -
- - - -## Function `check_agent_permission` - - - -
fun check_agent_permission(agent: &signer)
-
- - - -
-Implementation - - -
fun check_agent_permission(agent: &signer) acquires ModuleStore {
-    let module_store = borrow_global<ModuleStore>(@initia_std);
-    assert!(signer::address_of(agent) == module_store.agent, error::permission_denied(EUNAUTHORIZED));
-}
-
- - - -
- - - -## Function `load_bridge` - - - -
fun load_bridge(bridges: &table::Table<vector<u8>, vip::Bridge>, bridge_id: u64): &vip::Bridge
-
- - - -
-Implementation - - -
fun load_bridge(bridges: &table::Table<vector<u8>, Bridge>, bridge_id: u64): &Bridge {
-    assert!(table::contains(bridges, table_key::encode_u64(bridge_id)), error::not_found(EBRIDGE_NOT_FOUND));
-    table::borrow(bridges, table_key::encode_u64(bridge_id))
-}
-
- - - -
- - - -## Function `load_bridge_mut` - - - -
fun load_bridge_mut(bridges: &mut table::Table<vector<u8>, vip::Bridge>, bridge_id: u64): &mut vip::Bridge
-
- - - -
-Implementation - - -
fun load_bridge_mut(bridges: &mut table::Table<vector<u8>, Bridge>, bridge_id: u64): &mut Bridge {
-    assert!(table::contains(bridges, table_key::encode_u64(bridge_id)), error::not_found(EBRIDGE_NOT_FOUND));
-    table::borrow_mut(bridges, table_key::encode_u64(bridge_id))
-}
-
- - - -
- - - -## Function `claim_user_reward` - - - -
fun claim_user_reward(account: &signer, bridge_id: u64, stage: u64, merkle_proofs: vector<vector<u8>>, l2_score: u64): fungible_asset::FungibleAsset
-
- - - -
-Implementation - - -
fun claim_user_reward (
-    account: &signer,
-    bridge_id: u64,
-    stage: u64,
-    merkle_proofs: vector<vector<u8>>,
-    l2_score: u64,
-): FungibleAsset acquires ModuleStore {
-    let account_addr = signer::address_of(account);
-    let module_store = borrow_global<ModuleStore>(@initia_std);
-    let (_, block_time) = block::get_block_info();
-
-    assert!(table::contains(&module_store.stage_data, table_key::encode_u64(stage)), error::not_found(ESTAGE_DATA_NOT_FOUND));
-    let stage_data = table::borrow(&module_store.stage_data, table_key::encode_u64(stage));
-    let snapshot = table::borrow(&stage_data.snapshots, table_key::encode_u64(bridge_id));
-    assert!(block_time >= stage_data.user_vesting_release_time , error::unavailable(EVESTING_IN_PROGRESS));
-
-    let target_hash = score_hash(
-        bridge_id,
-        stage,
-        account_addr,
-        l2_score,
-        snapshot.total_l2_score,
-    );
-
-    assert_merkle_proofs(
-        merkle_proofs,
-        snapshot.merkle_root,
-        target_hash,
-    );
-
-    let vested_reward = vip_vesting::claim_user_reward(
-        account_addr,
-        bridge_id,
-        stage,
-        stage + stage_data.user_vesting_period,
-        l2_score,
-        snapshot.total_l2_score,
-        stage_data.proportion
-    );
-
-    vested_reward
-}
-
- - - -
- - - -## Function `zapping` - - - -
fun zapping(account: &signer, bridge_id: u64, lp_metadata: object::Object<fungible_asset::Metadata>, min_liquidity: option::Option<u64>, validator: string::String, stage: u64, zapping_amount: u64, stakelisted_amount: u64, stakelisted_metadata: object::Object<fungible_asset::Metadata>)
-
- - - -
-Implementation - - -
fun zapping(
-    account: &signer,
-    bridge_id: u64,
-    lp_metadata: Object<Metadata>,
-    min_liquidity: option::Option<u64>,
-    validator: string::String,
-    stage: u64,
-    zapping_amount: u64,
-    stakelisted_amount: u64,
-    stakelisted_metadata: Object<Metadata>,
-) {
-    let account_addr = signer::address_of(account);
-    let esinit = vip_vesting::zapping_vesting(
-        account_addr,
-        bridge_id,
-        stage,
-        zapping_amount
-    );
-    assert!(primary_fungible_store::balance(account_addr, stakelisted_metadata) >= stakelisted_amount, error::invalid_argument(EZAPPING_STAKELISTED_NOT_ENOUGH));
-    let stakelisted = primary_fungible_store::withdraw(account, stakelisted_metadata, stakelisted_amount);
-
-    vip_zapping::zapping(
-        account,
-        bridge_id,
-        lp_metadata,
-        min_liquidity,
-        validator,
-        stage,
-        esinit,
-        stakelisted
-    );
-}
-
- - - -
- - - -## Function `extract_commission` - - - -
fun extract_commission(operator_addr: address, bridge_id: u64, reward: fungible_asset::FungibleAsset): (fungible_asset::FungibleAsset, fungible_asset::FungibleAsset)
-
- - - -
-Implementation - - -
fun extract_commission(
-    operator_addr: address,
-    bridge_id: u64,
-    reward: FungibleAsset,
-): (FungibleAsset, FungibleAsset) {
-    let commission_rate = vip_operator::get_operator_commission(operator_addr, bridge_id);
-    let commission_amount = decimal256::mul_u64(&commission_rate, fungible_asset::amount(&reward));
-    let commission = fungible_asset::extract(&mut reward, commission_amount);
-    (commission, reward)
-}
-
- - - -
- - - -## Function `split_reward` - - - -
fun split_reward(module_store: &mut vip::ModuleStore, stage: u64, balance_shares: &simple_map::SimpleMap<u64, u64>, weight_shares: &simple_map::SimpleMap<u64, u64>, total_balance: u64, total_weight: u64, balance_pool_reward: fungible_asset::FungibleAsset, weight_pool_reward: fungible_asset::FungibleAsset): (u64, u64)
-
- - - -
-Implementation - - -
fun split_reward(
-    module_store: &mut ModuleStore,
-    stage: u64,
-    balance_shares: &SimpleMap<u64, u64>,
-    weight_shares: &SimpleMap<u64, u64>,
-    total_balance: u64,
-    total_weight: u64,
-    balance_pool_reward: FungibleAsset,
-    weight_pool_reward: FungibleAsset,
-): (u64, u64) {
-    let reward_distributions = vector::empty<RewardDistribution>();
-
-    let initial_balance_pool_reward_amount = fungible_asset::amount(&balance_pool_reward);
-    let initial_weight_pool_reward_amount = fungible_asset::amount(&weight_pool_reward);
-    let total_user_funded_reward = 0;
-    let total_operator_funded_reward = 0;
-
-    let index = 0;
-    let iter = table::iter(&module_store.bridges, option::none(), option::none(), 1);
-    loop {
-        if (!table::prepare<vector<u8>, Bridge>(&mut iter)){
-            break
-        };
-
-        let (bridge_id_vec, bridge) = table::next<vector<u8>, Bridge>(&mut iter);
-        let bridge_id = table_key::decode_u64(bridge_id_vec);
-        let balance_reward = split_reward_with_share(
-            balance_shares,
-            bridge_id,
-            total_balance,
-            initial_balance_pool_reward_amount,
-            &mut balance_pool_reward
-        );
-        let (balance_commission, balance_user_reward) = extract_commission(
-            bridge.operator_addr,
-            bridge_id,
-            balance_reward
-        );
-
-        let weight_reward = split_reward_with_share(
-            weight_shares,
-            bridge_id,
-            total_weight,
-            initial_weight_pool_reward_amount,
-            &mut weight_pool_reward
-        );
-        let (weight_commission, weight_user_reward) = extract_commission(
-            bridge.operator_addr,
-            bridge_id,
-            weight_reward
-        );
-
-        fungible_asset::merge(&mut balance_commission, weight_commission);
-        fungible_asset::merge(&mut balance_user_reward, weight_user_reward);
-
-        let commission_sum = balance_commission;
-        let user_reward_sum = balance_user_reward;
-
-        total_operator_funded_reward = total_operator_funded_reward + fungible_asset::amount(&commission_sum);
-        total_user_funded_reward = total_user_funded_reward + fungible_asset::amount(&user_reward_sum);
-
-        vector::push_back(&mut reward_distributions, RewardDistribution {
-            bridge_id,
-            user_reward_store_addr: bridge.user_reward_store_addr,
-            operator_reward_store_addr: bridge.operator_reward_store_addr,
-            user_reward_amount: fungible_asset::amount(&user_reward_sum),
-            operator_reward_amount: fungible_asset::amount(&commission_sum)
-        });
-
-        vip_vesting::supply_reward_on_operator(
-            bridge_id,
-            stage,
-            commission_sum,
-        );
-
-        vip_vesting::supply_reward_on_user(
-            bridge_id,
-            stage,
-            user_reward_sum,
-        );
-
-        index = index + 1;
-    };
-
-    let vault_store_addr = vip_vault::get_vault_store_address();
-    primary_fungible_store::deposit(vault_store_addr, balance_pool_reward);
-    primary_fungible_store::deposit(vault_store_addr, weight_pool_reward);
-
-    event::emit(
-        FundEvent {
-            stage,
-            total_operator_funded_reward,
-            total_user_funded_reward,
-            reward_distribution: reward_distributions
-        }
-    );
-
-    (total_operator_funded_reward, total_user_funded_reward)
-}
-
- - - -
- - - -## Function `split_reward_with_share` - - - -
fun split_reward_with_share(shares: &simple_map::SimpleMap<u64, u64>, bridge_id: u64, total_share: u64, total_reward_amount: u64, reward: &mut fungible_asset::FungibleAsset): fungible_asset::FungibleAsset
-
- - - -
-Implementation - - -
fun split_reward_with_share(
-    shares: &SimpleMap<u64, u64>,
-    bridge_id: u64,
-    total_share: u64,
-    total_reward_amount: u64,
-    reward: &mut FungibleAsset,
-): FungibleAsset {
-    let split_amount = split_reward_with_share_internal(shares, bridge_id, total_share, total_reward_amount);
-    fungible_asset::extract(reward, split_amount)
-}
-
- - - -
- - - -## Function `split_reward_with_share_internal` - - - -
fun split_reward_with_share_internal(shares: &simple_map::SimpleMap<u64, u64>, bridge_id: u64, total_share: u64, total_reward_amount: u64): u64
-
- - - -
-Implementation - - -
fun split_reward_with_share_internal(
-    shares: &SimpleMap<u64, u64>,
-    bridge_id: u64,
-    total_share: u64,
-    total_reward_amount: u64,
-): u64 {
-    let share_amount = *simple_map::borrow(shares, &bridge_id);
-    let share_ratio = decimal256::from_ratio_u64(share_amount, total_share);
-    let split_amount = decimal256::mul_u64(&share_ratio, total_reward_amount);
-    split_amount
-}
-
- - - -
- - - -## Function `fund_reward` - - - -
fun fund_reward(module_store: &mut vip::ModuleStore, stage: u64, initial_reward: fungible_asset::FungibleAsset): (u64, u64)
-
- - - -
-Implementation - - -
fun fund_reward(
-    module_store: &mut ModuleStore,
-    stage: u64,
-    initial_reward: FungibleAsset
-): (u64, u64) {
-    let initial_amount = fungible_asset::amount(&initial_reward);
-
-    let balance_shares = simple_map::create<u64, u64>();
-    let weight_shares = simple_map::create<u64, u64>();
-
-    let total_balance = calculate_balance_share(module_store, &mut balance_shares);
-    assert!(total_balance > 0, error::invalid_state(EINVALID_TOTAL_SHARE));
-    let total_weight = calculate_weight_share(module_store, &mut weight_shares);
-    assert!(total_weight > 0, error::invalid_state(EINVALID_TOTAL_SHARE));
-
-    let balance_pool_reward_amount = decimal256::mul_u64(&module_store.pool_split_ratio, initial_amount);
-    let balance_pool_reward = fungible_asset::extract(&mut initial_reward, balance_pool_reward_amount);
-    let weight_pool_reward = initial_reward;
-
-    let (total_operator_funded_reward, total_user_funded_reward) = split_reward(
-        module_store,
-        stage,
-        &balance_shares,
-        &weight_shares,
-        total_balance,
-        total_weight,
-        balance_pool_reward,
-        weight_pool_reward
-    );
-
-    (total_operator_funded_reward, total_user_funded_reward)
-}
-
- - - -
- - - -## Function `calculate_balance_share` - - - -
fun calculate_balance_share(module_store: &vip::ModuleStore, balance_shares: &mut simple_map::SimpleMap<u64, u64>): u64
-
- - - -
-Implementation - - -
fun calculate_balance_share(
-    module_store: &ModuleStore,
-    balance_shares: &mut SimpleMap<u64, u64>
-): u64 {
-    let total_balance = 0;
-
-    let iter = table::iter(&module_store.bridges, option::none(), option::none(), 1);
-    loop {
-        if (!table::prepare<vector<u8>, Bridge>(&mut iter)){
-            break
-        };
-        let (bridge_id_vec, bridge) = table::next<vector<u8>, Bridge>(&mut iter);
-        let bridge_id = table_key::decode_u64(bridge_id_vec);
-
-        let bridge_balance = primary_fungible_store::balance(bridge.bridge_addr, vip_reward::reward_metadata());
-        let bridge_balance = if (bridge_balance > module_store.maximum_tvl) {
-            module_store.maximum_tvl
-        } else if (bridge_balance < module_store.minimum_tvl){
-            0
-        } else {
-            bridge_balance
-        };
-
-        total_balance = total_balance + bridge_balance;
-        simple_map::add(balance_shares, bridge_id, bridge_balance);
-    };
-
-    (total_balance)
-}
-
- - - -
- - - -## Function `calculate_weight_share` - - - -
fun calculate_weight_share(module_store: &vip::ModuleStore, weight_shares: &mut simple_map::SimpleMap<u64, u64>): u64
-
- - - -
-Implementation - - -
fun calculate_weight_share(
-    module_store: &ModuleStore,
-    weight_shares: &mut SimpleMap<u64, u64>
-): u64 {
-    let total_weight = 0;
-
-    let iter = table::iter(&module_store.bridges, option::none(), option::none(), 1);
-    loop {
-        if (!table::prepare<vector<u8>, Bridge>(&mut iter)){
-            break
-        };
-        let (bridge_id_vec, bridge) = table::next<vector<u8>, Bridge>(&mut iter);
-        let bridge_id = table_key::decode_u64(bridge_id_vec);
-
-        let bridge_balance = primary_fungible_store::balance(bridge.bridge_addr, vip_reward::reward_metadata());
-        let weight = if (bridge_balance < module_store.minimum_tvl) {
-            0
-        } else {
-            bridge.vip_weight
-        };
-
-        total_weight = total_weight + weight;
-        simple_map::add(weight_shares, bridge_id, weight);
-    };
-
-    (total_weight)
-}
-
- - - -
- - - -## Function `claim_operator_reward` - - - -
fun claim_operator_reward(operator: &signer, bridge_id: u64, stage: u64): fungible_asset::FungibleAsset
-
- - - -
-Implementation - - -
fun claim_operator_reward(
-    operator: &signer,
-    bridge_id: u64,
-    stage: u64,
-): FungibleAsset acquires ModuleStore {
-    let operator_addr = signer::address_of(operator);
-    let module_store = borrow_global<ModuleStore>(@initia_std);
-    let (_, block_time) = block::get_block_info();
-
-    // assert claimable conditions
-    assert!(table::contains(&module_store.stage_data, table_key::encode_u64(stage)), error::not_found(ESTAGE_DATA_NOT_FOUND));
-    let stage_data = table::borrow(&module_store.stage_data, table_key::encode_u64(stage));
-    assert!(block_time >= stage_data.operator_vesting_release_time , error::unavailable(EVESTING_IN_PROGRESS));
-
-    let vested_reward = vip_vesting::claim_operator_reward(
-        operator_addr,
-        bridge_id,
-        stage,
-        stage + stage_data.operator_vesting_period,
-    );
-
-    vested_reward
-}
-
- - - -
- - - -## Function `register` - - - -
public entry fun register(chain: &signer, operator: address, bridge_id: u64, bridge_address: address, vip_weight: u64, operator_commission_max_rate: decimal256::Decimal256, operator_commission_max_change_rate: decimal256::Decimal256, operator_commission_rate: decimal256::Decimal256)
-
- - - -
-Implementation - - -
public entry fun register(
-    chain: &signer,
-    operator: address,
-    bridge_id: u64,
-    bridge_address: address,
-    vip_weight: u64,
-    operator_commission_max_rate: Decimal256,
-    operator_commission_max_change_rate: Decimal256,
-    operator_commission_rate: Decimal256,
-) acquires ModuleStore {
-    check_chain_permission(chain);
-
-    let module_store = borrow_global_mut<ModuleStore>(signer::address_of(chain));
-    assert!(!table::contains(&module_store.bridges, table_key::encode_u64(bridge_id)), error::already_exists(EALREADY_REGISTERED));
-
-    // register chain stores
-    if (!vip_operator::is_operator_store_registered(operator, bridge_id)) {
-        vip_operator::register_operator_store(
-            chain,
-            operator,
-            bridge_id,
-            module_store.stage,
-            operator_commission_max_rate,
-            operator_commission_max_change_rate,
-            operator_commission_rate,
-        );
-    };
-    if (!vip_vesting::is_operator_reward_store_registered(bridge_id)) {
-        vip_vesting::register_operator_reward_store(chain, bridge_id);
-    };
-    if (!vip_vesting::is_user_reward_store_registered(bridge_id)) {
-        vip_vesting::register_user_reward_store(chain, bridge_id);
-    };
-
-    // add bridge info
-    table::add(&mut module_store.bridges, table_key::encode_u64(bridge_id), Bridge {
-        bridge_addr: bridge_address,
-        operator_addr: operator,
-        vip_weight,
-        user_reward_store_addr: vip_vesting::get_user_reward_store_address(bridge_id),
-        operator_reward_store_addr: vip_vesting::get_operator_reward_store_address(bridge_id),
-    });
-}
-
- - - -
- - - -## Function `deregister` - - - -
public entry fun deregister(chain: &signer, bridge_id: u64)
-
- - - -
-Implementation - - -
public entry fun deregister(
-    chain: &signer,
-    bridge_id: u64,
-) acquires ModuleStore {
-    check_chain_permission(chain);
-    let module_store = borrow_global_mut<ModuleStore>(signer::address_of(chain));
-    assert!(table::contains(&module_store.bridges, table_key::encode_u64(bridge_id)), error::not_found(EBRIDGE_NOT_FOUND));
-
-    table::remove(&mut module_store.bridges, table_key::encode_u64(bridge_id));
-}
-
- - - -
- - - -## Function `update_agent` - - - -
public entry fun update_agent(old_agent: &signer, new_agent: address)
-
- - - -
-Implementation - - -
public entry fun update_agent(
-    old_agent: &signer,
-    new_agent: address,
-) acquires ModuleStore {
-    check_agent_permission(old_agent);
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    module_store.agent = new_agent;
-}
-
- - - -
- - - -## Function `fund_reward_script` - - - -
public entry fun fund_reward_script(agent: &signer, stage: u64, user_vesting_release_time: u64, operator_vesting_release_time: u64)
-
- - - -
-Implementation - - -
public entry fun fund_reward_script(
-    agent: &signer,
-    stage: u64,
-    user_vesting_release_time: u64,
-    operator_vesting_release_time: u64,
-) acquires ModuleStore {
-    check_agent_permission(agent);
-
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    assert!(!table::contains(&mut module_store.stage_data, table_key::encode_u64(stage)), error::already_exists(EALREADY_FUNDED));
-    assert!(stage == module_store.stage, error::invalid_argument(EINVALID_FUND_STAGE));
-
-    let total_reward = vip_vault::claim(stage);
-    let (total_operator_funded_reward, total_user_funded_reward) = fund_reward(
-        module_store,
-        stage,
-        total_reward
-    );
-
-    // set stage data
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    table::add(&mut module_store.stage_data, table_key::encode_u64(stage), StageData {
-        pool_split_ratio: module_store.pool_split_ratio,
-        total_operator_funded_reward,
-        total_user_funded_reward,
-        user_vesting_period: module_store.user_vesting_period,
-        operator_vesting_period: module_store.operator_vesting_period,
-        user_vesting_release_time: user_vesting_release_time,
-        operator_vesting_release_time: operator_vesting_release_time,
-        proportion: module_store.proportion,
-        snapshots: table::new<vector<u8>, Snapshot>(),
-    });
-
-    event::emit(
-        StageAdvanceEvent {
-            stage,
-            pool_split_ratio: module_store.pool_split_ratio,
-            total_operator_funded_reward,
-            total_user_funded_reward,
-            user_vesting_period: module_store.user_vesting_period,
-            operator_vesting_period: module_store.operator_vesting_period,
-            user_vesting_release_time,
-            operator_vesting_release_time,
-            proportion: module_store.proportion,
-        }
-    );
-
-    module_store.stage = stage + 1;
-}
-
- - - -
- - - -## Function `submit_snapshot` - - - -
public entry fun submit_snapshot(agent: &signer, bridge_id: u64, stage: u64, merkle_root: vector<u8>, total_l2_score: u64)
-
- - - -
-Implementation - - -
public entry fun submit_snapshot(
-    agent: &signer,
-    bridge_id: u64,
-    stage: u64,
-    merkle_root: vector<u8>,
-    total_l2_score: u64,
-) acquires ModuleStore {
-    check_agent_permission(agent);
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    assert!(table::contains(&module_store.stage_data, table_key::encode_u64(stage)), error::not_found(ESTAGE_DATA_NOT_FOUND));
-    let stage_data = table::borrow_mut(&mut module_store.stage_data, table_key::encode_u64(stage));
-
-    assert!(!table::contains(&stage_data.snapshots, table_key::encode_u64(bridge_id)), error::already_exists(ESNAPSHOT_ALREADY_EXISTS));
-    table::add(&mut stage_data.snapshots, table_key::encode_u64(bridge_id), Snapshot {
-        merkle_root,
-        total_l2_score,
-    });
-}
-
- - - -
- - - -## Function `update_snapshot` - - - -
public entry fun update_snapshot(agent: &signer, bridge_id: u64, stage: u64, merkle_root: vector<u8>, total_l2_score: u64)
-
- - - -
-Implementation - - -
public entry fun update_snapshot(
-    agent: &signer,
-    bridge_id: u64,
-    stage: u64,
-    merkle_root: vector<u8>,
-    total_l2_score: u64,
-)  acquires ModuleStore {
-    check_agent_permission(agent);
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    assert!(table::contains(&module_store.stage_data, table_key::encode_u64(stage)), error::not_found(ESTAGE_DATA_NOT_FOUND));
-    let stage_data = table::borrow_mut(&mut module_store.stage_data, table_key::encode_u64(stage));
-
-    let (_, block_time) = block::get_block_info();
-    assert!(block_time < stage_data.user_vesting_release_time, error::unavailable(EALREADY_RELEASED));
-    assert!(block_time < stage_data.operator_vesting_release_time, error::unavailable(EALREADY_RELEASED));
-    assert!(table::contains(&stage_data.snapshots, table_key::encode_u64(bridge_id)), error::not_found(ESNAPSHOT_NOT_EXISTS));
-
-    let snapshot = table::borrow_mut(&mut stage_data.snapshots, table_key::encode_u64(bridge_id));
-    snapshot.merkle_root = merkle_root;
-    snapshot.total_l2_score = total_l2_score;
-}
-
- - - -
- - - -## Function `claim_operator_reward_script` - - - -
public entry fun claim_operator_reward_script(operator: &signer, bridge_id: u64, stage: u64)
-
- - - -
-Implementation - - -
public entry fun claim_operator_reward_script(
-    operator: &signer,
-    bridge_id: u64,
-    stage: u64,
-) acquires ModuleStore {
-    if (!vip_vesting::is_operator_vesting_store_registered(signer::address_of(operator), bridge_id)) {
-        vip_vesting::register_operator_vesting_store(operator, bridge_id);
-    };
-    let vested_reward = claim_operator_reward(
-        operator,
-        bridge_id,
-        stage,
-    );
-
-    coin::deposit(signer::address_of(operator), vested_reward);
-}
-
- - - -
- - - -## Function `claim_user_reward_script` - - - -
public entry fun claim_user_reward_script(account: &signer, bridge_id: u64, stage: u64, merkle_proofs: vector<vector<u8>>, l2_score: u64)
-
- - - -
-Implementation - - -
public entry fun claim_user_reward_script (
-    account: &signer,
-    bridge_id: u64,
-    stage: u64,
-    merkle_proofs: vector<vector<u8>>,
-    l2_score: u64,
-) acquires ModuleStore {
-    if (!vip_vesting::is_user_vesting_store_registered(signer::address_of(account), bridge_id)) {
-        vip_vesting::register_user_vesting_store(account, bridge_id);
-    };
-
-    let vested_reward = claim_user_reward(
-        account,
-        bridge_id,
-        stage,
-        merkle_proofs,
-        l2_score,
-    );
-
-    coin::deposit(signer::address_of(account), vested_reward);
-}
-
- - - -
- - - -## Function `batch_claim_operator_reward_script` - - - -
public entry fun batch_claim_operator_reward_script(operator: &signer, bridge_id: u64, stage: vector<u64>)
-
- - - -
-Implementation - - -
public entry fun batch_claim_operator_reward_script(
-    operator: &signer,
-    bridge_id: u64,
-    stage: vector<u64>,
-) acquires ModuleStore {
-    vector::enumerate_ref(&stage, |_i, s| {
-        claim_operator_reward_script(
-            operator,
-            bridge_id,
-            *s,
-        );
-    });
-}
-
- - - -
- - - -## Function `batch_claim_user_reward_script` - - - -
public entry fun batch_claim_user_reward_script(account: &signer, bridge_id: u64, stage: vector<u64>, merkle_proofs: vector<vector<vector<u8>>>, l2_score: vector<u64>)
-
- - - -
-Implementation - - -
public entry fun batch_claim_user_reward_script (
-    account: &signer,
-    bridge_id: u64,
-    stage: vector<u64>,
-    merkle_proofs: vector<vector<vector<u8>>>,
-    l2_score: vector<u64>,
-) acquires ModuleStore {
-    assert!(vector::length(&stage) == vector::length(&merkle_proofs) &&
-        vector::length(&merkle_proofs) == vector::length(&l2_score), error::invalid_argument(EINVALID_BATCH_ARGUMENT));
-
-    vector::enumerate_ref(&stage, |i, s| {
-        claim_user_reward_script(
-            account,
-            bridge_id,
-            *s,
-            *vector::borrow(&merkle_proofs, i),
-            *vector::borrow(&l2_score, i),
-        );
-    });
-}
-
- - - -
- - - -## Function `update_vip_weight` - - - -
public entry fun update_vip_weight(chain: &signer, bridge_id: u64, weight: u64)
-
- - - -
-Implementation - - -
public entry fun update_vip_weight(
-    chain: &signer,
-    bridge_id: u64,
-    weight: u64,
-) acquires ModuleStore {
-    check_chain_permission(chain);
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let bridge = load_bridge_mut(&mut module_store.bridges, bridge_id);
-    bridge.vip_weight = weight;
-}
-
- - - -
- - - -## Function `update_vesting_period` - - - -
public entry fun update_vesting_period(chain: &signer, user_vesting_period: u64, operator_vesting_period: u64)
-
- - - -
-Implementation - - -
public entry fun update_vesting_period(
-    chain: &signer,
-    user_vesting_period: u64,
-    operator_vesting_period: u64,
-) acquires ModuleStore {
-    check_chain_permission(chain);
-    let module_store = borrow_global_mut<ModuleStore>(signer::address_of(chain));
-    assert!(user_vesting_period > 0 && operator_vesting_period > 0, error::invalid_argument(EINVALID_VEST_PERIOD));
-    module_store.user_vesting_period = user_vesting_period;
-    module_store.operator_vesting_period = operator_vesting_period;
-}
-
- - - -
- - - -## Function `update_minimum_tvl` - - - -
public entry fun update_minimum_tvl(chain: &signer, minimum_tvl: u64)
-
- - - -
-Implementation - - -
public entry fun update_minimum_tvl(
-    chain: &signer,
-    minimum_tvl: u64,
-) acquires ModuleStore {
-    check_chain_permission(chain);
-    let module_store = borrow_global_mut<ModuleStore>(signer::address_of(chain));
-    assert!(minimum_tvl >= 0,error::invalid_argument(EINVALID_MIN_TVL));
-    module_store.minimum_tvl = minimum_tvl;
-}
-
- - - -
- - - -## Function `update_maximum_tvl` - - - -
public entry fun update_maximum_tvl(chain: &signer, maximum_tvl: u64)
-
- - - -
-Implementation - - -
public entry fun update_maximum_tvl(
-    chain: &signer,
-    maximum_tvl: u64,
-) acquires ModuleStore {
-    check_chain_permission(chain);
-    let module_store = borrow_global_mut<ModuleStore>(signer::address_of(chain));
-    assert!(maximum_tvl >= module_store.minimum_tvl,error::invalid_argument(EINVALID_MAX_TVL));
-    module_store.maximum_tvl = maximum_tvl;
-}
-
- - - -
- - - -## Function `update_proportion` - - - -
public entry fun update_proportion(chain: &signer, proportion: decimal256::Decimal256)
-
- - - -
-Implementation - - -
public entry fun update_proportion(
-    chain: &signer,
-    proportion: Decimal256,
-) acquires ModuleStore {
-    check_chain_permission(chain);
-    let module_store = borrow_global_mut<ModuleStore>(signer::address_of(chain));
-    assert!(
-        decimal256::val(&proportion) >= decimal256::val(&decimal256::zero()),
-        error::invalid_argument(EINVALID_PROPORTION)
-    );
-
-    module_store.proportion = proportion;
-}
-
- - - -
- - - -## Function `update_pool_split_ratio` - - - -
public entry fun update_pool_split_ratio(chain: &signer, pool_split_ratio: decimal256::Decimal256)
-
- - - -
-Implementation - - -
public entry fun update_pool_split_ratio(
-    chain: &signer,
-    pool_split_ratio: Decimal256,
-) acquires ModuleStore {
-    check_chain_permission(chain);
-    let module_store = borrow_global_mut<ModuleStore>(signer::address_of(chain));
-    assert!(
-        decimal256::val(&pool_split_ratio) <= decimal256::val(&decimal256::one()),
-        error::invalid_argument(EINVALID_PROPORTION)
-    );
-
-    module_store.pool_split_ratio = pool_split_ratio;
-}
-
- - - -
- - - -## Function `zapping_script` - - - -
public entry fun zapping_script(account: &signer, bridge_id: u64, lp_metadata: object::Object<fungible_asset::Metadata>, min_liquidity: option::Option<u64>, validator: string::String, stage: u64, zapping_amount: u64, stakelisted_amount: u64, stakelisted_metadata: object::Object<fungible_asset::Metadata>)
-
- - - -
-Implementation - - -
public entry fun zapping_script(
-    account: &signer,
-    bridge_id: u64,
-    lp_metadata: Object<Metadata>,
-    min_liquidity: option::Option<u64>,
-    validator: string::String,
-    stage: u64,
-    zapping_amount: u64,
-    stakelisted_amount: u64,
-    stakelisted_metadata: Object<Metadata>,
-) {
-    zapping(
-        account,
-        bridge_id,
-        lp_metadata,
-        min_liquidity,
-        validator,
-        stage,
-        zapping_amount,
-        stakelisted_amount,
-        stakelisted_metadata,
-    );
-}
-
- - - -
- - - -## Function `batch_zapping_script` - - - -
public entry fun batch_zapping_script(account: &signer, bridge_id: u64, lp_metadata: vector<object::Object<fungible_asset::Metadata>>, min_liquidity: vector<option::Option<u64>>, validator: vector<string::String>, stage: vector<u64>, zapping_amount: vector<u64>, stakelisted_amount: vector<u64>, stakelisted_metadata: vector<object::Object<fungible_asset::Metadata>>)
-
- - - -
-Implementation - - -
public entry fun batch_zapping_script(
-    account: &signer,
-    bridge_id: u64,
-    lp_metadata: vector<Object<Metadata>>,
-    min_liquidity: vector<option::Option<u64>>,
-    validator: vector<string::String>,
-    stage: vector<u64>,
-    zapping_amount: vector<u64>,
-    stakelisted_amount: vector<u64>,
-    stakelisted_metadata: vector<Object<Metadata>>,
-) {
-    let batch_length = vector::length(&stage);
-    assert!(vector::length(&lp_metadata) == batch_length, error::invalid_argument(EINVALID_BATCH_ARGUMENT));
-    assert!(vector::length(&min_liquidity) == batch_length, error::invalid_argument(EINVALID_BATCH_ARGUMENT));
-    assert!(vector::length(&validator) == batch_length, error::invalid_argument(EINVALID_BATCH_ARGUMENT));
-    assert!(vector::length(&zapping_amount) == batch_length, error::invalid_argument(EINVALID_BATCH_ARGUMENT));
-    assert!(vector::length(&stakelisted_amount) == batch_length, error::invalid_argument(EINVALID_BATCH_ARGUMENT));
-    assert!(vector::length(&stakelisted_metadata) == batch_length, error::invalid_argument(EINVALID_BATCH_ARGUMENT));
-
-    vector::enumerate_ref(&stage, |i, s| {
-        zapping(
-            account,
-            bridge_id,
-            *vector::borrow(&lp_metadata, i),
-            *vector::borrow(&min_liquidity, i),
-            *vector::borrow(&validator, i),
-            *s,
-            *vector::borrow(&zapping_amount, i),
-            *vector::borrow(&stakelisted_amount, i),
-            *vector::borrow(&stakelisted_metadata, i),
-        );
-    });
-}
-
- - - -
- - - -## Function `update_operator_commission` - - - -
public entry fun update_operator_commission(operator: &signer, bridge_id: u64, commission_rate: decimal256::Decimal256)
-
- - - -
-Implementation - - -
public entry fun update_operator_commission(
-    operator: &signer,
-    bridge_id: u64,
-    commission_rate: Decimal256
-) acquires ModuleStore {
-    let module_store = borrow_global<ModuleStore>(@initia_std);
-    vip_operator::update_operator_commission(operator, bridge_id, module_store.stage, commission_rate);
-}
-
- - - -
- - - -## Function `get_snapshot` - - - -
#[view]
-public fun get_snapshot(bridge_id: u64, stage: u64): vip::SnapshotResponse
-
- - - -
-Implementation - - -
public fun get_snapshot(bridge_id: u64, stage: u64): SnapshotResponse acquires ModuleStore {
-    let module_store = borrow_global<ModuleStore>(@initia_std);
-
-    assert!(table::contains(&module_store.stage_data, table_key::encode_u64(stage)), error::not_found(ESTAGE_DATA_NOT_FOUND));
-    let snapshots = table::borrow(&module_store.stage_data, table_key::encode_u64(stage));
-    assert!(table::contains(&snapshots.snapshots, table_key::encode_u64(bridge_id)), error::not_found(ESNAPSHOT_NOT_EXISTS));
-    let snapshot = table::borrow(&snapshots.snapshots, table_key::encode_u64(bridge_id));
-
-    SnapshotResponse {
-        merkle_root: snapshot.merkle_root,
-        total_l2_score: snapshot.total_l2_score,
-    }
-}
-
- - - -
- - - -## Function `get_expected_reward` - - - -
#[view]
-public fun get_expected_reward(bridge_id: u64, fund_reward_amount: u64): u64
-
- - - -
-Implementation - - -
public fun get_expected_reward(bridge_id: u64, fund_reward_amount: u64): u64 acquires ModuleStore {
-    let module_store = borrow_global<ModuleStore>(@initia_std);
-    let balance_shares = simple_map::create<u64, u64>();
-    let weight_shares = simple_map::create<u64, u64>();
-
-    let total_balance = calculate_balance_share(module_store, &mut balance_shares);
-    let total_weight = calculate_weight_share(module_store, &mut weight_shares);
-
-    assert!(fund_reward_amount > 0, error::invalid_argument(EINVALID_TOTAL_REWARD));
-    assert!(total_balance > 0, error::invalid_state(EINVALID_TOTAL_SHARE));
-    assert!(total_weight > 0, error::invalid_state(EINVALID_TOTAL_SHARE));
-
-    let weight_ratio = decimal256::sub(&decimal256::one(), &module_store.pool_split_ratio);
-    let balance_pool_reward_amount = decimal256::mul_u64(&module_store.pool_split_ratio, fund_reward_amount);
-    let weight_pool_reward_amount = decimal256::mul_u64(&weight_ratio, fund_reward_amount);
-
-    let balance_split_amount = split_reward_with_share_internal(&balance_shares, bridge_id, total_balance, balance_pool_reward_amount);
-    let weight_split_amount = split_reward_with_share_internal(&weight_shares, bridge_id, total_weight, weight_pool_reward_amount);
-
-    balance_split_amount + weight_split_amount
-}
-
- - - -
- - - -## Function `get_stage_data` - - - -
#[view]
-public fun get_stage_data(stage: u64): vip::StageDataResponse
-
- - - -
-Implementation - - -
public fun get_stage_data(stage: u64): StageDataResponse acquires ModuleStore {
-    let module_store = borrow_global<ModuleStore>(@initia_std);
-    let stage_data = table::borrow(&module_store.stage_data, table_key::encode_u64(stage));
-
-    StageDataResponse {
-        pool_split_ratio: stage_data.pool_split_ratio,
-        total_operator_funded_reward: stage_data.total_operator_funded_reward,
-        total_user_funded_reward: stage_data.total_user_funded_reward,
-        user_vesting_period: stage_data.user_vesting_period,
-        operator_vesting_period: stage_data.operator_vesting_period,
-        user_vesting_release_time: stage_data.user_vesting_release_time,
-        operator_vesting_release_time: stage_data.operator_vesting_release_time,
-        proportion: stage_data.proportion,
-    }
-}
-
- - - -
- - - -## Function `get_bridge_info` - - - -
#[view]
-public fun get_bridge_info(bridge_id: u64): vip::BridgeResponse
-
- - - -
-Implementation - - -
public fun get_bridge_info(bridge_id: u64): BridgeResponse acquires ModuleStore {
-    let module_store = borrow_global<ModuleStore>(@initia_std);
-    let bridge = load_bridge(&module_store.bridges, bridge_id);
-
-    BridgeResponse {
-        bridge_addr: bridge.bridge_addr,
-        operator_addr: bridge.operator_addr,
-        vip_weight: bridge.vip_weight,
-        user_reward_store_addr: bridge.user_reward_store_addr,
-        operator_reward_store_addr: bridge.operator_reward_store_addr,
-    }
-}
-
- - - -
- - - -## Function `get_next_stage` - - - -
#[view]
-public fun get_next_stage(bridge_id: u64): u64
-
- - - -
-Implementation - - -
public fun get_next_stage(bridge_id: u64): u64 acquires ModuleStore {
-    let module_store = borrow_global<ModuleStore>(@initia_std);
-
-    let iter = table::iter(&module_store.stage_data, option::none(), option::none(), 2);
-    loop {
-        if (!table::prepare<vector<u8>, StageData>(&mut iter)) {
-            break
-        };
-
-        let (key, value) = table::next<vector<u8>, StageData>(&mut iter);
-        if (table::contains(&value.snapshots, table_key::encode_u64(bridge_id))) {
-            return table_key::decode_u64(key) + 1
-        };
-    };
-
-    module_store.stage
-}
-
- - - -
- - - -## Function `get_module_store` - - - -
#[view]
-public fun get_module_store(): vip::ModuleResponse
-
- - - -
-Implementation - - -
public fun get_module_store(): ModuleResponse acquires ModuleStore {
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-
-    ModuleResponse {
-        stage: module_store.stage,
-        agent: module_store.agent,
-        proportion: module_store.proportion,
-        pool_split_ratio: module_store.pool_split_ratio,
-        user_vesting_period: module_store.user_vesting_period,
-        operator_vesting_period: module_store.operator_vesting_period,
-        minimum_tvl: module_store.minimum_tvl,
-        maximum_tvl: module_store.maximum_tvl,
-    }
-}
-
- - - -
- - - -## Function `batch_simulate_user_claim_reward` - - - -
#[view]
-public fun batch_simulate_user_claim_reward(initial_reward: vector<u64>, minimum_score: vector<u64>, vesting_period: vector<u64>, l2_scores: vector<vector<u64>>): (vector<u64>, vector<u64>)
-
- - - -
-Implementation - - -
public fun batch_simulate_user_claim_reward(
-    initial_reward: vector<u64>,
-    minimum_score: vector<u64>,
-    vesting_period: vector<u64>,
-    l2_scores: vector<vector<u64>>
-): (vector<u64>, vector<u64>) {
-    let batch_length = vector::length(&initial_reward);
-    assert!(vector::length(&minimum_score) == batch_length, error::invalid_argument(EINVALID_BATCH_ARGUMENT));
-    assert!(vector::length(&vesting_period) == batch_length, error::invalid_argument(EINVALID_BATCH_ARGUMENT));
-    assert!(vector::length(&l2_scores) == batch_length, error::invalid_argument(EINVALID_BATCH_ARGUMENT));
-    assert!(batch_length > 0, error::invalid_argument(EINVALID_BATCH_ARGUMENT));
-
-    let claimable_list = vector::empty<u64>();
-    let remaining_list = vector::empty<u64>();
-    vector::enumerate_ref(&initial_reward, |i, reward| {
-        let (claimed_reward, remaining_reward) = simulate_user_claim_reward(
-            *reward,
-            *vector::borrow(&minimum_score, i),
-            *vector::borrow(&vesting_period, i),
-            *vector::borrow(&l2_scores, i),
-        );
-        vector::push_back(&mut claimable_list, claimed_reward);
-        vector::push_back(&mut remaining_list, remaining_reward);
-    });
-
-    (claimable_list, remaining_list)
-}
-
- - - -
- - - -## Function `simulate_user_claim_reward` - - - -
#[view]
-public fun simulate_user_claim_reward(initial_reward: u64, minimum_score: u64, vesting_period: u64, l2_scores: vector<u64>): (u64, u64)
-
- - - -
-Implementation - - -
public fun simulate_user_claim_reward(
-    initial_reward: u64,
-    minimum_score: u64,
-    vesting_period: u64,
-    l2_scores: vector<u64>
-): (u64, u64) {
-    let total_claimed_reward = 0;
-    let remaining_reward = initial_reward;
-    vector::enumerate_ref(&l2_scores, |_i, l2_score| {
-        let score_ratio = if (*l2_score >= minimum_score) {
-            decimal256::one()
-        } else {
-            decimal256::from_ratio_u64(*l2_score, minimum_score)
-        };
-
-        let max_ratio = decimal256::div_u64(&decimal256::one(), vesting_period);
-        let vest_ratio = decimal256::mul(&max_ratio, &score_ratio);
-        let vest_amount = decimal256::mul_u64(&vest_ratio, initial_reward);
-
-        if (vest_amount > remaining_reward) {
-            vest_amount = remaining_reward;
-        };
-        remaining_reward = remaining_reward - vest_amount;
-        total_claimed_reward = total_claimed_reward + vest_amount;
-    });
-    (total_claimed_reward, remaining_reward)
-}
-
- - - -
diff --git a/initia_stdlib/doc/zapping.md b/initia_stdlib/doc/zapping.md deleted file mode 100644 index 1256626..0000000 --- a/initia_stdlib/doc/zapping.md +++ /dev/null @@ -1,1526 +0,0 @@ - - - -# Module `0x1::vip_zapping` - - - -- [Resource `ModuleStore`](#0x1_vip_zapping_ModuleStore) -- [Struct `Zapping`](#0x1_vip_zapping_Zapping) -- [Struct `DelegationInfo`](#0x1_vip_zapping_DelegationInfo) -- [Resource `LSStore`](#0x1_vip_zapping_LSStore) -- [Struct `ZappingResponse`](#0x1_vip_zapping_ZappingResponse) -- [Struct `LSEntryResponse`](#0x1_vip_zapping_LSEntryResponse) -- [Struct `LockEvent`](#0x1_vip_zapping_LockEvent) -- [Struct `ZappingClaimEvent`](#0x1_vip_zapping_ZappingClaimEvent) -- [Struct `RewardClaimEvent`](#0x1_vip_zapping_RewardClaimEvent) -- [Struct `DepositEvent`](#0x1_vip_zapping_DepositEvent) -- [Struct `WithdrawEvent`](#0x1_vip_zapping_WithdrawEvent) -- [Struct `ZappingEvent`](#0x1_vip_zapping_ZappingEvent) -- [Constants](#@Constants_0) -- [Function `check_chain_permission`](#0x1_vip_zapping_check_chain_permission) -- [Function `init_module`](#0x1_vip_zapping_init_module) -- [Function `batch_claim_zapping_script`](#0x1_vip_zapping_batch_claim_zapping_script) -- [Function `batch_claim_reward_script`](#0x1_vip_zapping_batch_claim_reward_script) -- [Function `claim_zapping_script`](#0x1_vip_zapping_claim_zapping_script) -- [Function `claim_reward_script`](#0x1_vip_zapping_claim_reward_script) -- [Function `update_lock_period_script`](#0x1_vip_zapping_update_lock_period_script) -- [Function `zapping`](#0x1_vip_zapping_zapping) -- [Function `register`](#0x1_vip_zapping_register) -- [Function `lock_stake`](#0x1_vip_zapping_lock_stake) -- [Function `provide_lock_stake`](#0x1_vip_zapping_provide_lock_stake) -- [Function `create_lock_stake_entry`](#0x1_vip_zapping_create_lock_stake_entry) -- [Function `deposit_lock_stake_entry`](#0x1_vip_zapping_deposit_lock_stake_entry) -- [Function `withdraw_zapping`](#0x1_vip_zapping_withdraw_zapping) -- [Function `claim`](#0x1_vip_zapping_claim) -- [Function `delegation_res_to_delegation_info`](#0x1_vip_zapping_delegation_res_to_delegation_info) -- [Function `get_zapping`](#0x1_vip_zapping_get_zapping) -- [Function `get_delegation_info`](#0x1_vip_zapping_get_delegation_info) - - -
use 0x1::block;
-use 0x1::coin;
-use 0x1::dex;
-use 0x1::error;
-use 0x1::event;
-use 0x1::fungible_asset;
-use 0x1::object;
-use 0x1::option;
-use 0x1::primary_fungible_store;
-use 0x1::signer;
-use 0x1::simple_map;
-use 0x1::staking;
-use 0x1::string;
-use 0x1::table;
-
- - - - - -## Resource `ModuleStore` - - - -
struct ModuleStore has key
-
- - - -
-Fields - - -
-
-extend_ref: object::ExtendRef -
-
- -
-
-lock_period: u64 -
-
- -
-
-zappings: table::Table<u64, vip_zapping::Zapping> -
-
- -
-
- - -
- - - -## Struct `Zapping` - - - -
struct Zapping has store
-
- - - -
-Fields - - -
-
-bridge_id: u64 -
-
- -
-
-zapper: address -
-
- -
-
-validator: string::String -
-
- -
-
-stage: u64 -
-
- -
-
-lock_period: u64 -
-
- -
-
-release_time: u64 -
-
- -
-
-esinit_metadata: object::Object<fungible_asset::Metadata> -
-
- -
-
-stakelisted_metadata: object::Object<fungible_asset::Metadata> -
-
- -
-
-delegation: staking::Delegation -
-
- -
-
-share: u64 -
-
- -
-
- - -
- - - -## Struct `DelegationInfo` - - - -
struct DelegationInfo has drop, store
-
- - - -
-Fields - - -
-
-validator: string::String -
-
- -
-
-share: u64 -
-
- -
-
-unclaimed_reward: u64 -
-
- -
-
- - -
- - - -## Resource `LSStore` - - - -
struct LSStore has key
-
- - - -
-Fields - - -
-
-entries: simple_map::SimpleMap<u64, bool> -
-
- -
-
- - -
- - - -## Struct `ZappingResponse` - - - -
struct ZappingResponse has drop
-
- - - -
-Fields - - -
-
-bridge_id: u64 -
-
- -
-
-zapper: address -
-
- -
-
-validator: string::String -
-
- -
-
-stage: u64 -
-
- -
-
-lock_period: u64 -
-
- -
-
-release_time: u64 -
-
- -
-
-esinit_metadata: object::Object<fungible_asset::Metadata> -
-
- -
-
-stakelisted_metadata: object::Object<fungible_asset::Metadata> -
-
- -
-
-delegation: staking::DelegationResponse -
-
- -
-
-share: u64 -
-
- -
-
- - -
- - - -## Struct `LSEntryResponse` - - - -
struct LSEntryResponse has drop
-
- - - -
-Fields - - -
-
-delegation: staking::DelegationResponse -
-
- -
-
-release_time: u64 -
-
- -
-
-share: u64 -
-
- -
-
- - -
- - - -## Struct `LockEvent` - - - -
#[event]
-struct LockEvent has drop, store
-
- - - -
-Fields - - -
-
-coin_metadata: address -
-
- -
-
-bond_amount: u64 -
-
- -
-
-release_time: u64 -
-
- -
-
-share: u64 -
-
- -
-
- - -
- - - -## Struct `ZappingClaimEvent` - - - -
#[event]
-struct ZappingClaimEvent has drop, store
-
- - - -
-Fields - - -
-
-zid: u64 -
-
- -
-
-coin_metadata: address -
-
- -
-
-reward_amount: u64 -
-
- -
-
-delegation_reward_amount: u64 -
-
- -
-
-share: u64 -
-
- -
-
- - -
- - - -## Struct `RewardClaimEvent` - - - -
#[event]
-struct RewardClaimEvent has drop, store
-
- - - -
-Fields - - -
-
-zid: u64 -
-
- -
-
-coin_metadata: address -
-
- -
-
-reward_amount: u64 -
-
- -
-
- - -
- - - -## Struct `DepositEvent` - - - -
#[event]
-struct DepositEvent has drop, store
-
- - - -
-Fields - - -
-
-zid: u64 -
-
- -
-
-addr: address -
-
- -
-
-delegation: vip_zapping::DelegationInfo -
-
- -
-
-release_time: u64 -
-
- -
-
-share: u64 -
-
- -
-
- - -
- - - -## Struct `WithdrawEvent` - - - -
#[event]
-struct WithdrawEvent has drop, store
-
- - - -
-Fields - - -
-
-zid: u64 -
-
- -
-
-addr: address -
-
- -
-
-delegation: vip_zapping::DelegationInfo -
-
- -
-
-release_time: u64 -
-
- -
-
-share: u64 -
-
- -
-
- - -
- - - -## Struct `ZappingEvent` - - - -
#[event]
-struct ZappingEvent has drop, store
-
- - - -
-Fields - - -
-
-zid: u64 -
-
- -
-
-account: address -
-
- -
-
-bridge_id: u64 -
-
- -
-
-stage: u64 -
-
- -
-
-lp_metadata: object::Object<fungible_asset::Metadata> -
-
- -
-
-validator: string::String -
-
- -
-
-zapping_amount: u64 -
-
- -
-
-stakelisted_amount: u64 -
-
- -
-
-stakelisted_metadata: object::Object<fungible_asset::Metadata> -
-
- -
-
-release_time: u64 -
-
- -
-
- - -
- - - -## Constants - - - - - - -
const EUNAUTHORIZED: u64 = 5;
-
- - - - - - - -
const DEFAULT_LOCK_PERIOD: u64 = 15724800;
-
- - - - - - - -
const EINVALID_ZAPPING_AMOUNT: u64 = 8;
-
- - - - - - - -
const ELOCK_STAKING_END: u64 = 1;
-
- - - - - - - -
const ELOCK_STAKING_IN_PROGRESS: u64 = 2;
-
- - - - - - - -
const ELS_STORE_ALREADY_EXISTS: u64 = 4;
-
- - - - - - - -
const ELS_STORE_NOT_FOUND: u64 = 3;
-
- - - - - - - -
const EZAPPING_ALREADY_EXIST: u64 = 7;
-
- - - - - - - -
const EZAPPING_NOT_EXIST: u64 = 6;
-
- - - - - -## Function `check_chain_permission` - - - -
fun check_chain_permission(chain: &signer)
-
- - - -
-Implementation - - -
fun check_chain_permission(chain: &signer) {
-    assert!(signer::address_of(chain) == @initia_std, error::permission_denied(EUNAUTHORIZED));
-}
-
- - - -
- - - -## Function `init_module` - - - -
fun init_module(chain: &signer)
-
- - - -
-Implementation - - -
fun init_module(chain: &signer) {
-    let constructor_ref = object::create_object(@initia_std, false);
-    let extend_ref = object::generate_extend_ref(&constructor_ref);
-
-    move_to(chain, ModuleStore {
-        extend_ref,
-        lock_period: DEFAULT_LOCK_PERIOD,
-        zappings: table::new<u64, Zapping>(),
-    });
-}
-
- - - -
- - - -## Function `batch_claim_zapping_script` - - - -
public entry fun batch_claim_zapping_script(account: &signer, zids: vector<u64>)
-
- - - -
-Implementation - - -
public entry fun batch_claim_zapping_script(
-    account: &signer,
-    zids: vector<u64>,
-) acquires ModuleStore, LSStore {
-    vector::enumerate_ref(&zids, |_i, zid| {
-        claim_zapping_script(account, *zid);
-    });
-}
-
- - - -
- - - -## Function `batch_claim_reward_script` - - - -
public entry fun batch_claim_reward_script(account: &signer, zids: vector<u64>)
-
- - - -
-Implementation - - -
public entry fun batch_claim_reward_script(
-    account: &signer,
-    zids: vector<u64>,
-) acquires ModuleStore, LSStore {
-    vector::enumerate_ref(&zids, |_i, zid| {
-        claim_reward_script(account, *zid);
-    });
-}
-
- - - -
- - - -## Function `claim_zapping_script` - - - -
public entry fun claim_zapping_script(account: &signer, zid: u64)
-
- - - -
-Implementation - - -
public entry fun claim_zapping_script(
-    account: &signer,
-    zid: u64,
-) acquires ModuleStore, LSStore {
-    let account_addr = signer::address_of(account);
-    let zapping = withdraw_zapping(account, zid);
-
-    // claim delegation with lock staking rewards
-    let (delegation, reward) = claim(zapping, zid);
-
-    // deposit delegation to user address
-    let d_reward = staking::deposit_delegation(account_addr, delegation);
-
-    // merge delegation rewards with lock staking rewards
-    fungible_asset::merge(&mut reward, d_reward);
-
-    // deposit rewards to account coin store
-    primary_fungible_store::deposit(account_addr, reward);
-}
-
- - - -
- - - -## Function `claim_reward_script` - - - -
public entry fun claim_reward_script(account: &signer, zid: u64)
-
- - - -
-Implementation - - -
public entry fun claim_reward_script(account: &signer, zid: u64) acquires ModuleStore, LSStore {
-    let account_addr = signer::address_of(account);
-
-    assert!(exists<LSStore>(account_addr), error::not_found(ELS_STORE_NOT_FOUND));
-
-    let ls_store = borrow_global_mut<LSStore>(account_addr);
-    assert!(simple_map::contains_key(&ls_store.entries, &zid), error::not_found(EZAPPING_NOT_EXIST));
-
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let zapping = table::borrow_mut(&mut module_store.zappings, zid);
-    let reward = staking::claim_reward(&mut zapping.delegation);
-
-    event::emit<RewardClaimEvent>(
-        RewardClaimEvent {
-            zid,
-            coin_metadata: object::object_address(fungible_asset::asset_metadata(&reward)),
-            reward_amount: fungible_asset::amount(&reward)
-        }
-    );
-
-    coin::deposit(account_addr, reward);
-}
-
- - - -
- - - -## Function `update_lock_period_script` - - - -
public entry fun update_lock_period_script(chain: &signer, lock_period: u64)
-
- - - -
-Implementation - - -
public entry fun update_lock_period_script(
-    chain: &signer,
-    lock_period: u64,
-) acquires ModuleStore {
-    check_chain_permission(chain);
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    module_store.lock_period = lock_period;
-}
-
- - - -
- - - -## Function `zapping` - - - -
public(friend) fun zapping(account: &signer, bridge_id: u64, lp_metadata: object::Object<fungible_asset::Metadata>, min_liquidity: option::Option<u64>, validator: string::String, stage: u64, esinit: fungible_asset::FungibleAsset, stakelisted: fungible_asset::FungibleAsset)
-
- - - -
-Implementation - - -
public(friend) fun zapping(
-    account: &signer,
-    bridge_id: u64,
-    lp_metadata: Object<Metadata>,
-    min_liquidity: Option<u64>,
-    validator: String,
-    stage: u64,
-    esinit: FungibleAsset,
-    stakelisted: FungibleAsset,
-) acquires ModuleStore, LSStore{
-    assert!(fungible_asset::amount(&esinit) > 0 && fungible_asset::amount(&stakelisted) > 0, error::invalid_argument(EINVALID_ZAPPING_AMOUNT));
-
-    let pair = object::convert<Metadata, dex::Config>(lp_metadata);
-    let (_height, timestamp) = block::get_block_info();
-    let module_store = borrow_global<ModuleStore>(@initia_std);
-    let release_time = timestamp + module_store.lock_period;
-    let zapping_amount = fungible_asset::amount(&esinit);
-    let esinit_metadata = fungible_asset::asset_metadata(&esinit);
-    let stakelisted_amount = fungible_asset::amount(&stakelisted);
-    let stakelisted_metadata = fungible_asset::asset_metadata(&stakelisted);
-
-    let (coin_a_metadata, _) = dex::pool_metadata(pair);
-
-    // if pair is reversed, swap coin_a and coin_b
-    let (coin_a, coin_b) = if (coin_a_metadata == esinit_metadata){
-        (esinit, stakelisted)
-    } else {
-        (stakelisted, esinit)
-    };
-
-
-    let zid = provide_lock_stake(
-        account,
-        bridge_id,
-        coin_a,
-        coin_b,
-        pair,
-        min_liquidity,
-        validator,
-        stage,
-        release_time,
-        esinit_metadata,
-        stakelisted_metadata
-    );
-
-    event::emit(
-        ZappingEvent {
-            zid,
-            account: signer::address_of(account),
-            bridge_id,
-            stage,
-            lp_metadata,
-            validator,
-            zapping_amount,
-            stakelisted_amount,
-            stakelisted_metadata,
-            release_time,
-        }
-    );
-}
-
- - - -
- - - -## Function `register` - - - -
fun register(account: &signer)
-
- - - -
-Implementation - - -
fun register(account: &signer) {
-    assert!(!exists<LSStore>(signer::address_of(account)), error::already_exists(ELS_STORE_ALREADY_EXISTS));
-    move_to(account, LSStore{
-        entries: simple_map::create<u64, bool>(),
-    });
-}
-
- - - -
- - - -## Function `lock_stake` - - - -
fun lock_stake(account: &signer, bridge_id: u64, lock_coin: fungible_asset::FungibleAsset, validator: string::String, stage: u64, release_time: u64, esinit_metadata: object::Object<fungible_asset::Metadata>, stakelisted_metadata: object::Object<fungible_asset::Metadata>): u64
-
- - - -
-Implementation - - -
fun lock_stake(
-    account: &signer,
-    bridge_id: u64,
-    lock_coin: FungibleAsset,
-    validator: String,
-    stage: u64,
-    release_time: u64,
-    esinit_metadata: Object<Metadata>,
-    stakelisted_metadata: Object<Metadata>,
-): u64 acquires ModuleStore, LSStore {
-    let account_addr = signer::address_of(account);
-    if (!exists<LSStore>(account_addr)) {
-        register(account);
-    };
-
-    if (!staking::is_account_registered(signer::address_of(account))) {
-        staking::register(account);
-    };
-
-    let (share, zid, delegation_res) = create_lock_stake_entry(
-        bridge_id,
-        account_addr,
-        validator,
-        stage,
-        release_time,
-        lock_coin,
-        esinit_metadata,
-        stakelisted_metadata
-    );
-
-    // deposit lock stake to account store
-    deposit_lock_stake_entry(account_addr, release_time, share, zid, delegation_res);
-
-    zid
-}
-
- - - -
- - - -## Function `provide_lock_stake` - - - -
fun provide_lock_stake(account: &signer, bridge_id: u64, coin_a: fungible_asset::FungibleAsset, coin_b: fungible_asset::FungibleAsset, pair: object::Object<dex::Config>, min_liquidity: option::Option<u64>, validator: string::String, stage: u64, release_time: u64, esinit_metadata: object::Object<fungible_asset::Metadata>, stakelisted_metadata: object::Object<fungible_asset::Metadata>): u64
-
- - - -
-Implementation - - -
fun provide_lock_stake(
-    account: &signer,
-    bridge_id: u64,
-    coin_a: FungibleAsset,
-    coin_b: FungibleAsset,
-    pair: Object<dex::Config>,
-    min_liquidity: Option<u64>,
-    validator: String,
-    stage: u64,
-    release_time: u64,
-    esinit_metadata: Object<Metadata>,
-    stakelisted_metadata: Object<Metadata>,
-): u64 acquires LSStore, ModuleStore {
-    let lp_token = dex::provide_liquidity(
-        pair,
-        coin_a,
-        coin_b,
-        min_liquidity,
-    );
-
-    let zid = lock_stake(
-        account,
-        bridge_id,
-        lp_token,
-        validator,
-        stage,
-        release_time,
-        esinit_metadata,
-        stakelisted_metadata
-    );
-
-    zid
-}
-
- - - -
- - - -## Function `create_lock_stake_entry` - -Execute lock staking and return created LSEntry - - -
fun create_lock_stake_entry(bridge_id: u64, zapper: address, validator: string::String, stage: u64, release_time: u64, lock_coin: fungible_asset::FungibleAsset, esinit_metadata: object::Object<fungible_asset::Metadata>, stakelisted_metadata: object::Object<fungible_asset::Metadata>): (u64, u64, staking::DelegationResponse)
-
- - - -
-Implementation - - -
fun create_lock_stake_entry(
-    bridge_id: u64,
-    zapper: address,
-    validator: String,
-    stage: u64,
-    release_time: u64,
-    lock_coin: FungibleAsset,
-    esinit_metadata: Object<Metadata>,
-    stakelisted_metadata: Object<Metadata>,
-): (u64, u64, DelegationResponse) acquires ModuleStore {
-    let bond_amount = fungible_asset::amount(&lock_coin);
-    let share = bond_amount;
-    let coin_metadata = object::object_address(fungible_asset::asset_metadata(&lock_coin));
-    let delegation = staking::delegate(validator, lock_coin);
-
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let zid = table::length(&module_store.zappings);
-
-    assert!(!table::contains(&module_store.zappings, zid), error::already_exists(EZAPPING_ALREADY_EXIST));
-
-    let (_, block_time) = block::get_block_info();
-    assert!(release_time > block_time, error::unavailable(ELOCK_STAKING_END));
-
-    // create zapping
-    let zapping = Zapping {
-        bridge_id,
-        zapper,
-        validator,
-        stage,
-        lock_period: module_store.lock_period,
-        release_time,
-        esinit_metadata,
-        stakelisted_metadata,
-        delegation,
-        share
-    };
-
-    let delegation_res = staking::get_delegation_response_from_delegation(&zapping.delegation);
-    table::add(&mut module_store.zappings, zid, zapping);
-
-    event::emit(
-        LockEvent {
-            coin_metadata,
-            bond_amount,
-            release_time,
-            share,
-        }
-    );
-
-    (share, zid, delegation_res)
-}
-
- - - -
- - - -## Function `deposit_lock_stake_entry` - - - -
fun deposit_lock_stake_entry(account_addr: address, release_time: u64, share: u64, zid: u64, delegation_res: staking::DelegationResponse)
-
- - - -
-Implementation - - -
fun deposit_lock_stake_entry(account_addr: address, release_time: u64, share: u64, zid: u64, delegation_res: DelegationResponse) acquires LSStore {
-    assert!(exists<LSStore>(account_addr), error::not_found(ELS_STORE_NOT_FOUND));
-
-    let ls_store = borrow_global_mut<LSStore>(account_addr);
-    simple_map::add(&mut ls_store.entries, zid, true);
-
-    event::emit(
-        DepositEvent {
-            zid,
-            addr: account_addr,
-            delegation: delegation_res_to_delegation_info(&delegation_res),
-            release_time,
-            share,
-        }
-    );
-}
-
- - - -
- - - -## Function `withdraw_zapping` - - - -
fun withdraw_zapping(account: &signer, zid: u64): vip_zapping::Zapping
-
- - - -
-Implementation - - -
fun withdraw_zapping(account: &signer, zid: u64): Zapping acquires ModuleStore, LSStore {
-    let account_addr = signer::address_of(account);
-    assert!(exists<LSStore>(account_addr), error::not_found(ELS_STORE_NOT_FOUND));
-
-    let ls_store = borrow_global_mut<LSStore>(account_addr);
-    assert!(simple_map::contains_key(&ls_store.entries, &zid), error::not_found(EZAPPING_NOT_EXIST));
-
-    let module_store = borrow_global_mut<ModuleStore>(@initia_std);
-    let zapping = table::remove(&mut module_store.zappings, zid);
-    simple_map::remove(&mut ls_store.entries, &zid);
-
-    let delegation_res = staking::get_delegation_response_from_delegation(&zapping.delegation);
-
-    event::emit<WithdrawEvent>(
-        WithdrawEvent {
-            zid,
-            addr: account_addr,
-            delegation: delegation_res_to_delegation_info(&delegation_res),
-            release_time: zapping.release_time,
-            share: zapping.share,
-        }
-    );
-
-    zapping
-}
-
- - - -
- - - -## Function `claim` - -Claim lock staking rewards with Delegation - - -
public fun claim(zapping: vip_zapping::Zapping, zid: u64): (staking::Delegation, fungible_asset::FungibleAsset)
-
- - - -
-Implementation - - -
public fun claim(zapping: Zapping, zid: u64): (Delegation, FungibleAsset) {
-    let (_, block_time) = block::get_block_info();
-    assert!(block_time >= zapping.release_time, error::unavailable(ELOCK_STAKING_IN_PROGRESS));
-
-    let reward = staking::claim_reward(&mut zapping.delegation);
-    let Zapping {
-        bridge_id: _,
-        zapper: _,
-        validator: _,
-        stage: _,
-        lock_period: _,
-        release_time: _,
-        esinit_metadata: _,
-        stakelisted_metadata: _,
-        delegation,
-        share,
-    } = zapping;
-
-    let delegation_res = staking::get_delegation_response_from_delegation(&delegation);
-
-    event::emit<ZappingClaimEvent>(
-        ZappingClaimEvent {
-            zid,
-            coin_metadata: object::object_address(fungible_asset::asset_metadata(&reward)),
-            reward_amount: fungible_asset::amount(&reward),
-            delegation_reward_amount: staking::get_unclaimed_reward_from_delegation_response(&delegation_res),
-            share,
-        }
-    );
-
-    (delegation, reward)
-}
-
- - - -
- - - -## Function `delegation_res_to_delegation_info` - - - -
fun delegation_res_to_delegation_info(delegation_res: &staking::DelegationResponse): vip_zapping::DelegationInfo
-
- - - -
-Implementation - - -
fun delegation_res_to_delegation_info(delegation_res: &DelegationResponse): DelegationInfo {
-    DelegationInfo {
-        validator: staking::get_validator_from_delegation_response(delegation_res),
-        unclaimed_reward: staking::get_unclaimed_reward_from_delegation_response(delegation_res),
-        share: staking::get_share_from_delegation_response(delegation_res),
-    }
-}
-
- - - -
- - - -## Function `get_zapping` - - - -
#[view]
-public fun get_zapping(zid: u64): vip_zapping::ZappingResponse
-
- - - -
-Implementation - - -
public fun get_zapping(zid: u64): ZappingResponse acquires ModuleStore {
-    let module_store = borrow_global<ModuleStore>(@initia_std);
-    assert!(table::contains(&module_store.zappings, zid), error::not_found(EZAPPING_NOT_EXIST));
-    let zapping = table::borrow(&module_store.zappings, zid);
-
-    ZappingResponse {
-        bridge_id: zapping.bridge_id,
-        zapper: zapping.zapper,
-        validator: zapping.validator,
-        stage: zapping.stage,
-        lock_period: zapping.lock_period,
-        release_time: zapping.release_time,
-        esinit_metadata: zapping.esinit_metadata,
-        stakelisted_metadata: zapping.stakelisted_metadata,
-        delegation: staking::get_delegation_response_from_delegation(&zapping.delegation),
-        share: zapping.share,
-    }
-}
-
- - - -
- - - -## Function `get_delegation_info` - - - -
#[view]
-public fun get_delegation_info(zid: u64): vip_zapping::DelegationInfo
-
- - - -
-Implementation - - -
public fun get_delegation_info(zid: u64): DelegationInfo acquires ModuleStore {
-    let module_store = borrow_global<ModuleStore>(@initia_std);
-    assert!(table::contains(&module_store.zappings, zid), error::not_found(EZAPPING_NOT_EXIST));
-    let zapping = table::borrow(&module_store.zappings, zid);
-
-    let delegation_res = staking::get_delegation_response_from_delegation(&zapping.delegation);
-    let delegation_info = delegation_res_to_delegation_info(&delegation_res);
-
-    delegation_info
-}
-
- - - -
diff --git a/initia_stdlib/sources/account.move b/initia_stdlib/sources/account.move index 0c66d28..17c040f 100644 --- a/initia_stdlib/sources/account.move +++ b/initia_stdlib/sources/account.move @@ -24,7 +24,7 @@ module initia_std::account { account_number: u64, sequence_number: u64, account_type: u8, - is_blocked: bool, + is_blocked: bool } public entry fun create_account_script(addr: address) { @@ -35,7 +35,7 @@ module initia_std::account { let (found, _, _, _, _) = account_info(addr); assert!( !found, - error::already_exists(EACCOUNT_ALREADY_EXISTS), + error::already_exists(EACCOUNT_ALREADY_EXISTS) ); request_create_account(addr, 0, ACCOUNT_TYPE_BASE) @@ -46,15 +46,14 @@ module initia_std::account { public(friend) fun create_table_account(addr: address): u64 { let (found, account_number, sequence, account_type, _) = account_info(addr); assert!( - !found - || (account_type == ACCOUNT_TYPE_BASE && sequence == 0), - error::already_exists(EACCOUNT_ALREADY_EXISTS), + !found || (account_type == ACCOUNT_TYPE_BASE && sequence == 0), + error::already_exists(EACCOUNT_ALREADY_EXISTS) ); request_create_account( addr, account_number, - ACCOUNT_TYPE_TABLE, + ACCOUNT_TYPE_TABLE ) } @@ -68,7 +67,7 @@ module initia_std::account { request_create_account( addr, account_number, - ACCOUNT_TYPE_OBJECT, + ACCOUNT_TYPE_OBJECT ) } else { // When an Object is deleted, the ObjectAccount in CosmosSDK is designed @@ -180,8 +179,11 @@ module initia_std::account { info.sequence_number } - native fun request_create_account(addr: address, account_number: u64, account_type: u8): u64; - native public fun account_info(addr: address): ( + native fun request_create_account( + addr: address, account_number: u64, account_type: u8 + ): u64; + native public fun account_info(addr: address): + ( bool /* found */, u64 /* account_number */, u64 /* sequence_number */, @@ -232,7 +234,7 @@ module initia_std::account { assert!(bob_account_num == get_account_number(bob), 7); assert!( carol_account_num == get_account_number(carol), - 7, + 7 ); // object account @@ -244,7 +246,7 @@ module initia_std::account { let dan_object_account_num = create_object_account(dan); assert!( dan_object_account_num == get_account_number(dan), - 9, + 9 ); assert!(is_object_account(dan), 10); assert!(exists_at(dan), 11); @@ -258,7 +260,7 @@ module initia_std::account { let erin_table_account_num = create_table_account(erin); assert!( erin_table_account_num == get_account_number(erin), - 13, + 13 ); assert!(is_table_account(erin), 14); assert!(exists_at(erin), 15); @@ -276,11 +278,11 @@ module initia_std::account { ); assert!( bob == @0x0000000000000000000000000000000000000000000000000000000000000b0b, - 0, + 0 ); assert!( carol == @0x00000000000000000000000000000000000000000000000000000000000ca501, - 1, + 1 ); } @@ -291,17 +293,24 @@ module initia_std::account { assert!(vector::length(&authentication_key) == 32, 0); } - #[test(new_address = @0x41, new_address2 = @0x42, new_address3 = @0x43, new_address4 = @0x44)] + #[ + test( + new_address = @0x41, + new_address2 = @0x42, + new_address3 = @0x43, + new_address4 = @0x44 + ) + ] public fun test_create_table_account_and_object_account( new_address: address, new_address2: address, new_address3: address, - new_address4: address, + new_address4: address ) { let table_account_num = create_table_account(new_address); assert!( table_account_num == get_account_number(new_address), - 0, + 0 ); assert!(is_table_account(new_address), 1); assert!(exists_at(new_address), 2); @@ -312,12 +321,12 @@ module initia_std::account { 100, 0, ACCOUNT_TYPE_BASE, - false, + false ); let table_account_num = create_table_account(new_address2); assert!( table_account_num == get_account_number(new_address2), - 0, + 0 ); assert!(table_account_num == 100, 0); assert!(is_table_account(new_address2), 1); @@ -327,7 +336,7 @@ module initia_std::account { let object_account_num = create_object_account(new_address3); assert!( object_account_num == get_account_number(new_address3), - 3, + 3 ); assert!(is_object_account(new_address3), 4); assert!(exists_at(new_address3), 5); @@ -338,12 +347,12 @@ module initia_std::account { 200, 0, ACCOUNT_TYPE_BASE, - false, + false ); let object_account_num = create_object_account(new_address4); assert!( object_account_num == get_account_number(new_address4), - 0, + 0 ); assert!(object_account_num == 200, 0); assert!(is_object_account(new_address4), 1); @@ -360,7 +369,7 @@ module initia_std::account { 200, 0, ACCOUNT_TYPE_BASE, - true, + true ); assert!(is_blocked(new_address), 1); @@ -369,7 +378,7 @@ module initia_std::account { 100, 0, ACCOUNT_TYPE_BASE, - false, + false ); assert!(!is_blocked(new_address2), 2); } @@ -398,4 +407,11 @@ module initia_std::account { create_table_account(new_address); create_object_account(new_address); } + + // functions for compatibility with the aptos + + #[test_only] + public fun create_account_for_test(new_address: address): signer { + create_signer_for_test(new_address) + } } diff --git a/initia_stdlib/sources/address.move b/initia_stdlib/sources/address.move index 88c2899..83d14e7 100644 --- a/initia_stdlib/sources/address.move +++ b/initia_stdlib/sources/address.move @@ -6,11 +6,11 @@ module initia_std::address { use initia_std::json; struct FromSdkRequest has copy, drop { - sdk_addr: String, + sdk_addr: String } struct FromSdkResponse has copy, drop { - vm_addr: address, + vm_addr: address } public fun from_sdk(sdk_addr: String): address { @@ -18,19 +18,19 @@ module initia_std::address { json::unmarshal( query::query_custom( b"from_sdk_address", - json::marshal(&FromSdkRequest { sdk_addr: sdk_addr, }), - ), + json::marshal(&FromSdkRequest { sdk_addr: sdk_addr }) + ) ); res.vm_addr } struct ToSdkRequest has copy, drop { - vm_addr: address, + vm_addr: address } struct ToSdkResponse has copy, drop { - sdk_addr: String, + sdk_addr: String } public fun to_sdk(vm_addr: address): String { @@ -38,8 +38,8 @@ module initia_std::address { json::unmarshal( query::query_custom( b"to_sdk_address", - json::marshal(&ToSdkRequest { vm_addr: vm_addr, }), - ), + json::marshal(&ToSdkRequest { vm_addr: vm_addr }) + ) ); res.sdk_addr diff --git a/initia_stdlib/sources/any.move b/initia_stdlib/sources/any.move index a5eae0f..43669bf 100644 --- a/initia_stdlib/sources/any.move +++ b/initia_stdlib/sources/any.move @@ -27,14 +27,17 @@ module initia_std::any { /// Pack a value into the `Any` representation. Because Any can be stored and dropped, this is /// also required from `T`. public fun pack(x: T): Any { - Any { type_name: type_info::type_name(), data: to_bytes(&x) } + Any { + type_name: type_info::type_name(), + data: to_bytes(&x) + } } /// Unpack a value from the `Any` representation. This aborts if the value has not the expected type `T`. public fun unpack(x: Any): T { assert!( type_info::type_name() == x.type_name, - error::invalid_argument(ETYPE_MISMATCH), + error::invalid_argument(ETYPE_MISMATCH) ); from_bytes(x.data) } diff --git a/initia_stdlib/sources/bigdecimal.move b/initia_stdlib/sources/bigdecimal.move new file mode 100644 index 0000000..eac9d72 --- /dev/null +++ b/initia_stdlib/sources/bigdecimal.move @@ -0,0 +1,614 @@ +module initia_std::bigdecimal { + use initia_std::error; + use initia_std::biguint::{Self, BigUint}; + + // Const values + const DECIMAL_FRACTIONAL: u64 = 1000000000000000000; + const FRACTIONAL_LENGTH: u64 = 18; + + // Error codes + const NEGATIVE_RESULT: u64 = 100; + const EDIVISION_BY_ZERO: u64 = 101; + + struct BigDecimal has copy, drop, store { + scaled: BigUint + } + + fun f(): BigUint { + biguint::from_u64(DECIMAL_FRACTIONAL) + } + + fun hf(): BigUint { + biguint::from_u64(DECIMAL_FRACTIONAL / 2) + } + + fun f_1(): BigUint { + biguint::from_u64(DECIMAL_FRACTIONAL - 1) + } + + // creation + + /// Create a BigDecimal from a u64 value by multiplying it by the fractional part. + public fun from_u64(value: u64): BigDecimal { + BigDecimal { + scaled: biguint::mul(biguint::from_u64(value), f()) + } + } + + /// Create a BigDecimal from a u128 value by multiplying it by the fractional part. + public fun from_u128(value: u128): BigDecimal { + BigDecimal { + scaled: biguint::mul(biguint::from_u128(value), f()) + } + } + + /// Create a BigDecimal from a u256 value by multiplying it by the fractional part. + public fun from_u256(value: u256): BigDecimal { + BigDecimal { + scaled: biguint::mul(biguint::from_u256(value), f()) + } + } + + /// Create a BigDecimal from a BigUint value by multiplying it by the fractional part. + public fun new(value: BigUint): BigDecimal { + BigDecimal { + scaled: biguint::mul(value, f()) + } + } + + /// Create a BigDecimal from a scaled BigUint value. + public fun from_scaled(scaled: BigUint): BigDecimal { + BigDecimal { scaled: scaled } + } + + /// Get the scaled value of a BigDecimal. + public fun get_scaled(num: BigDecimal): BigUint { + num.scaled + } + + /// Create a BigDecimal from a scaled BigUint le_bytes value. + public fun from_scaled_le_bytes(le_bytes: vector): BigDecimal { + BigDecimal { scaled: biguint::from_le_bytes(le_bytes) } + } + + public fun get_scaled_le_bytes(num: BigDecimal): vector { + biguint::to_le_bytes(num.scaled) + } + + public fun from_ratio(numerator: BigUint, denominator: BigUint): BigDecimal { + assert!( + !biguint::is_zero(denominator), error::invalid_argument(EDIVISION_BY_ZERO) + ); + + let numerator = biguint::mul(numerator, f()); + BigDecimal { scaled: biguint::div(numerator, denominator) } + } + + public fun from_ratio_u64(numerator: u64, denominator: u64): BigDecimal { + assert!(denominator != 0, error::invalid_argument(EDIVISION_BY_ZERO)); + + let numerator = biguint::from_u128( + (numerator as u128) * (DECIMAL_FRACTIONAL as u128) + ); + let denominator = biguint::from_u64(denominator); + + BigDecimal { scaled: biguint::div(numerator, denominator) } + } + + public fun from_ratio_u128(numerator: u128, denominator: u128): BigDecimal { + assert!(denominator != 0, error::invalid_argument(EDIVISION_BY_ZERO)); + + let numerator = biguint::from_u256( + (numerator as u256) * (DECIMAL_FRACTIONAL as u256) + ); + let denominator = biguint::from_u128(denominator); + + BigDecimal { scaled: biguint::div(numerator, denominator) } + } + + public fun from_ratio_u256(numerator: u256, denominator: u256): BigDecimal { + assert!(denominator != 0, error::invalid_argument(EDIVISION_BY_ZERO)); + + let numerator = biguint::mul(biguint::from_u256(numerator), f()); + let denominator = biguint::from_u256(denominator); + + BigDecimal { scaled: biguint::div(numerator, denominator) } + } + + public fun rev(num: BigDecimal): BigDecimal { + let fractional = f(); + BigDecimal { + scaled: biguint::div(biguint::mul(fractional, fractional), num.scaled) + } + } + + public fun one(): BigDecimal { + BigDecimal { scaled: f() } + } + + public fun zero(): BigDecimal { + BigDecimal { scaled: biguint::zero() } + } + + // cmp + + public fun eq(num1: BigDecimal, num2: BigDecimal): bool { + biguint::eq(num1.scaled, num2.scaled) + } + + public fun lt(num1: BigDecimal, num2: BigDecimal): bool { + biguint::lt(num1.scaled, num2.scaled) + } + + public fun le(num1: BigDecimal, num2: BigDecimal): bool { + biguint::le(num1.scaled, num2.scaled) + } + + public fun gt(num1: BigDecimal, num2: BigDecimal): bool { + biguint::gt(num1.scaled, num2.scaled) + } + + public fun ge(num1: BigDecimal, num2: BigDecimal): bool { + biguint::ge(num1.scaled, num2.scaled) + } + + public fun is_zero(num: BigDecimal): bool { + biguint::is_zero(num.scaled) + } + + public fun is_one(num: BigDecimal): bool { + biguint::eq(num.scaled, f()) + } + + // arithmetic + + public fun add(num1: BigDecimal, num2: BigDecimal): BigDecimal { + BigDecimal { scaled: biguint::add(num1.scaled, num2.scaled) } + } + + public fun add_by_u64(num1: BigDecimal, num2: u64): BigDecimal { + BigDecimal { + scaled: biguint::add(num1.scaled, from_u64(num2).scaled) + } + } + + public fun add_by_u128(num1: BigDecimal, num2: u128): BigDecimal { + BigDecimal { + scaled: biguint::add(num1.scaled, from_u128(num2).scaled) + } + } + + public fun add_by_u256(num1: BigDecimal, num2: u256): BigDecimal { + BigDecimal { + scaled: biguint::add(num1.scaled, from_u256(num2).scaled) + } + } + + public fun sub(num1: BigDecimal, num2: BigDecimal): BigDecimal { + assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT)); + BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) } + } + + public fun sub_by_u64(num1: BigDecimal, num2: u64): BigDecimal { + let num2 = from_u64(num2); + assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT)); + BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) } + } + + public fun sub_by_u128(num1: BigDecimal, num2: u128): BigDecimal { + let num2 = from_u128(num2); + assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT)); + BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) } + } + + public fun sub_by_u256(num1: BigDecimal, num2: u256): BigDecimal { + let num2 = from_u256(num2); + assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT)); + BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) } + } + + public fun mul(num1: BigDecimal, num2: BigDecimal): BigDecimal { + BigDecimal { + scaled: biguint::div(biguint::mul(num1.scaled, num2.scaled), f()) + } + } + + public fun mul_truncate(num1: BigDecimal, num2: BigDecimal): BigUint { + truncate(mul(num1, num2)) + } + + public fun mul_ceil(num1: BigDecimal, num2: BigDecimal): BigUint { + ceil(mul(num1, num2)) + } + + public fun mul_by_u64(num1: BigDecimal, num2: u64): BigDecimal { + BigDecimal { scaled: biguint::mul_by_u64(num1.scaled, num2) } + } + + public fun mul_by_u64_truncate(num1: BigDecimal, num2: u64): u64 { + truncate_u64(mul_by_u64(num1, num2)) + } + + public fun mul_by_u64_ceil(num1: BigDecimal, num2: u64): u64 { + ceil_u64(mul_by_u64(num1, num2)) + } + + public fun mul_by_u128(num1: BigDecimal, num2: u128): BigDecimal { + BigDecimal { scaled: biguint::mul_by_u128(num1.scaled, num2) } + } + + public fun mul_by_u128_truncate(num1: BigDecimal, num2: u128): u128 { + truncate_u128(mul_by_u128(num1, num2)) + } + + public fun mul_by_u128_ceil(num1: BigDecimal, num2: u128): u128 { + ceil_u128(mul_by_u128(num1, num2)) + } + + public fun mul_by_u256(num1: BigDecimal, num2: u256): BigDecimal { + BigDecimal { scaled: biguint::mul_by_u256(num1.scaled, num2) } + } + + public fun mul_by_u256_truncate(num1: BigDecimal, num2: u256): u256 { + truncate_u256(mul_by_u256(num1, num2)) + } + + public fun mul_by_u256_ceil(num1: BigDecimal, num2: u256): u256 { + ceil_u256(mul_by_u256(num1, num2)) + } + + public fun div(num1: BigDecimal, num2: BigDecimal): BigDecimal { + assert!( + !biguint::is_zero(num2.scaled), error::invalid_argument(EDIVISION_BY_ZERO) + ); + + BigDecimal { + scaled: biguint::div(biguint::mul(num1.scaled, f()), num2.scaled) + } + } + + public fun div_by_u64(num1: BigDecimal, num2: u64): BigDecimal { + assert!(num2 != 0, error::invalid_argument(EDIVISION_BY_ZERO)); + + BigDecimal { scaled: biguint::div_by_u64(num1.scaled, num2) } + } + + public fun div_by_u128(num1: BigDecimal, num2: u128): BigDecimal { + assert!(num2 != 0, error::invalid_argument(EDIVISION_BY_ZERO)); + + BigDecimal { scaled: biguint::div_by_u128(num1.scaled, num2) } + } + + public fun div_by_u256(num1: BigDecimal, num2: u256): BigDecimal { + assert!(num2 != 0, error::invalid_argument(EDIVISION_BY_ZERO)); + + BigDecimal { scaled: biguint::div_by_u256(num1.scaled, num2) } + } + + // cast + + public fun truncate(num: BigDecimal): BigUint { + biguint::div(num.scaled, f()) + } + + public fun truncate_u64(num: BigDecimal): u64 { + biguint::to_u64(truncate(num)) + } + + public fun truncate_u128(num: BigDecimal): u128 { + biguint::to_u128(truncate(num)) + } + + public fun truncate_u256(num: BigDecimal): u256 { + biguint::to_u256(truncate(num)) + } + + public fun round_up(num: BigDecimal): BigUint { + biguint::div(biguint::add(num.scaled, hf()), f()) + } + + public fun round_up_u64(num: BigDecimal): u64 { + biguint::to_u64(round_up(num)) + } + + public fun round_up_u128(num: BigDecimal): u128 { + biguint::to_u128(round_up(num)) + } + + public fun round_up_u256(num: BigDecimal): u256 { + biguint::to_u256(round_up(num)) + } + + public fun ceil(num: BigDecimal): BigUint { + biguint::div(biguint::add(num.scaled, f_1()), f()) + } + + public fun ceil_u64(num: BigDecimal): u64 { + biguint::to_u64(ceil(num)) + } + + public fun ceil_u128(num: BigDecimal): u128 { + biguint::to_u128(ceil(num)) + } + + public fun ceil_u256(num: BigDecimal): u256 { + biguint::to_u256(ceil(num)) + } + + // tests + + #[test] + fun test_bigdecimal() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + let num2 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + assert!(eq(num1, num2), 1); + + let num3 = from_ratio(biguint::from_u64(1), biguint::from_u64(3)); + assert!(lt(num3, num1), 2); + assert!(gt(num1, num3), 3); + + let num4 = add(num1, num3); + assert!( + eq(num4, from_ratio(biguint::from_u64(5), biguint::from_u64(6))), + 4 + ); + + let num5 = sub(num1, num2); + assert!(is_zero(num5), 5); + + let num6 = truncate(num1); + assert!(biguint::is_zero(num6), 6); + + let num7 = round_up(num1); + assert!(biguint::is_one(num7), 7); + + let num8 = round_up(num3); + assert!(biguint::is_zero(num8), 8); + + let num9 = ceil(num3); + assert!(biguint::is_one(num9), 9); + + let num10 = add_by_u64(num1, 1); + assert!( + eq(num10, from_ratio(biguint::from_u64(3), biguint::from_u64(2))), + 10 + ); + + let num11 = sub_by_u64(num10, 1); + assert!( + eq(num11, from_ratio(biguint::from_u64(1), biguint::from_u64(2))), + 11 + ); + + let num12 = mul_by_u64(num1, 2); + assert!(eq(num12, from_u64(1)), 12); + + let num13 = div_by_u64(num1, 2); + assert!( + eq(num13, from_ratio(biguint::from_u64(1), biguint::from_u64(4))), + 13 + ); + } + + #[test] + fun test_bigdecimal_u64() { + let num1 = from_ratio_u64(1, 2); + let num2 = from_ratio_u64(1, 2); + assert!(eq(num1, num2), 1); + + let num3 = from_ratio_u64(1, 3); + assert!(lt(num3, num1), 2); + assert!(gt(num1, num3), 3); + + let num4 = add(num1, num3); + assert!(eq(num4, from_ratio_u64(5, 6)), 4); + + let num5 = sub(num1, num2); + assert!(is_zero(num5), 5); + + let num6 = truncate_u64(num1); + assert!(num6 == 0, 7); + + let num7 = round_up_u64(num1); + assert!(num7 == 1, 8); + + let num8 = round_up_u64(num3); + assert!(num8 == 0, 9); + + let num9 = ceil_u64(num3); + assert!(num9 == 1, 10); + + let num10 = add_by_u64(num1, 1); + assert!(eq(num10, from_ratio_u64(3, 2)), 11); + + let num11 = sub_by_u64(num10, 1); + assert!(eq(num11, from_ratio_u64(1, 2)), 12); + + let num12 = mul_by_u64(num1, 2); + assert!(eq(num12, from_u64(1)), 13); + + let num13 = div_by_u64(num1, 2); + assert!(eq(num13, from_ratio_u64(1, 4)), 14); + } + + #[test] + fun test_bigdecimal_u128() { + let num1 = from_ratio_u128(1, 2); + let num2 = from_ratio_u128(1, 2); + assert!(eq(num1, num2), 1); + + let num3 = from_ratio_u128(1, 3); + assert!(lt(num3, num1), 2); + assert!(gt(num1, num3), 3); + + let num4 = add(num1, num3); + assert!(eq(num4, from_ratio_u128(5, 6)), 4); + + let num5 = sub(num1, num2); + assert!(is_zero(num5), 5); + + let num6 = truncate_u128(num1); + assert!(num6 == 0, 7); + + let num7 = round_up_u128(num1); + assert!(num7 == 1, 8); + + let num8 = round_up_u128(num3); + assert!(num8 == 0, 9); + + let num9 = ceil_u128(num3); + assert!(num9 == 1, 10); + + let num10 = add_by_u128(num1, 1); + assert!(eq(num10, from_ratio_u128(3, 2)), 11); + + let num11 = sub_by_u128(num10, 1); + assert!(eq(num11, from_ratio_u128(1, 2)), 12); + + let num12 = mul_by_u128(num1, 2); + assert!(eq(num12, from_u128(1)), 13); + + let num13 = div_by_u128(num1, 2); + assert!(eq(num13, from_ratio_u128(1, 4)), 14); + } + + #[test] + fun test_bigdecimal_u256() { + let num1 = from_ratio_u256(1, 2); + let num2 = from_ratio_u256(1, 2); + assert!(eq(num1, num2), 1); + + let num3 = from_ratio_u256(1, 3); + assert!(lt(num3, num1), 2); + assert!(gt(num1, num3), 3); + + let num4 = add(num1, num3); + assert!(eq(num4, from_ratio_u256(5, 6)), 4); + + let num5 = sub(num1, num2); + assert!(is_zero(num5), 5); + + let num6 = truncate_u256(num1); + assert!(num6 == 0, 7); + + let num7 = round_up_u256(num1); + assert!(num7 == 1, 8); + + let num8 = round_up_u256(num3); + assert!(num8 == 0, 9); + + let num9 = ceil_u256(num3); + assert!(num9 == 1, 10); + + let num10 = add_by_u256(num1, 1); + assert!(eq(num10, from_ratio_u256(3, 2)), 11); + + let num11 = sub_by_u256(num10, 1); + assert!(eq(num11, from_ratio_u256(1, 2)), 12); + + let num12 = mul_by_u256(num1, 2); + assert!(eq(num12, from_u256(1)), 13); + + let num13 = div_by_u256(num1, 2); + assert!(eq(num13, from_ratio_u256(1, 4)), 14); + } + + #[test] + fun test_bigdecimal_sclaed_value() { + let num1 = div_by_u64(new(biguint::from_u64(1)), 2); + let num2 = get_scaled(num1); + assert!(biguint::eq(num2, biguint::from_u64(500000000000000000)), 1); + + let num3 = from_scaled(num2); + assert!(eq(num1, num3), 2); + } + + #[test] + fun test_bigdecimal_one_zero() { + let num1 = one(); + let num2 = zero(); + assert!(is_one(num1), 1); + assert!(is_zero(num2), 2); + } + + #[test] + fun test_bigdecimal_from_scaled_le_bytes() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(3)); + let num2 = from_scaled_le_bytes(biguint::to_le_bytes(num1.scaled)); + assert!(eq(num1, num2), 1); + } + + #[test] + #[expected_failure(abort_code = 0x10064, location = Self)] + fun test_bigdecimal_sub_negative() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(3)); + let num2 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + + sub(num1, num2); + } + + #[test] + #[expected_failure(abort_code = 0x10064, location = Self)] + fun test_bigdecimal_sub_by_u64_negative() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + + sub_by_u64(num1, 1); + } + + #[test] + #[expected_failure(abort_code = 0x10064, location = Self)] + fun test_bigdecimal_sub_by_u128_negative() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + + sub_by_u128(num1, 1); + } + + #[test] + #[expected_failure(abort_code = 0x10064, location = Self)] + fun test_bigdecimal_sub_by_u256_negative() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + + sub_by_u256(num1, 1); + } + + #[test] + #[expected_failure(abort_code = 0x10065, location = Self)] + fun test_bigdecimal_div_by_zero() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + let num2 = zero(); + + div(num1, num2); + } + + #[test] + #[expected_failure(abort_code = 0x10065, location = Self)] + fun test_bigdecimal_div_by_u64_zero() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + + div_by_u64(num1, 0); + } + + #[test] + #[expected_failure(abort_code = 0x10065, location = Self)] + fun test_bigdecimal_div_by_u128_zero() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + + div_by_u128(num1, 0); + } + + #[test] + #[expected_failure(abort_code = 0x10065, location = Self)] + fun test_bigdecimal_div_by_u256_zero() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + + div_by_u256(num1, 0); + } + + #[test] + fun test_bigdecimal_scaled_le_bytes() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(3)); + let le_bytes = get_scaled_le_bytes(num1); + let num2 = from_scaled_le_bytes(le_bytes); + assert!(eq(num1, num2), 1); + } +} diff --git a/initia_stdlib/sources/biguint.move b/initia_stdlib/sources/biguint.move new file mode 100644 index 0000000..50a2bf6 --- /dev/null +++ b/initia_stdlib/sources/biguint.move @@ -0,0 +1,340 @@ +module initia_std::biguint { + const NEGATIVE_RESULT: u64 = 100; + const EDIVISION_BY_ZERO: u64 = 101; + const CAST_OVERFLOW: u64 = 102; + const INVALID_NUMERIC_TYPE: u64 = 103; + + struct BigUint has copy, drop, store { + bytes: vector + } + + // creation + + /// Create a new BigUint from little-endian bytes. + public fun from_le_bytes(le_bytes: vector): BigUint { + BigUint { bytes: le_bytes } + } + + public fun zero(): BigUint { + from_u64(0) + } + + public fun one(): BigUint { + from_u64(1) + } + + public fun from_u64(num: u64): BigUint { + let num_bytes = new_internal(num); + BigUint { bytes: num_bytes } + } + + public fun to_u64(num: BigUint): u64 { + cast_internal(num.bytes) + } + + public fun from_u128(num: u128): BigUint { + let num_bytes = new_internal(num); + BigUint { bytes: num_bytes } + } + + public fun to_u128(num: BigUint): u128 { + cast_internal(num.bytes) + } + + public fun from_u256(num: u256): BigUint { + let num_bytes = new_internal(num); + BigUint { bytes: num_bytes } + } + + public fun to_u256(num: BigUint): u256 { + cast_internal(num.bytes) + } + + public fun to_le_bytes(num: BigUint): vector { + num.bytes + } + + // arithmetic + + public fun add(num1: BigUint, num2: BigUint): BigUint { + let result_bytes = add_internal(num1.bytes, num2.bytes); + BigUint { bytes: result_bytes } + } + + public fun add_by_u64(num1: BigUint, num2: u64): BigUint { + let num2 = from_u64(num2); + add(num1, num2) + } + + public fun add_by_u128(num1: BigUint, num2: u128): BigUint { + let num2 = from_u128(num2); + add(num1, num2) + } + + public fun add_by_u256(num1: BigUint, num2: u256): BigUint { + let num2 = from_u256(num2); + add(num1, num2) + } + + public fun sub(num1: BigUint, num2: BigUint): BigUint { + let result_bytes = sub_internal(num1.bytes, num2.bytes); + BigUint { bytes: result_bytes } + } + + public fun sub_by_u64(num1: BigUint, num2: u64): BigUint { + let num2 = from_u64(num2); + sub(num1, num2) + } + + public fun sub_by_u128(num1: BigUint, num2: u128): BigUint { + let num2 = from_u128(num2); + sub(num1, num2) + } + + public fun sub_by_u256(num1: BigUint, num2: u256): BigUint { + let num2 = from_u256(num2); + sub(num1, num2) + } + + public fun mul(num1: BigUint, num2: BigUint): BigUint { + let result_bytes = mul_internal(num1.bytes, num2.bytes); + BigUint { bytes: result_bytes } + } + + public fun mul_by_u64(num1: BigUint, num2: u64): BigUint { + let num2 = from_u64(num2); + mul(num1, num2) + } + + public fun mul_by_u128(num1: BigUint, num2: u128): BigUint { + let num2 = from_u128(num2); + mul(num1, num2) + } + + public fun mul_by_u256(num1: BigUint, num2: u256): BigUint { + let num2 = from_u256(num2); + mul(num1, num2) + } + + public fun div(num1: BigUint, num2: BigUint): BigUint { + let result_bytes = div_internal(num1.bytes, num2.bytes); + BigUint { bytes: result_bytes } + } + + public fun div_by_u64(num1: BigUint, num2: u64): BigUint { + let num2 = from_u64(num2); + div(num1, num2) + } + + public fun div_by_u128(num1: BigUint, num2: u128): BigUint { + let num2 = from_u128(num2); + div(num1, num2) + } + + public fun div_by_u256(num1: BigUint, num2: u256): BigUint { + let num2 = from_u256(num2); + div(num1, num2) + } + + // cmp + + public fun eq(num1: BigUint, num2: BigUint): bool { + num1.bytes == num2.bytes + } + + public fun lt(num1: BigUint, num2: BigUint): bool { + lt_internal(num1.bytes, num2.bytes) + } + + public fun le(num1: BigUint, num2: BigUint): bool { + le_internal(num1.bytes, num2.bytes) + } + + public fun gt(num1: BigUint, num2: BigUint): bool { + gt_internal(num1.bytes, num2.bytes) + } + + public fun ge(num1: BigUint, num2: BigUint): bool { + ge_internal(num1.bytes, num2.bytes) + } + + public fun is_zero(num: BigUint): bool { + eq(num, zero()) + } + + public fun is_one(num: BigUint): bool { + eq(num, one()) + } + + native fun add_internal( + num1_bytes: vector, num2_bytes: vector + ): vector; + native fun sub_internal( + num1_bytes: vector, num2_bytes: vector + ): vector; + native fun mul_internal( + num1_bytes: vector, num2_bytes: vector + ): vector; + native fun div_internal( + num1_bytes: vector, num2_bytes: vector + ): vector; + native fun new_internal(num: T): vector; + native fun cast_internal(num_bytes: vector): T; + native fun lt_internal(num1_bytes: vector, num2_bytes: vector): bool; + native fun le_internal(num1_bytes: vector, num2_bytes: vector): bool; + native fun gt_internal(num1_bytes: vector, num2_bytes: vector): bool; + native fun ge_internal(num1_bytes: vector, num2_bytes: vector): bool; + + #[test] + fun test_biguint_u64() { + let num1 = from_u64(4294967295u64 * 2u64); + let num2 = from_u64(4294967295u64 * 2u64); + let num3 = add(num1, num2); + assert!(to_u64(num3) == 4294967295u64 * 4u64, 1); + let num4 = sub(num1, num2); + assert!(to_u64(num4) == 0, 1); + let num5 = mul(num1, from_u64(2)); + assert!(to_u64(num5) == 4294967295u64 * 4u64, 2); + let num6 = div(num1, from_u64(2)); + assert!(to_u64(num6) == 4294967295u64, 3); + + let num7 = add_by_u64(num1, 1); + assert!(to_u64(num7) == 4294967295u64 * 2u64 + 1u64, 4); + let num8 = sub_by_u64(num1, 1); + assert!(to_u64(num8) == 4294967295u64 * 2u64 - 1u64, 5); + let num9 = mul_by_u64(num1, 2); + assert!(to_u64(num9) == 4294967295u64 * 4u64, 6); + let num10 = div_by_u64(num1, 2); + assert!(to_u64(num10) == 4294967295u64, 7); + } + + #[test] + fun test_biguint_u128() { + let num1 = from_u128(18446744073709551615u128 * 2u128); + let num2 = from_u128(18446744073709551615u128 * 2u128); + let num3 = add(num1, num2); + assert!(to_u128(num3) == 18446744073709551615u128 * 4u128, 1); + let num4 = sub(num1, num2); + assert!(to_u128(num4) == 0, 1); + let num5 = mul(num1, from_u128(2)); + assert!(to_u128(num5) == 18446744073709551615u128 * 4u128, 2); + let num6 = div(num1, from_u128(2)); + assert!(to_u128(num6) == 18446744073709551615u128, 3); + + let num7 = add_by_u128(num1, 1); + assert!(to_u128(num7) == 18446744073709551615u128 * 2u128 + 1u128, 4); + let num8 = sub_by_u128(num1, 1); + assert!(to_u128(num8) == 18446744073709551615u128 * 2u128 - 1u128, 5); + let num9 = mul_by_u128(num1, 2); + assert!(to_u128(num9) == 18446744073709551615u128 * 4u128, 6); + let num10 = div_by_u128(num1, 2); + assert!(to_u128(num10) == 18446744073709551615u128, 7); + } + + #[test] + fun test_biguint_u256() { + let num1 = from_u256(340282366920938463463374607431768211455u256 * 2u256); + let num2 = from_u256(340282366920938463463374607431768211455u256 * 2u256); + let num3 = add(num1, num2); + assert!(to_u256(num3) == 340282366920938463463374607431768211455u256 * 4u256, 1); + let num4 = sub(num1, num2); + assert!(to_u256(num4) == 0, 1); + let num5 = mul(num1, from_u256(2)); + assert!(to_u256(num5) == 340282366920938463463374607431768211455u256 * 4u256, 2); + let num6 = div(num1, from_u256(2)); + assert!(to_u256(num6) == 340282366920938463463374607431768211455u256, 3); + + let num7 = add_by_u256(num1, 1); + assert!( + to_u256(num7) + == 340282366920938463463374607431768211455u256 * 2u256 + 1u256, + 4 + ); + let num8 = sub_by_u256(num1, 1); + assert!( + to_u256(num8) + == 340282366920938463463374607431768211455u256 * 2u256 - 1u256, + 5 + ); + let num9 = mul_by_u256(num1, 2); + assert!(to_u256(num9) == 340282366920938463463374607431768211455u256 * 4u256, 6); + let num10 = div_by_u256(num1, 2); + assert!(to_u256(num10) == 340282366920938463463374607431768211455u256, 7); + } + + #[test] + #[expected_failure(abort_code = 0x10064, location = Self)] + fun test_biguint_sub_negative() { + let num1 = from_u64(1); + let num2 = from_u64(2); + let _ = sub(num1, num2); + } + + #[test] + #[expected_failure(abort_code = 0x10066, location = Self)] + fun test_biguint_case_overflow_u64() { + let num1 = from_u128(18446744073709551616u128); + let _ = cast_internal(num1.bytes); + } + + #[test] + #[expected_failure(abort_code = 0x10066, location = Self)] + fun test_biguint_case_overflow_u128() { + let num1 = from_u256(340282366920938463463374607431768211456u256); + let _ = cast_internal(num1.bytes); + } + + #[test] + #[expected_failure(abort_code = 0x10066, location = Self)] + fun test_biguint_case_overflow_u256() { + let num1 = + from_u256( + 115792089237316195423570985008687907853269984665640564039457584007913129639935u256 + ); + let num1 = mul(num1, from_u64(2u64)); + let _ = cast_internal(num1.bytes); + } + + #[test] + fun test_biguint_max_cast() { + let num1 = from_u64(18446744073709551615u64); + let _ = cast_internal(num1.bytes); + + let num1 = from_u128(340282366920938463463374607431768211454u128); + let _ = cast_internal(num1.bytes); + + let num1 = + from_u256( + 115792089237316195423570985008687907853269984665640564039457584007913129639935u256 + ); + let _ = cast_internal(num1.bytes); + } + + #[test] + #[expected_failure(abort_code = 0x10065, location = Self)] + fun test_biguint_div_by_zero() { + let num1 = from_u64(1); + let num2 = from_u64(0); + let _ = div(num1, num2); + } + + #[test] + fun test_biguint_cmp() { + let num1 = from_u64(1); + let num2 = from_u64(2); + assert!(lt(num1, num2), 1); + assert!(le(num1, num2), 2); + assert!(gt(num2, num1), 3); + assert!(ge(num2, num1), 4); + assert!(eq(num1, num1), 5); + assert!(!eq(num1, num2), 6); + } + + #[test] + fun test_biguint_from_le_bytes() { + let num1 = from_u64(1123); + let bytes = to_le_bytes(num1); + let num2 = from_le_bytes(bytes); + assert!(eq(num1, num2), 1); + } +} diff --git a/initia_stdlib/sources/block.move b/initia_stdlib/sources/block.move index 225fd40..f7475c7 100644 --- a/initia_stdlib/sources/block.move +++ b/initia_stdlib/sources/block.move @@ -12,4 +12,44 @@ module initia_std::block { assert!(height == 12321u64, 0); assert!(timestamp == 9999999u64, 1); } + + // Functions for compatibility with the aptos + + #[view] + public fun get_current_block_height(): u64 { + let (height, _) = get_block_info(); + height + } + + #[view] + public fun get_current_block_timestamp(): u64 { + let (_, timestamp) = get_block_info(); + timestamp + } + + #[test_only] + public fun initialize_for_test( + _vm: &signer, _epoch_interval_microsecs: u64 + ) { + // no-op + } + + #[test_only] + use initia_std::signer; + + #[test_only] + struct HasGenesisBlock has key {} + + #[test_only] + public fun emit_writeset_block_event( + vm: &signer, _fake_block_hash: address + ) { + if (!exists(signer::address_of(vm))) { + move_to(vm, HasGenesisBlock {}); + return + }; + + let (block_height, block_time) = get_block_info(); + set_block_info(block_height + 1, block_time); + } } diff --git a/initia_stdlib/sources/code.move b/initia_stdlib/sources/code.move index ca88352..57127a0 100644 --- a/initia_stdlib/sources/code.move +++ b/initia_stdlib/sources/code.move @@ -4,7 +4,9 @@ module initia_std::code { use std::signer; use std::vector; use std::event; + use std::option; + use initia_std::object::{Self, Object}; use initia_std::table::{Self, Table}; use initia_std::simple_map; @@ -17,11 +19,11 @@ module initia_std::code { allowed_publishers: vector
, /// The total number of modules published. - total_modules: u64, + total_modules: u64 } struct MetadataStore has key { - metadata: Table, + metadata: Table } /// Describes an upgrade policy @@ -32,7 +34,7 @@ module initia_std::code { #[event] struct ModulePublishedEvent has store, drop { module_id: String, - upgrade_policy: u8, + upgrade_policy: u8 } /// Cannot upgrade an immutable package. @@ -56,6 +58,12 @@ module initia_std::code { /// The module ID is duplicated. const EDUPLICATE_MODULE_ID: u64 = 0x7; + /// Not the owner of the package registry. + const ENOT_PACKAGE_OWNER: u64 = 0x8; + + /// `code_object` does not exist. + const ECODE_OBJECT_DOES_NOT_EXIST: u64 = 0x9; + /// Whether a compatibility check should be performed for upgrades. The check only passes if /// a new module has (a) the same public functions (b) for existing resources, no layout change. const UPGRADE_POLICY_COMPATIBLE: u8 = 1; @@ -72,7 +80,7 @@ module initia_std::code { fun init_module(chain: &signer) { move_to( chain, - ModuleStore { allowed_publishers: vector[], total_modules: 0, }, + ModuleStore { allowed_publishers: vector[], total_modules: 0 } ); } @@ -103,18 +111,16 @@ module initia_std::code { assert!( vector::is_empty(allowed_publishers) || vector::contains(allowed_publishers, &addr), - error::invalid_argument(EINVALID_ALLOWED_PUBLISHERS), + error::invalid_argument(EINVALID_ALLOWED_PUBLISHERS) ) } public entry fun init_genesis( - chain: &signer, - module_ids: vector, - allowed_publishers: vector
, + chain: &signer, module_ids: vector, allowed_publishers: vector
) acquires ModuleStore { assert!( signer::address_of(chain) == @initia_std, - error::permission_denied(EINVALID_CHAIN_OPERATOR), + error::permission_denied(EINVALID_CHAIN_OPERATOR) ); let metadata_table = table::new(); @@ -124,14 +130,14 @@ module initia_std::code { table::add( &mut metadata_table, *module_id, - ModuleMetadata { upgrade_policy: UPGRADE_POLICY_COMPATIBLE, }, + ModuleMetadata { upgrade_policy: UPGRADE_POLICY_COMPATIBLE } ); - }, + } ); move_to( chain, - MetadataStore { metadata: metadata_table, }, + MetadataStore { metadata: metadata_table } ); set_allowed_publishers(chain, allowed_publishers); @@ -143,7 +149,7 @@ module initia_std::code { ) acquires ModuleStore { assert!( signer::address_of(chain) == @initia_std, - error::permission_denied(EINVALID_CHAIN_OPERATOR), + error::permission_denied(EINVALID_CHAIN_OPERATOR) ); assert_allowed(&allowed_publishers, @initia_std); @@ -151,18 +157,43 @@ module initia_std::code { module_store.allowed_publishers = allowed_publishers; } + public fun freeze_code_object( + publisher: &signer, code_object: Object + ) acquires MetadataStore { + let code_object_addr = object::object_address(&code_object); + assert!( + exists(code_object_addr), + error::not_found(ECODE_OBJECT_DOES_NOT_EXIST) + ); + assert!( + object::is_owner(code_object, signer::address_of(publisher)), + error::permission_denied(ENOT_PACKAGE_OWNER) + ); + + let registry = borrow_global_mut(code_object_addr); + let iter = table::iter_mut( + &mut registry.metadata, option::none(), option::none(), 1 + ); + loop { + if (!table::prepare_mut(iter)) { break }; + + let (_, metadata) = table::next_mut(iter); + metadata.upgrade_policy = UPGRADE_POLICY_IMMUTABLE; + } + } + /// Publishes a package at the given signer's address. The caller must provide package metadata describing the /// package. public entry fun publish( owner: &signer, module_ids: vector, // 0x1::coin code: vector>, - upgrade_policy: u8, + upgrade_policy: u8 ) acquires ModuleStore, MetadataStore { // Disallow incompatible upgrade mode. Governance can decide later if this should be reconsidered. assert!( vector::length(&code) == vector::length(&module_ids), - error::invalid_argument(EINVALID_ARGUMENTS), + error::invalid_argument(EINVALID_ARGUMENTS) ); // duplication check @@ -172,14 +203,14 @@ module initia_std::code { |module_id| { assert!( !simple_map::contains_key(&module_ids_set, module_id), - error::invalid_argument(EDUPLICATE_MODULE_ID), + error::invalid_argument(EDUPLICATE_MODULE_ID) ); simple_map::add( &mut module_ids_set, *module_id, - true, + true ); - }, + } ); // Check whether arbitrary publish is allowed or not. @@ -187,7 +218,7 @@ module initia_std::code { assert!( upgrade_policy == UPGRADE_POLICY_COMPATIBLE || upgrade_policy == UPGRADE_POLICY_IMMUTABLE, - error::invalid_argument(EUPGRADE_POLICY_UNSPECIFIED), + error::invalid_argument(EUPGRADE_POLICY_UNSPECIFIED) ); let addr = signer::address_of(owner); @@ -196,7 +227,7 @@ module initia_std::code { if (!exists(addr)) { move_to( owner, - MetadataStore { metadata: table::new(), }, + MetadataStore { metadata: table::new() } ); }; @@ -212,14 +243,14 @@ module initia_std::code { ); assert!( metadata.upgrade_policy < UPGRADE_POLICY_IMMUTABLE, - error::invalid_argument(EUPGRADE_IMMUTABLE), + error::invalid_argument(EUPGRADE_IMMUTABLE) ); assert!( can_change_upgrade_policy_to( metadata.upgrade_policy, - upgrade_policy, + upgrade_policy ), - error::invalid_argument(EUPGRADE_WEAKER_POLICY), + error::invalid_argument(EUPGRADE_WEAKER_POLICY) ); metadata.upgrade_policy = upgrade_policy; @@ -227,14 +258,14 @@ module initia_std::code { table::add( metadata_table, *module_id, - ModuleMetadata { upgrade_policy, }, + ModuleMetadata { upgrade_policy } ); }; event::emit( - ModulePublishedEvent { module_id: *module_id, upgrade_policy, }, + ModulePublishedEvent { module_id: *module_id, upgrade_policy } ); - }, + } ); // Request publish @@ -244,6 +275,6 @@ module initia_std::code { /// Native function to initiate module loading native fun request_publish( - owner: address, expected_modules: vector, code: vector>, + owner: address, expected_modules: vector, code: vector> ); } diff --git a/initia_stdlib/sources/coin.move b/initia_stdlib/sources/coin.move index 66ff76d..62ba20e 100644 --- a/initia_stdlib/sources/coin.move +++ b/initia_stdlib/sources/coin.move @@ -26,7 +26,7 @@ module initia_std::coin { struct ManagingRefs has key { mint_ref: MintRef, burn_ref: BurnRef, - transfer_ref: TransferRef, + transfer_ref: TransferRef } /// Only fungible asset metadata owner can make changes. @@ -37,19 +37,19 @@ module initia_std::coin { #[event] struct CoinCreatedEvent has drop, store { - metadata_addr: address, + metadata_addr: address } struct MintCapability has drop, store { - metadata: Object, + metadata: Object } struct BurnCapability has drop, store { - metadata: Object, + metadata: Object } struct FreezeCapability has drop, store { - metadata: Object, + metadata: Object } const EUNAUTHORIZED: u64 = 1; @@ -61,7 +61,7 @@ module initia_std::coin { fun check_sudo(account: &signer) { assert!( signer::address_of(account) == @initia_std, - error::permission_denied(EUNAUTHORIZED), + error::permission_denied(EUNAUTHORIZED) ); } @@ -70,7 +70,7 @@ module initia_std::coin { sender: &signer, recipient: address, metadata: Object, - amount: u64, + amount: u64 ) { check_sudo(chain); @@ -78,7 +78,7 @@ module initia_std::coin { } public(friend) fun sudo_deposit( - account_addr: address, fa: FungibleAsset, + account_addr: address, fa: FungibleAsset ) { primary_fungible_store::sudo_deposit(account_addr, fa) } @@ -94,7 +94,7 @@ module initia_std::coin { symbol: String, decimals: u8, icon_uri: String, - project_uri: String, + project_uri: String ): (MintCapability, BurnCapability, FreezeCapability) { let (mint_cap, burn_cap, freeze_cap, _) = initialize_and_generate_extend_ref( @@ -104,7 +104,7 @@ module initia_std::coin { symbol, decimals, icon_uri, - project_uri, + project_uri ); (mint_cap, burn_cap, freeze_cap) @@ -117,13 +117,13 @@ module initia_std::coin { symbol: String, decimals: u8, icon_uri: String, - project_uri: String, + project_uri: String ): (MintCapability, BurnCapability, FreezeCapability, ExtendRef) { // create object for fungible asset metadata let constructor_ref = &object::create_named_object( creator, - *string::bytes(&symbol), + *string::bytes(&symbol) ); primary_fungible_store::create_primary_store_enabled_fungible_asset( @@ -133,7 +133,7 @@ module initia_std::coin { symbol, decimals, icon_uri, - project_uri, + project_uri ); let mint_ref = fungible_asset::generate_mint_ref(constructor_ref); @@ -143,11 +143,11 @@ module initia_std::coin { let object_signer = object::generate_signer(constructor_ref); move_to( &object_signer, - ManagingRefs { mint_ref, burn_ref, transfer_ref, }, + ManagingRefs { mint_ref, burn_ref, transfer_ref } ); let metadata_addr = object::address_from_constructor_ref(constructor_ref); - event::emit(CoinCreatedEvent { metadata_addr, }); + event::emit(CoinCreatedEvent { metadata_addr }); let metadata = object::object_from_constructor_ref(constructor_ref); ( @@ -159,14 +159,12 @@ module initia_std::coin { } public fun withdraw( - account: &signer, - metadata: Object, - amount: u64, + account: &signer, metadata: Object, amount: u64 ): FungibleAsset { primary_fungible_store::withdraw(account, metadata, amount) } - public fun deposit(account_addr: address, fa: FungibleAsset,) { + public fun deposit(account_addr: address, fa: FungibleAsset) { primary_fungible_store::deposit(account_addr, fa) } @@ -174,7 +172,7 @@ module initia_std::coin { sender: &signer, recipient: address, metadata: Object, - amount: u64, + amount: u64 ) { primary_fungible_store::transfer(sender, metadata, recipient, amount) } @@ -184,13 +182,13 @@ module initia_std::coin { // /// Mint FAs as the owner of metadat object. - public fun mint(mint_cap: &MintCapability, amount: u64,): FungibleAsset acquires ManagingRefs { + public fun mint(mint_cap: &MintCapability, amount: u64): FungibleAsset acquires ManagingRefs { let metadata = mint_cap.metadata; let metadata_addr = object::object_address(&metadata); assert!( exists(metadata_addr), - ERR_MANAGING_REFS_NOT_FOUND, + ERR_MANAGING_REFS_NOT_FOUND ); let refs = borrow_global(metadata_addr); @@ -199,16 +197,14 @@ module initia_std::coin { /// Mint FAs as the owner of metadat object to the primary fungible store of the given recipient. public fun mint_to( - mint_cap: &MintCapability, - recipient: address, - amount: u64, + mint_cap: &MintCapability, recipient: address, amount: u64 ) acquires ManagingRefs { let metadata = mint_cap.metadata; let metadata_addr = object::object_address(&metadata); assert!( exists(metadata_addr), - ERR_MANAGING_REFS_NOT_FOUND, + ERR_MANAGING_REFS_NOT_FOUND ); let refs = borrow_global(metadata_addr); @@ -216,13 +212,13 @@ module initia_std::coin { } /// Burn FAs as the owner of metadat object. - public fun burn(burn_cap: &BurnCapability, fa: FungibleAsset,) acquires ManagingRefs { + public fun burn(burn_cap: &BurnCapability, fa: FungibleAsset) acquires ManagingRefs { let metadata = burn_cap.metadata; let metadata_addr = object::object_address(&metadata); assert!( exists(metadata_addr), - ERR_MANAGING_REFS_NOT_FOUND, + ERR_MANAGING_REFS_NOT_FOUND ); let refs = borrow_global(metadata_addr); @@ -231,41 +227,41 @@ module initia_std::coin { /// Freeze the primary store of an account. public fun freeze_coin_store( - freeze_cap: &FreezeCapability, account_addr: address, + freeze_cap: &FreezeCapability, account_addr: address ) acquires ManagingRefs { let metadata = freeze_cap.metadata; let metadata_addr = object::object_address(&metadata); assert!( exists(metadata_addr), - ERR_MANAGING_REFS_NOT_FOUND, + ERR_MANAGING_REFS_NOT_FOUND ); let refs = borrow_global(metadata_addr); primary_fungible_store::set_frozen_flag( &refs.transfer_ref, account_addr, - true, + true ) } /// Unfreeze the primary store of an account. public fun unfreeze_coin_store( - freeze_cap: &FreezeCapability, account_addr: address, + freeze_cap: &FreezeCapability, account_addr: address ) acquires ManagingRefs { let metadata = freeze_cap.metadata; let metadata_addr = object::object_address(&metadata); assert!( exists(metadata_addr), - ERR_MANAGING_REFS_NOT_FOUND, + ERR_MANAGING_REFS_NOT_FOUND ); let refs = borrow_global(metadata_addr); primary_fungible_store::set_frozen_flag( &refs.transfer_ref, account_addr, - false, + false ) } @@ -285,9 +281,7 @@ module initia_std::coin { #[view] public fun balances( - account: address, - start_after: Option
, - limit: u8, + account: address, start_after: Option
, limit: u8 ): (vector>, vector) { primary_fungible_store::balances(account, start_after, limit) } @@ -364,7 +358,7 @@ module initia_std::coin { public fun denom_to_metadata(denom: String): Object { let addr = if (string::length(&denom) > 5 - && &b"move/" == string::bytes(&string::sub_string(&denom, 0, 5))) { + && &b"move/" == string::bytes(&string::sub_string(&denom, 0, 5))) { let len = string::length(&denom); let hex_string = string::sub_string(&denom, 5, len); from_bcs::to_address(hex::decode_string(&hex_string)) @@ -375,11 +369,13 @@ module initia_std::coin { object::address_to_object(addr) } + // for lz compatibility + struct Coin {} + #[test_only] - fun initialized_coin(account: &signer, symbol: String,) - : ( - BurnCapability, FreezeCapability, MintCapability - ) { + fun initialize_coin_for_testing( + account: &signer, symbol: String + ): (BurnCapability, FreezeCapability, MintCapability) { let (mint_cap, burn_cap, freeze_cap, _) = initialize_and_generate_extend_ref( account, @@ -388,25 +384,25 @@ module initia_std::coin { symbol, 6, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); return (burn_cap, freeze_cap, mint_cap) } #[test(chain = @0x1, not_chain = @0x2)] - fun test_denom_metadata_convert(chain: signer, not_chain: signer,) { + fun test_denom_metadata_convert(chain: signer, not_chain: signer) { initia_std::primary_fungible_store::init_module_for_test(); - initialized_coin(&chain, string::utf8(b"INIT")); - initialized_coin(¬_chain, string::utf8(b"INIT")); + initialize_coin_for_testing(&chain, string::utf8(b"INIT")); + initialize_coin_for_testing(¬_chain, string::utf8(b"INIT")); let metadata = metadata( std::signer::address_of(&chain), - string::utf8(b"INIT"), + string::utf8(b"INIT") ); let metadata_ = metadata( std::signer::address_of(¬_chain), - string::utf8(b"INIT"), + string::utf8(b"INIT") ); let denom = metadata_to_denom(metadata); let denom_ = metadata_to_denom(metadata_); diff --git a/initia_stdlib/sources/comparator.move b/initia_stdlib/sources/comparator.move index 9463bab..deec526 100644 --- a/initia_stdlib/sources/comparator.move +++ b/initia_stdlib/sources/comparator.move @@ -8,7 +8,7 @@ module initia_std::comparator { const GREATER: u8 = 2; struct Result has drop { - inner: u8, + inner: u8 } public fun is_equal(result: &Result): bool { @@ -73,29 +73,29 @@ module initia_std::comparator { assert!( is_greater_than(&compare(&value0, &value1)), - 3, + 3 ); assert!( is_smaller_than(&compare(&value1, &value0)), - 4, + 4 ); assert!( is_smaller_than(&compare(&value0, &value2)), - 5, + 5 ); assert!( is_greater_than(&compare(&value2, &value0)), - 6, + 6 ); assert!( is_smaller_than(&compare(&value1, &value2)), - 7, + 7 ); assert!( is_greater_than(&compare(&value2, &value1)), - 8, + 8 ); } @@ -111,29 +111,29 @@ module initia_std::comparator { assert!( is_smaller_than(&compare(&value0, &value1)), - 2, + 2 ); assert!( is_greater_than(&compare(&value1, &value0)), - 3, + 3 ); assert!( is_smaller_than(&compare(&value0, &value2)), - 3, + 3 ); assert!( is_greater_than(&compare(&value2, &value0)), - 4, + 4 ); assert!( is_smaller_than(&compare(&value1, &value2)), - 5, + 5 ); assert!( is_greater_than(&compare(&value2, &value1)), - 6, + 6 ); } @@ -141,7 +141,7 @@ module initia_std::comparator { struct Complex has drop { value0: vector, value1: u8, - value2: u64, + value2: u64 } #[test] @@ -157,13 +157,13 @@ module initia_std::comparator { vector::push_back(&mut value0_1, 5); vector::push_back(&mut value0_1, 1); - let base = Complex { value0: value0_0, value1: 13, value2: 41, }; + let base = Complex { value0: value0_0, value1: 13, value2: 41 }; - let other_0 = Complex { value0: value0_1, value1: 13, value2: 41, }; + let other_0 = Complex { value0: value0_1, value1: 13, value2: 41 }; - let other_1 = Complex { value0: copy value0_0, value1: 14, value2: 41, }; + let other_1 = Complex { value0: copy value0_0, value1: 14, value2: 41 }; - let other_2 = Complex { value0: value0_0, value1: 13, value2: 42, }; + let other_2 = Complex { value0: value0_0, value1: 13, value2: 42 }; assert!(is_equal(&compare(&base, &base)), 0); assert!(is_smaller_than(&compare(&base, &other_0)), 1); diff --git a/initia_stdlib/sources/compatibility/aptos_coin.move b/initia_stdlib/sources/compatibility/aptos_coin.move index 1520d28..64c2104 100644 --- a/initia_stdlib/sources/compatibility/aptos_coin.move +++ b/initia_stdlib/sources/compatibility/aptos_coin.move @@ -16,14 +16,14 @@ module initia_std::aptos_coin { string::utf8(b"uinit"), 0, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); }; managed_coin::mint( &account::create_signer_for_test(@initia_std), coin::metadata(@initia_std, string::utf8(b"uinit")), - amount, + amount ) } diff --git a/initia_stdlib/sources/compatibility/reconfiguration.move b/initia_stdlib/sources/compatibility/reconfiguration.move new file mode 100644 index 0000000..ae6bb98 --- /dev/null +++ b/initia_stdlib/sources/compatibility/reconfiguration.move @@ -0,0 +1,6 @@ +#[test_only] +module initia_std::reconfiguration { + public fun initialize_for_test(_: &signer) { + // no-op + } +} diff --git a/initia_stdlib/sources/copyable_any.move b/initia_stdlib/sources/copyable_any.move index 9fa1b54..68bdc8c 100644 --- a/initia_stdlib/sources/copyable_any.move +++ b/initia_stdlib/sources/copyable_any.move @@ -17,14 +17,17 @@ module initia_std::copyable_any { /// Pack a value into the `Any` representation. Because Any can be stored, dropped, and copied this is /// also required from `T`. public fun pack(x: T): Any { - Any { type_name: type_info::type_name(), data: bcs::to_bytes(&x) } + Any { + type_name: type_info::type_name(), + data: bcs::to_bytes(&x) + } } /// Unpack a value from the `Any` representation. This aborts if the value has not the expected type `T`. public fun unpack(x: Any): T { assert!( type_info::type_name() == x.type_name, - error::invalid_argument(ETYPE_MISMATCH), + error::invalid_argument(ETYPE_MISMATCH) ); from_bytes(x.data) } diff --git a/initia_stdlib/sources/cosmos.move b/initia_stdlib/sources/cosmos.move index ff981f7..35e3dcc 100644 --- a/initia_stdlib/sources/cosmos.move +++ b/initia_stdlib/sources/cosmos.move @@ -15,7 +15,7 @@ module initia_std::cosmos { proposal_id: u64, voter: String, option: u64, - metadata: String, + metadata: String } public entry fun stargate_vote( @@ -33,9 +33,9 @@ module initia_std::cosmos { proposal_id, voter, option, - metadata, - }, - ), + metadata + } + ) ); } @@ -49,7 +49,7 @@ module initia_std::cosmos { module_name: String, function_name: String, type_args: vector, - args: vector>, + args: vector> ) { move_execute_internal( signer::address_of(sender), @@ -58,7 +58,7 @@ module initia_std::cosmos { *string::bytes(&function_name), vector::map_ref(&type_args, |v| *string::bytes(v)), args, - false, + false ) } @@ -68,7 +68,7 @@ module initia_std::cosmos { module_name: String, function_name: String, type_args: vector, - args: vector, + args: vector ) { move_execute_internal( signer::address_of(sender), @@ -77,7 +77,7 @@ module initia_std::cosmos { *string::bytes(&function_name), vector::map_ref(&type_args, |v| *string::bytes(v)), vector::map_ref(&args, |v| *string::bytes(v)), - true, + true ) } @@ -85,14 +85,14 @@ module initia_std::cosmos { sender: &signer, code_bytes: vector, type_args: vector, - args: vector>, + args: vector> ) { move_script_internal( signer::address_of(sender), code_bytes, vector::map_ref(&type_args, |v| *string::bytes(v)), args, - false, + false ) } @@ -100,14 +100,14 @@ module initia_std::cosmos { sender: &signer, code_bytes: vector, type_args: vector, - args: vector, + args: vector ) { move_script_internal( signer::address_of(sender), code_bytes, vector::map_ref(&type_args, |v| *string::bytes(v)), vector::map_ref(&args, |v| *string::bytes(v)), - true, + true ) } @@ -115,25 +115,23 @@ module initia_std::cosmos { delegator: &signer, validator: String, metadata: Object, - amount: u64, + amount: u64 ) { delegate_internal( signer::address_of(delegator), *string::bytes(&validator), &metadata, - amount, + amount ) } public entry fun fund_community_pool( - sender: &signer, - metadata: Object, - amount: u64, + sender: &signer, metadata: Object, amount: u64 ) { fund_community_pool_internal( signer::address_of(sender), &metadata, - amount, + amount ) } @@ -149,7 +147,7 @@ module initia_std::cosmos { revision_number: u64, revision_height: u64, timeout_timestamp: u64, - memo: String, + memo: String ) { transfer_internal( signer::address_of(sender), @@ -161,7 +159,7 @@ module initia_std::cosmos { revision_number, revision_height, timeout_timestamp, - *string::bytes(&memo), + *string::bytes(&memo) ) } @@ -177,7 +175,7 @@ module initia_std::cosmos { revision_number: u64, revision_height: u64, timeout_timestamp: u64, - memo: String, + memo: String ) { nft_transfer_internal( signer::address_of(sender), @@ -189,7 +187,7 @@ module initia_std::cosmos { revision_number, revision_height, timeout_timestamp, - *string::bytes(&memo), + *string::bytes(&memo) ) } @@ -204,7 +202,7 @@ module initia_std::cosmos { ack_fee_metadata: Object, ack_fee_amount: u64, timeout_fee_metadata: Object, - timeout_fee_amount: u64, + timeout_fee_amount: u64 ) { pay_fee_internal( signer::address_of(sender), @@ -215,11 +213,11 @@ module initia_std::cosmos { &ack_fee_metadata, ack_fee_amount, &timeout_fee_metadata, - timeout_fee_amount, + timeout_fee_amount ) } - native fun stargate_internal(sender: address, data: vector,); + native fun stargate_internal(sender: address, data: vector); native fun move_execute_internal( sender: address, @@ -228,7 +226,7 @@ module initia_std::cosmos { function_name: vector, type_args: vector>, args: vector>, - is_json: bool, + is_json: bool ); native fun move_script_internal( @@ -236,18 +234,18 @@ module initia_std::cosmos { code_bytes: vector, type_args: vector>, args: vector>, - is_json: bool, + is_json: bool ); native fun delegate_internal( delegator: address, validator: vector, metadata: &Object, - amount: u64, + amount: u64 ); native fun fund_community_pool_internal( - sender: address, metadata: &Object, amount: u64, + sender: address, metadata: &Object, amount: u64 ); native fun transfer_internal( @@ -260,7 +258,7 @@ module initia_std::cosmos { revision_number: u64, revision_height: u64, timeout_timestamp: u64, - memo: vector, + memo: vector ); native fun nft_transfer_internal( @@ -273,7 +271,7 @@ module initia_std::cosmos { revision_number: u64, revision_height: u64, timeout_timestamp: u64, - memo: vector, + memo: vector ); native fun pay_fee_internal( @@ -285,6 +283,6 @@ module initia_std::cosmos { ack_fee_metadata: &Object, ack_fee_amount: u64, timeout_fee_metadata: &Object, - timeout_fee_amount: u64, + timeout_fee_amount: u64 ); } diff --git a/initia_stdlib/sources/crypto/ed25519.move b/initia_stdlib/sources/crypto/ed25519.move index 476c273..b73d75f 100644 --- a/initia_stdlib/sources/crypto/ed25519.move +++ b/initia_stdlib/sources/crypto/ed25519.move @@ -44,7 +44,7 @@ module initia_std::ed25519 { public fun public_key_from_bytes(bytes: vector): PublicKey { assert!( std::vector::length(&bytes) == PUBLIC_KEY_SIZE, - std::error::invalid_argument(PUBLIC_KEY_SIZE), + std::error::invalid_argument(PUBLIC_KEY_SIZE) ); PublicKey { bytes } } @@ -53,7 +53,7 @@ module initia_std::ed25519 { public fun signature_from_bytes(bytes: vector): Signature { assert!( std::vector::length(&bytes) == SIGNATURE_SIZE, - std::error::invalid_argument(E_WRONG_SIGNATURE_SIZE), + std::error::invalid_argument(E_WRONG_SIGNATURE_SIZE) ); Signature { bytes } } @@ -70,14 +70,12 @@ module initia_std::ed25519 { /// Verifies a Ed25519 `signature` under an `public_key` on the specified `message`. public fun verify( - message: vector, - public_key: &PublicKey, - signature: &Signature, + message: vector, public_key: &PublicKey, signature: &Signature ): bool { verify_internal( message, public_key.bytes, - signature.bytes, + signature.bytes ) } @@ -100,7 +98,7 @@ module initia_std::ed25519 { public fun batch_verify( messages: vector>, public_keys: vector, - signatures: vector, + signatures: vector ): bool { let message_length = std::vector::length(&messages); let public_key_length = std::vector::length(&public_keys); @@ -109,19 +107,20 @@ module initia_std::ed25519 { if (message_length == 1) { assert!( public_key_length == signature_length, - std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH), + std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH) ); if (public_key_length == 0) return true; } else if (public_key_length == 1) { assert!( message_length == signature_length, - std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH), + std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH) ); if (message_length == 0) return true; } else { assert!( - message_length == public_key_length && public_key_length == signature_length, - std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH), + message_length == public_key_length + && public_key_length == signature_length, + std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH) ); if (message_length == 0) return true; }; diff --git a/initia_stdlib/sources/crypto/secp256k1.move b/initia_stdlib/sources/crypto/secp256k1.move index e54123c..3ac1333 100644 --- a/initia_stdlib/sources/crypto/secp256k1.move +++ b/initia_stdlib/sources/crypto/secp256k1.move @@ -45,7 +45,7 @@ module initia_std::secp256k1 { public fun ecdsa_signature_from_bytes(bytes: vector): ECDSASignature { assert!( std::vector::length(&bytes) == SIGNATURE_NUM_BYTES, - std::error::invalid_argument(E_DESERIALIZE), + std::error::invalid_argument(E_DESERIALIZE) ); ECDSASignature { bytes } } @@ -59,17 +59,17 @@ module initia_std::secp256k1 { public fun ecdsa_raw_public_key_from_bytes(bytes: vector): ECDSARawPublicKey { assert!( std::vector::length(&bytes) == RAW_PUBLIC_KEY_NUM_BYTES, - std::error::invalid_argument(E_DESERIALIZE), + std::error::invalid_argument(E_DESERIALIZE) ); ECDSARawPublicKey { bytes } } /// Constructs an ECDSACompressedPublicKey struct, given a 33-byte raw representation. - public fun ecdsa_compressed_public_key_from_bytes(bytes: vector) - : ECDSACompressedPublicKey { + public fun ecdsa_compressed_public_key_from_bytes(bytes: vector): + ECDSACompressedPublicKey { assert!( std::vector::length(&bytes) == COMPRESSED_PUBLIC_KEY_SIZE, - std::error::invalid_argument(E_DESERIALIZE), + std::error::invalid_argument(E_DESERIALIZE) ); ECDSACompressedPublicKey { bytes } } @@ -91,6 +91,24 @@ module initia_std::secp256k1 { sig.bytes } + /// Returns `true` if the signature can verify the public key on the message + public fun verify( + message: vector, + public_key: &ECDSACompressedPublicKey, + signature: &ECDSASignature + ): bool { + assert!( + std::vector::length(&message) == MESSAGE_SIZE, + std::error::invalid_argument(E_DESERIALIZE) + ); + + return verify_internal( + message, + public_key.bytes, + signature.bytes + ) + } + /// Recovers the signer's raw (64-byte) public key from a secp256k1 ECDSA `signature` given the `recovery_id` and the signed /// `message` (32 byte digest). /// @@ -98,13 +116,11 @@ module initia_std::secp256k1 { /// incorrect public key. This recovery algorithm can only be used to check validity of a signature if the signer's /// public key (or its hash) is known beforehand. public fun ecdsa_recover( - message: vector, - recovery_id: u8, - signature: &ECDSASignature, + message: vector, recovery_id: u8, signature: &ECDSASignature ): Option { assert!( std::vector::length(&message) == MESSAGE_SIZE, - std::error::invalid_argument(E_DESERIALIZE), + std::error::invalid_argument(E_DESERIALIZE) ); let (pk, success) = @@ -112,7 +128,7 @@ module initia_std::secp256k1 { recovery_id, message, signature.bytes, - false, + false ); if (success) { std::option::some(ecdsa_raw_public_key_from_bytes(pk)) @@ -128,13 +144,11 @@ module initia_std::secp256k1 { /// incorrect public key. This recovery algorithm can only be used to check validity of a signature if the signer's /// public key (or its hash) is known beforehand. public fun ecdsa_recover_compressed( - message: vector, - recovery_id: u8, - signature: &ECDSASignature, + message: vector, recovery_id: u8, signature: &ECDSASignature ): Option { assert!( std::vector::length(&message) == MESSAGE_SIZE, - std::error::invalid_argument(E_DESERIALIZE), + std::error::invalid_argument(E_DESERIALIZE) ); let (pk, success) = @@ -142,7 +156,7 @@ module initia_std::secp256k1 { recovery_id, message, signature.bytes, - true, + true ); if (success) { std::option::some(ecdsa_compressed_public_key_from_bytes(pk)) @@ -155,10 +169,25 @@ module initia_std::secp256k1 { // Native functions // + /// Returns `true` if `signature` verifies on `public_key` and `message` + /// and returns `false` otherwise. + /// + /// - `message`: A 32-byte hashed message. + /// - `public_key`: A compressed public key in bytes. + /// - `signature`: A 64-byte ECDSA signature. + native fun verify_internal( + message: vector, + public_key: vector, + signature: vector + ): bool; + /// Returns `(public_key, true)` if `signature` verifies on `message` under the recovered `public_key` /// and returns `([], false)` otherwise. native fun recover_public_key_internal( - recovery_id: u8, message: vector, signature: vector, compressed: bool, + recovery_id: u8, + message: vector, + signature: vector, + compressed: bool ): (vector, bool); #[test_only] @@ -173,6 +202,29 @@ module initia_std::secp256k1 { // Tests // + #[test] + fun test_secp256k1_sign_verify() { + use std::hash; + + let (sk, vk) = generate_keys(true); + let pk = ecdsa_compressed_public_key_from_bytes(vk); + + let msg: vector = hash::sha2_256(b"test initia secp256k1"); + let (_rid, sig_bytes) = sign(msg, sk); + let sig = ecdsa_signature_from_bytes(sig_bytes); + assert!(verify(msg, &pk, &sig), 1); + + // Test with an incorrect message + let wrong_msg: vector = hash::sha2_256(b"wrong message"); + assert!(!verify(wrong_msg, &pk, &sig), 2); + + // Test with an incorrect signature + let invalid_sig_bytes = sig_bytes; + *std::vector::borrow_mut(&mut invalid_sig_bytes, 0) = 0xFF; // Corrupt the signature + let invalid_sig = ecdsa_signature_from_bytes(invalid_sig_bytes); + assert!(!verify(msg, &pk, &invalid_sig), 3); + } + #[test] fun test_gen_sign_recover() { use std::hash; @@ -187,7 +239,7 @@ module initia_std::secp256k1 { assert!(std::option::is_some(&recovered_pk), 1); assert!( std::option::extract(&mut recovered_pk).bytes == pk.bytes, - 2, + 2 ); let wrong_msg: vector = hash::sha2_256(b"test initia"); @@ -195,7 +247,7 @@ module initia_std::secp256k1 { assert!(std::option::is_some(&recovered_pk), 3); assert!( std::option::extract(&mut recovered_pk).bytes != pk.bytes, - 4, + 4 ); } @@ -213,7 +265,7 @@ module initia_std::secp256k1 { assert!(std::option::is_some(&recovered_pk), 1); assert!( std::option::extract(&mut recovered_pk).bytes == pk.bytes, - 2, + 2 ); let wrong_msg: vector = hash::sha2_256(b"test initia"); @@ -221,7 +273,7 @@ module initia_std::secp256k1 { assert!(std::option::is_some(&recovered_pk), 3); assert!( std::option::extract(&mut recovered_pk).bytes != pk.bytes, - 4, + 4 ); } } diff --git a/initia_stdlib/sources/debug.move b/initia_stdlib/sources/debug.move index 3a0c6aa..d829fdf 100644 --- a/initia_stdlib/sources/debug.move +++ b/initia_stdlib/sources/debug.move @@ -38,7 +38,7 @@ module initia_std::debug { #[test_only] struct GenericStruct has drop { - val: u64, + val: u64 } #[test_only] @@ -54,7 +54,7 @@ module initia_std::debug { number: u8, bytes: vector, name: String, - vec: vector, + vec: vector } #[test_only] @@ -70,7 +70,7 @@ module initia_std::debug { fun assert_string_equal(x: vector, expected: vector) { assert!( std::string::bytes(&format(&std::string::utf8(x))) == &expected, - 1, + 1 ); } @@ -88,19 +88,19 @@ module initia_std::debug { let foo = Foo {}; assert_equal( &foo, - b"0x1::debug::Foo {\n dummy_field: false\n}", + b"0x1::debug::Foo {\n dummy_field: false\n}" ); let bar = Bar { x: 404, y: Foo {}, z: true }; assert_equal( &bar, - b"0x1::debug::Bar {\n x: 404,\n y: 0x1::debug::Foo {\n dummy_field: false\n },\n z: true\n}", + b"0x1::debug::Bar {\n x: 404,\n y: 0x1::debug::Foo {\n dummy_field: false\n },\n z: true\n}" ); let box = Box { x: Foo {} }; assert_equal( &box, - b"0x1::debug::Box<0x1::debug::Foo> {\n x: 0x1::debug::Foo {\n dummy_field: false\n }\n}", + b"0x1::debug::Box<0x1::debug::Foo> {\n x: 0x1::debug::Foo {\n dummy_field: false\n }\n}" ); } @@ -110,7 +110,7 @@ module initia_std::debug { assert_equal( &str_bytes, - b"0x48656c6c6f2c2073616e65204d6f766520646562756767696e6721", + b"0x48656c6c6f2c2073616e65204d6f766520646562756767696e6721" ); let str = std::string::utf8(str_bytes); @@ -142,15 +142,14 @@ module initia_std::debug { let u128 = 340282366920938463463374607431768211455u128; assert_equal( &u128, - b"340282366920938463463374607431768211455", + b"340282366920938463463374607431768211455" ); let u256 = - - 115792089237316195423570985008687907853269984665640564039457584007913129639935u256; + 115792089237316195423570985008687907853269984665640564039457584007913129639935u256; assert_equal( &u256, - b"115792089237316195423570985008687907853269984665640564039457584007913129639935", + b"115792089237316195423570985008687907853269984665640564039457584007913129639935" ); let bool = false; @@ -174,19 +173,23 @@ module initia_std::debug { let obj = TestInner { val: 100, vec: vector[200u128, 400u128], - msgs: vector[MSG_1, MSG_2], + msgs: vector[MSG_1, MSG_2] }; assert_equal( &obj, - b"0x1::debug::TestInner {\n val: 100,\n vec: [ 200, 400 ],\n msgs: [\n 0x616263646566,\n 0x313233343536\n ]\n}", + b"0x1::debug::TestInner {\n val: 100,\n vec: [ 200, 400 ],\n msgs: [\n 0x616263646566,\n 0x313233343536\n ]\n}" ); - let obj = TestInner { val: 10, vec: vector[], msgs: vector[], }; + let obj = TestInner { + val: 10, + vec: vector[], + msgs: vector[] + }; assert_equal( &obj, - b"0x1::debug::TestInner {\n val: 10,\n vec: [],\n msgs: []\n}", + b"0x1::debug::TestInner {\n val: 10,\n vec: [],\n msgs: []\n}" ); } @@ -219,19 +222,24 @@ module initia_std::debug { let v_signer = vector[s1, s2]; assert_equal( &v_signer, - b"[ signer(@0x123), signer(@0x456) ]", + b"[ signer(@0x123), signer(@0x456) ]" ); let v = vector[ TestInner { val: 4u128, vec: vector[127u128, 128u128], - msgs: vector[x"00ff", x"abcd"], + msgs: vector[x"00ff", x"abcd"] }, - TestInner { val: 8u128, vec: vector[128u128, 129u128], msgs: vector[x"0000"], }]; + TestInner { + val: 8u128, + vec: vector[128u128, 129u128], + msgs: vector[x"0000"] + } + ]; assert_equal( &v, - b"[\n 0x1::debug::TestInner {\n val: 4,\n vec: [ 127, 128 ],\n msgs: [\n 0x00ff,\n 0xabcd\n ]\n },\n 0x1::debug::TestInner {\n val: 8,\n vec: [ 128, 129 ],\n msgs: [\n 0x0000\n ]\n }\n]", + b"[\n 0x1::debug::TestInner {\n val: 4,\n vec: [ 127, 128 ],\n msgs: [\n 0x00ff,\n 0xabcd\n ]\n },\n 0x1::debug::TestInner {\n val: 8,\n vec: [ 128, 129 ],\n msgs: [\n 0x0000\n ]\n }\n]" ); } @@ -252,43 +260,62 @@ module initia_std::debug { let v_u128 = vector[vector[128u128, 129u128], vector[130u128, 131u128]]; assert_equal( &v_u128, - b"[\n [ 128, 129 ],\n [ 130, 131 ]\n]", + b"[\n [ 128, 129 ],\n [ 130, 131 ]\n]" ); let v_u256 = vector[vector[256u256, 257u256], vector[258u256, 259u256]]; assert_equal( &v_u256, - b"[\n [ 256, 257 ],\n [ 258, 259 ]\n]", + b"[\n [ 256, 257 ],\n [ 258, 259 ]\n]" ); let v_bool = vector[vector[true, false], vector[false, true]]; assert_equal( &v_bool, - b"[\n [ true, false ],\n [ false, true ]\n]", + b"[\n [ true, false ],\n [ false, true ]\n]" ); let v_addr = vector[vector[@0x1234, @0x5678], vector[@0xabcdef, @0x9999]]; assert_equal( &v_addr, - b"[\n [ @0x1234, @0x5678 ],\n [ @0xabcdef, @0x9999 ]\n]", + b"[\n [ @0x1234, @0x5678 ],\n [ @0xabcdef, @0x9999 ]\n]" ); let v_signer = vector[vector[s1], vector[s2]]; assert_equal( &v_signer, - b"[\n [ signer(@0x123) ],\n [ signer(@0x456) ]\n]", + b"[\n [ signer(@0x123) ],\n [ signer(@0x456) ]\n]" ); let v = vector[ vector[ - TestInner { val: 4u128, vec: vector[127u128, 128u128], msgs: vector[] }, - TestInner { val: 8u128, vec: vector[128u128, 129u128], msgs: vector[] }], + TestInner { + val: 4u128, + vec: vector[127u128, 128u128], + msgs: vector[] + }, + TestInner { + val: 8u128, + vec: vector[128u128, 129u128], + msgs: vector[] + } + ], vector[ - TestInner { val: 4u128, vec: vector[127u128, 128u128], msgs: vector[] }, - TestInner { val: 8u128, vec: vector[128u128, 129u128], msgs: vector[] }]]; + TestInner { + val: 4u128, + vec: vector[127u128, 128u128], + msgs: vector[] + }, + TestInner { + val: 8u128, + vec: vector[128u128, 129u128], + msgs: vector[] + } + ] + ]; assert_equal( &v, - b"[\n [\n 0x1::debug::TestInner {\n val: 4,\n vec: [ 127, 128 ],\n msgs: []\n },\n 0x1::debug::TestInner {\n val: 8,\n vec: [ 128, 129 ],\n msgs: []\n }\n ],\n [\n 0x1::debug::TestInner {\n val: 4,\n vec: [ 127, 128 ],\n msgs: []\n },\n 0x1::debug::TestInner {\n val: 8,\n vec: [ 128, 129 ],\n msgs: []\n }\n ]\n]", + b"[\n [\n 0x1::debug::TestInner {\n val: 4,\n vec: [ 127, 128 ],\n msgs: []\n },\n 0x1::debug::TestInner {\n val: 8,\n vec: [ 128, 129 ],\n msgs: []\n }\n ],\n [\n 0x1::debug::TestInner {\n val: 4,\n vec: [ 127, 128 ],\n msgs: []\n },\n 0x1::debug::TestInner {\n val: 8,\n vec: [ 128, 129 ],\n msgs: []\n }\n ]\n]" ); } @@ -300,23 +327,32 @@ module initia_std::debug { bytes: x"c0ffee", name: std::string::utf8(b"He\"llo"), vec: vector[ - TestInner { val: 1, vec: vector[130u128, 131u128], msgs: vector[] }, - TestInner { val: 2, vec: vector[132u128, 133u128], msgs: vector[] }], + TestInner { + val: 1, + vec: vector[130u128, 131u128], + msgs: vector[] + }, + TestInner { + val: 2, + vec: vector[132u128, 133u128], + msgs: vector[] + } + ] }; assert_equal( &obj, - b"0x1::debug::TestStruct {\n addr: @0x1,\n number: 255,\n bytes: 0xc0ffee,\n name: \"He\\\"llo\",\n vec: [\n 0x1::debug::TestInner {\n val: 1,\n vec: [ 130, 131 ],\n msgs: []\n },\n 0x1::debug::TestInner {\n val: 2,\n vec: [ 132, 133 ],\n msgs: []\n }\n ]\n}", + b"0x1::debug::TestStruct {\n addr: @0x1,\n number: 255,\n bytes: 0xc0ffee,\n name: \"He\\\"llo\",\n vec: [\n 0x1::debug::TestInner {\n val: 1,\n vec: [ 130, 131 ],\n msgs: []\n },\n 0x1::debug::TestInner {\n val: 2,\n vec: [ 132, 133 ],\n msgs: []\n }\n ]\n}" ); } #[test] fun test_print_generic_struct() { - let obj = GenericStruct { val: 60u64, }; + let obj = GenericStruct { val: 60u64 }; assert_equal( &obj, - b"0x1::debug::GenericStruct<0x1::debug::Foo> {\n val: 60\n}", + b"0x1::debug::GenericStruct<0x1::debug::Foo> {\n val: 60\n}" ); } } diff --git a/initia_stdlib/sources/decimal128.move b/initia_stdlib/sources/decimal128.move deleted file mode 100644 index fa1cb5a..0000000 --- a/initia_stdlib/sources/decimal128.move +++ /dev/null @@ -1,671 +0,0 @@ -module initia_std::decimal128 { - use std::string::{Self, String}; - use std::vector; - use std::error; - - const EDIV_WITH_ZERO: u64 = 0; - const EFAILED_TO_DESERIALIZE: u64 = 1; - const EOUT_OF_RANGE: u64 = 2; - - const DECIMAL_FRACTIONAL: u128 = 1000000000000000000; - const FRACTIONAL_LENGTH: u64 = 18; - - // const MAX_U128: u128 = 340282366920938463463374607431768211455; - const MAX_INTEGER_PART: u128 = 340282366920938463463; - - /// A fixed-point decimal value with 18 fractional digits, i.e. Decimal128{ val: 1_000_000_000_000_000_000 } == 1.0 - struct Decimal128 has copy, drop, store { - val: u128 - } - - public fun new(val: u128): Decimal128 { - Decimal128 { val } - } - - public fun new_u64(val: u64): Decimal128 { - Decimal128 { val: (val as u128) } - } - - public fun one(): Decimal128 { - Decimal128 { val: DECIMAL_FRACTIONAL } - } - - public fun zero(): Decimal128 { - Decimal128 { val: 0 } - } - - public fun from_ratio_u64(numerator: u64, denominator: u64): Decimal128 { - assert!(denominator != 0, EDIV_WITH_ZERO); - - new( - (numerator as u128) * DECIMAL_FRACTIONAL / (denominator as u128), - ) - } - - public fun from_ratio(numerator: u128, denominator: u128): Decimal128 { - assert!(denominator != 0, EDIV_WITH_ZERO); - - new(numerator * DECIMAL_FRACTIONAL / denominator) - } - - public fun add(left: &Decimal128, right: &Decimal128): Decimal128 { - new(left.val + right.val) - } - - public fun sub(left: &Decimal128, right: &Decimal128): Decimal128 { - new(left.val - right.val) - } - - public fun mul_u64(decimal: &Decimal128, val: u64): u64 { - ((decimal.val as u256) * (val as u256) / (DECIMAL_FRACTIONAL as u256) as u64) - } - - public fun mul_u64_with_round_up(decimal: &Decimal128, val: u64): u64 { - let val = (decimal.val as u256) * (val as u256); - let val = val + (DECIMAL_FRACTIONAL as u256) / 2; - (val / (DECIMAL_FRACTIONAL as u256) as u64) - } - - public fun mul_u64_with_ceil(decimal: &Decimal128, val: u64): u64 { - let val = (decimal.val as u256) * (val as u256); - let val = val + (DECIMAL_FRACTIONAL as u256) - 1; - (val / (DECIMAL_FRACTIONAL as u256) as u64) - } - - public fun mul_u128(decimal: &Decimal128, val: u128): u128 { - ((decimal.val as u256) * (val as u256) / (DECIMAL_FRACTIONAL as u256) as u128) - } - - public fun mul_u128_with_round_up(decimal: &Decimal128, val: u128): u128 { - let val = (decimal.val as u256) * (val as u256); - let val = val + (DECIMAL_FRACTIONAL as u256) / 2; - (val / (DECIMAL_FRACTIONAL as u256) as u128) - } - - public fun mul_u128_with_ceil(decimal: &Decimal128, val: u128): u128 { - let val = (decimal.val as u256) * (val as u256); - let val = val + (DECIMAL_FRACTIONAL as u256) - 1; - (val / (DECIMAL_FRACTIONAL as u256) as u128) - } - - public fun mul(a: &Decimal128, b: &Decimal128): Decimal128 { - new( - ((a.val as u256) * (b.val as u256) / (DECIMAL_FRACTIONAL as u256) as u128), - ) - } - - public fun div_u64(decimal: &Decimal128, val: u64): Decimal128 { - assert!(val != 0, EDIV_WITH_ZERO); - new(decimal.val / (val as u128)) - } - - public fun div(decimal: &Decimal128, val: u128): Decimal128 { - assert!(val != 0, EDIV_WITH_ZERO); - new(decimal.val / val) - } - - public fun val(decimal: &Decimal128): u128 { - decimal.val - } - - public fun round_up_u64(decimal: &Decimal128): u64 { - let val = decimal.val + DECIMAL_FRACTIONAL / 2; - (val / DECIMAL_FRACTIONAL as u64) - } - - public fun round_up_u128(decimal: &Decimal128): u128 { - let val = decimal.val + DECIMAL_FRACTIONAL / 2; - (val / DECIMAL_FRACTIONAL as u128) - } - - public fun ceil_u64(decimal: &Decimal128): u64 { - let val = decimal.val + DECIMAL_FRACTIONAL - 1; - (val / DECIMAL_FRACTIONAL as u64) - } - - public fun ceil_u128(decimal: &Decimal128): u128 { - let val = decimal.val + DECIMAL_FRACTIONAL - 1; - val / DECIMAL_FRACTIONAL - } - - public fun is_same(left: &Decimal128, right: &Decimal128): bool { - left.val == right.val - } - - public fun from_string(num: &String): Decimal128 { - let vec = string::bytes(num); - let len = vector::length(vec); - - let cursor = 0; - let dot_index = 0; - - let int_part = 0; - let frac_part = 0; - - while (cursor < len) { - let s = *vector::borrow(vec, cursor); - cursor = cursor + 1; - - // find `.` position - if (s == 46) break; - - int_part = int_part * 10; - assert!( - s >= 48 && s <= 57, - error::invalid_argument(EFAILED_TO_DESERIALIZE), - ); - - let n = (s - 48 as u128); - int_part = int_part + n; - assert!( - int_part < MAX_INTEGER_PART, - error::invalid_argument(EOUT_OF_RANGE), - ); - dot_index = dot_index + 1; - }; - - while (cursor < len) { - let s = *vector::borrow(vec, cursor); - cursor = cursor + 1; - - frac_part = frac_part * 10; - assert!( - s >= 48 && s <= 57, - error::invalid_argument(EFAILED_TO_DESERIALIZE), - ); - - let n = (s - 48 as u128); - frac_part = frac_part + n; - assert!( - frac_part < MAX_INTEGER_PART, - error::invalid_argument(EOUT_OF_RANGE), - ); - }; - - // ignore fractional part longer than `FRACTIONAL_LENGTH` - let frac_part_val = - if (dot_index == len) { 0 } - else { - let fractional_length = len - dot_index - 1; - if (fractional_length > FRACTIONAL_LENGTH) { - frac_part / pow( - 10, - fractional_length - FRACTIONAL_LENGTH, - ) - } else { - frac_part * pow( - 10, - FRACTIONAL_LENGTH - fractional_length, - ) - } - }; - - new(int_part * DECIMAL_FRACTIONAL + frac_part_val) - } - - fun pow(num: u128, pow_amount: u64): u128 { - let index = 0; - let val = 1; - while (index < pow_amount) { - val = val * num; - index = index + 1; - }; - - val - } - - #[test] - fun test() { - assert!( - from_string(&string::utf8(b"1234.5678")) == new(1234567800000000000000), - 0, - ); - assert!( - from_string(&string::utf8(b"340282366920938463462")) - == new(340282366920938463462 * DECIMAL_FRACTIONAL), - 0, - ); - assert!( - from_string(&string::utf8(b"340282366920938463462.0")) - == new(340282366920938463462 * DECIMAL_FRACTIONAL), - 0, - ); - - let max_a = from_ratio(10000, 1); - let result = mul(&max_a, &from_ratio(34028236692093, 1)); - assert!( - result == from_ratio(340282366920930000, 1), - 0, - ); - } - - #[test] - fun test_round_up() { - // u64 - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u128 - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u64 - assert!( - round_up_u64(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.1"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.2"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.3"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.4"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - - // u128 - assert!( - round_up_u128(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.1"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.2"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.3"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.4"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - } - - #[test] - fun test_ceil() { - // u64 - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u128 - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u64 - assert!( - ceil_u64(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.1"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.2"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.3"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.4"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - - // u128 - assert!( - ceil_u128(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.1"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.2"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.3"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.4"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - } - - #[test] - #[expected_failure(abort_code = 0x10001, location = Self)] - fun multible_dots() { - from_string(&string::utf8(b".1.1.")); - } - - #[test] - #[expected_failure(abort_code = 0x10002, location = Self)] - fun failed_out_of_range() { - _ = from_string(&string::utf8(b"340282366920938463463.0")); - } -} diff --git a/initia_stdlib/sources/decimal256.move b/initia_stdlib/sources/decimal256.move deleted file mode 100644 index e68f232..0000000 --- a/initia_stdlib/sources/decimal256.move +++ /dev/null @@ -1,928 +0,0 @@ -module initia_std::decimal256 { - use std::string::{Self, String}; - use std::vector; - use std::error; - - const EDIV_WITH_ZERO: u64 = 0; - const EFAILED_TO_DESERIALIZE: u64 = 1; - const EOUT_OF_RANGE: u64 = 2; - - const DECIMAL_FRACTIONAL: u256 = 1000000000000000000; - const FRACTIONAL_LENGTH: u64 = 18; - - // const MAX_U256: u256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935; - const MAX_INTEGER_PART: u256 = - 115792089237316195423570985008687907853269984665640564039457; - - /// A fixed-point decimal value with 18 fractional digits, i.e. Decimal256{ val: 1_000_000_000_000_000_000 } == 1.0 - struct Decimal256 has copy, drop, store { - val: u256 - } - - public fun new(val: u256): Decimal256 { - Decimal256 { val } - } - - public fun new_u64(val: u64): Decimal256 { - Decimal256 { val: (val as u256) } - } - - public fun new_u128(val: u128): Decimal256 { - Decimal256 { val: (val as u256) } - } - - public fun one(): Decimal256 { - Decimal256 { val: DECIMAL_FRACTIONAL } - } - - public fun zero(): Decimal256 { - Decimal256 { val: 0 } - } - - public fun from_ratio_u64(numerator: u64, denominator: u64): Decimal256 { - assert!(denominator != 0, EDIV_WITH_ZERO); - - new( - (numerator as u256) * DECIMAL_FRACTIONAL / (denominator as u256), - ) - } - - public fun from_ratio_u128(numerator: u128, denominator: u128): Decimal256 { - assert!(denominator != 0, EDIV_WITH_ZERO); - - new( - (numerator as u256) * DECIMAL_FRACTIONAL / (denominator as u256), - ) - } - - public fun from_ratio(numerator: u256, denominator: u256): Decimal256 { - assert!(denominator != 0, EDIV_WITH_ZERO); - - new(numerator * DECIMAL_FRACTIONAL / denominator) - } - - public fun add(left: &Decimal256, right: &Decimal256): Decimal256 { - new(left.val + right.val) - } - - public fun sub(left: &Decimal256, right: &Decimal256): Decimal256 { - new(left.val - right.val) - } - - public fun mul_u64(decimal: &Decimal256, val: u64): u64 { - (decimal.val * (val as u256) / DECIMAL_FRACTIONAL as u64) - } - - public fun mul_u64_with_round_up(decimal: &Decimal256, val: u64): u64 { - let val = decimal.val * (val as u256); - let val = val + DECIMAL_FRACTIONAL / 2; - (val / DECIMAL_FRACTIONAL as u64) - } - - public fun mul_u64_with_ceil(decimal: &Decimal256, val: u64): u64 { - let val = decimal.val * (val as u256); - let val = val + DECIMAL_FRACTIONAL - 1; - (val / DECIMAL_FRACTIONAL as u64) - } - - public fun mul_u128(decimal: &Decimal256, val: u128): u128 { - (decimal.val * (val as u256) / DECIMAL_FRACTIONAL as u128) - } - - public fun mul_u128_with_round_up(decimal: &Decimal256, val: u128): u128 { - let val = decimal.val * (val as u256); - let val = val + DECIMAL_FRACTIONAL / 2; - (val / DECIMAL_FRACTIONAL as u128) - } - - public fun mul_u128_with_ceil(decimal: &Decimal256, val: u128): u128 { - let val = decimal.val * (val as u256); - let val = val + DECIMAL_FRACTIONAL - 1; - (val / DECIMAL_FRACTIONAL as u128) - } - - public fun mul_u256(decimal: &Decimal256, val: u256): u256 { - decimal.val * val / DECIMAL_FRACTIONAL - } - - public fun mul_u256_with_round_up(decimal: &Decimal256, val: u256): u256 { - let val = decimal.val * val; - let val = val + DECIMAL_FRACTIONAL / 2; - val / DECIMAL_FRACTIONAL - } - - public fun mul_u256_with_ceil(decimal: &Decimal256, val: u256): u256 { - let val = decimal.val * val; - let val = val + DECIMAL_FRACTIONAL - 1; - val / DECIMAL_FRACTIONAL - } - - public fun mul(a: &Decimal256, b: &Decimal256): Decimal256 { - new(a.val * b.val / DECIMAL_FRACTIONAL) - } - - public fun div_u64(decimal: &Decimal256, val: u64): Decimal256 { - assert!(val != 0, EDIV_WITH_ZERO); - new(decimal.val / (val as u256)) - } - - public fun div_u128(decimal: &Decimal256, val: u128): Decimal256 { - assert!(val != 0, EDIV_WITH_ZERO); - new(decimal.val / (val as u256)) - } - - public fun div(decimal: &Decimal256, val: u256): Decimal256 { - assert!(val != 0, EDIV_WITH_ZERO); - new(decimal.val / val) - } - - public fun val(decimal: &Decimal256): u256 { - decimal.val - } - - public fun round_up_u64(decimal: &Decimal256): u64 { - let val = decimal.val + DECIMAL_FRACTIONAL / 2; - (val / DECIMAL_FRACTIONAL as u64) - } - - public fun round_up_u128(decimal: &Decimal256): u128 { - let val = decimal.val + DECIMAL_FRACTIONAL / 2; - (val / DECIMAL_FRACTIONAL as u128) - } - - public fun round_up_u256(decimal: &Decimal256): u256 { - let val = decimal.val + DECIMAL_FRACTIONAL / 2; - (val / DECIMAL_FRACTIONAL as u256) - } - - public fun ceil_u64(decimal: &Decimal256): u64 { - let val = decimal.val + DECIMAL_FRACTIONAL - 1; - (val / DECIMAL_FRACTIONAL as u64) - } - - public fun ceil_u128(decimal: &Decimal256): u128 { - let val = decimal.val + DECIMAL_FRACTIONAL - 1; - (val / DECIMAL_FRACTIONAL as u128) - } - - public fun ceil_u256(decimal: &Decimal256): u256 { - let val = decimal.val + DECIMAL_FRACTIONAL - 1; - val / DECIMAL_FRACTIONAL - } - - public fun is_same(left: &Decimal256, right: &Decimal256): bool { - left.val == right.val - } - - public fun from_string(num: &String): Decimal256 { - let vec = string::bytes(num); - let len = vector::length(vec); - - let cursor = 0; - let dot_index = 0; - - let int_part = 0; - let frac_part = 0; - - while (cursor < len) { - let s = *vector::borrow(vec, cursor); - cursor = cursor + 1; - - // find `.` position - if (s == 46) break; - - int_part = int_part * 10; - assert!( - s >= 48 && s <= 57, - error::invalid_argument(EFAILED_TO_DESERIALIZE), - ); - - let n = (s - 48 as u256); - int_part = int_part + n; - assert!( - int_part < MAX_INTEGER_PART, - error::invalid_argument(EOUT_OF_RANGE), - ); - dot_index = dot_index + 1; - }; - - while (cursor < len) { - let s = *vector::borrow(vec, cursor); - cursor = cursor + 1; - - frac_part = frac_part * 10; - assert!( - s >= 48 && s <= 57, - error::invalid_argument(EFAILED_TO_DESERIALIZE), - ); - - let n = (s - 48 as u256); - frac_part = frac_part + n; - assert!( - frac_part < MAX_INTEGER_PART, - error::invalid_argument(EOUT_OF_RANGE), - ); - }; - - // ignore fractional part longer than `FRACTIONAL_LENGTH` - let frac_part_val = - if (dot_index == len) { 0 } - else { - let fractional_length = len - dot_index - 1; - if (fractional_length > FRACTIONAL_LENGTH) { - frac_part / pow( - 10, - fractional_length - FRACTIONAL_LENGTH, - ) - } else { - frac_part * pow( - 10, - FRACTIONAL_LENGTH - fractional_length, - ) - } - }; - - new(int_part * DECIMAL_FRACTIONAL + frac_part_val) - } - - fun pow(num: u256, pow_amount: u64): u256 { - let index = 0; - let val = 1; - while (index < pow_amount) { - val = val * num; - index = index + 1; - }; - - val - } - - #[test] - fun test() { - assert!( - from_string(&string::utf8(b"1234.5678")) == new(1234567800000000000000), - 0, - ); - assert!( - from_string( - &string::utf8( - b"115792089237316195423570985008687907853269984665640564039456" - ), - ) == new( - 115792089237316195423570985008687907853269984665640564039456 - * DECIMAL_FRACTIONAL, - ), - 0, - ); - assert!( - from_string( - &string::utf8( - b"115792089237316195423570985008687907853269984665640564039456.0" - ), - ) == new( - 115792089237316195423570985008687907853269984665640564039456 - * DECIMAL_FRACTIONAL, - ), - 0, - ); - } - - #[test] - fun test_round_up() { - // u64 - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u128 - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u256 - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u64 - assert!( - round_up_u64(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.1"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.2"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.3"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.4"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - - // u128 - assert!( - round_up_u128(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.1"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.2"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.3"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.4"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - - // u256 - assert!( - round_up_u256(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.1"))) == 200, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.2"))) == 200, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.3"))) == 200, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.4"))) == 200, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - } - - #[test] - fun test_ceil() { - // u64 - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u128 - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u256 - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u64 - assert!( - ceil_u64(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.1"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.2"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.3"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.4"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - - // u128 - assert!( - ceil_u128(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.1"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.2"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.3"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.4"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - - // u256 - assert!( - ceil_u256(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.1"))) == 201, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.2"))) == 201, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.3"))) == 201, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.4"))) == 201, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - } - - #[test] - #[expected_failure(abort_code = 0x10001, location = Self)] - fun multible_dots() { - from_string(&string::utf8(b".1.1.")); - } - - #[test] - #[expected_failure(abort_code = 0x10002, location = Self)] - fun failed_out_of_range() { - _ = from_string( - &string::utf8( - b"115792089237316195423570985008687907853269984665640564039457.0" - ), - ); - } -} diff --git a/initia_stdlib/sources/dex.move b/initia_stdlib/sources/dex.move index 7ab8361..2910bed 100644 --- a/initia_stdlib/sources/dex.move +++ b/initia_stdlib/sources/dex.move @@ -9,39 +9,40 @@ module initia_std::dex { use initia_std::block::get_block_info; use initia_std::fungible_asset::{Self, Metadata, FungibleAsset, FungibleStore}; use initia_std::primary_fungible_store; - use initia_std::decimal128::{Self, Decimal128}; use initia_std::string::{Self, String}; use initia_std::table::{Self, Table}; use initia_std::coin; + use initia_std::bigdecimal::{Self, BigDecimal}; + use initia_std::biguint; /// Pool configuration struct Config has key { extend_ref: ExtendRef, weights: Weights, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal } struct Pool has key { coin_a_store: Object, - coin_b_store: Object, + coin_b_store: Object } struct Weights has copy, drop, store { weights_before: Weight, - weights_after: Weight, + weights_after: Weight } struct Weight has copy, drop, store { - coin_a_weight: Decimal128, - coin_b_weight: Decimal128, - timestamp: u64, + coin_a_weight: BigDecimal, + coin_b_weight: BigDecimal, + timestamp: u64 } /// Key for pair struct PairKey has copy, drop { coin_a: address, coin_b: address, - liquidity_token: address, + liquidity_token: address } struct PairResponse has copy, drop, store { @@ -49,7 +50,7 @@ module initia_std::dex { coin_b: address, liquidity_token: address, weights: Weights, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal } struct PairByDenomResponse has copy, drop, store { @@ -57,14 +58,14 @@ module initia_std::dex { coin_b: String, liquidity_token: String, weights: Weights, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal } /// Coin capabilities struct CoinCapabilities has key { burn_cap: coin::BurnCapability, freeze_cap: coin::FreezeCapability, - mint_cap: coin::MintCapability, + mint_cap: coin::MintCapability } #[event] @@ -75,7 +76,7 @@ module initia_std::dex { liquidity_token: address, coin_a_amount: u64, coin_b_amount: u64, - liquidity: u64, + liquidity: u64 } #[event] @@ -86,7 +87,7 @@ module initia_std::dex { liquidity_token: address, coin_a_amount: u64, coin_b_amount: u64, - liquidity: u64, + liquidity: u64 } #[event] @@ -97,7 +98,7 @@ module initia_std::dex { liquidity_token: address, offer_amount: u64, return_amount: u64, - fee_amount: u64, + fee_amount: u64 } #[event] @@ -108,33 +109,33 @@ module initia_std::dex { provide_coin: address, provide_amount: u64, fee_amount: u64, - liquidity: u64, + liquidity: u64 } struct PoolInfoResponse has drop { coin_a_amount: u64, coin_b_amount: u64, - total_share: u128, + total_share: u128 } struct ConfigResponse has drop { weights: Weights, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal } struct CurrentWeightResponse has drop { - coin_a_weight: Decimal128, - coin_b_weight: Decimal128, + coin_a_weight: BigDecimal, + coin_b_weight: BigDecimal } struct PairMetadataResponse has drop { coin_a_metadata: Object, - coin_b_metadata: Object, + coin_b_metadata: Object } struct PairDenomResponse has drop { coin_a_denom: String, - coin_b_denom: String, + coin_b_denom: String } #[event] @@ -143,7 +144,7 @@ module initia_std::dex { coin_b: address, liquidity_token: address, weights: Weights, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal } #[event] @@ -151,13 +152,13 @@ module initia_std::dex { coin_a: address, coin_b: address, liquidity_token: address, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal } /// Module store for storing pair infos struct ModuleStore has key { pairs: Table, - pair_count: u64, + pair_count: u64 } // Errors @@ -210,31 +211,32 @@ module initia_std::dex { /// Zero amount in the swap simulation is not allowed const EZERO_AMOUNT_IN: u64 = 20; + /// Weights sum must be 1.0 + const EINVALID_WEIGHTS: u64 = 21; + // Constants const MAX_LIMIT: u8 = 30; // TODO - find the resonable percision /// Result Precision of `pow` and `ln` function - const PRECISION: u128 = 100000; - - const MAX_FEE_RATE: u128 = 50_000_000_000_000_000; // 5% + const PRECISION: u64 = 100000; #[view] - public fun get_pair_metadata(pair: Object,): PairMetadataResponse acquires Pool { + public fun get_pair_metadata(pair: Object): PairMetadataResponse acquires Pool { let pool = borrow_global_mut(object::object_address(&pair)); let coin_a_metadata = fungible_asset::store_metadata(pool.coin_a_store); let coin_b_metadata = fungible_asset::store_metadata(pool.coin_b_store); - PairMetadataResponse { coin_a_metadata, coin_b_metadata, } + PairMetadataResponse { coin_a_metadata, coin_b_metadata } } #[view] - public fun get_pair_denom(pair: Object,): PairDenomResponse acquires Pool { + public fun get_pair_denom(pair: Object): PairDenomResponse acquires Pool { let pair_metadata = get_pair_metadata(pair); PairDenomResponse { coin_a_denom: coin::metadata_to_denom(pair_metadata.coin_a_metadata), - coin_b_denom: coin::metadata_to_denom(pair_metadata.coin_b_metadata), + coin_b_denom: coin::metadata_to_denom(pair_metadata.coin_b_metadata) } } @@ -242,8 +244,8 @@ module initia_std::dex { /// Calculate spot price /// https://balancer.fi/whitepaper.pdf (2) public fun get_spot_price( - pair: Object, base_coin: Object, - ): Decimal128 acquires Config, Pool { + pair: Object, base_coin: Object + ): BigDecimal acquires Config, Pool { let (coin_a_pool, coin_b_pool, coin_a_weight, coin_b_weight, _) = pool_info(pair, false); @@ -251,7 +253,7 @@ module initia_std::dex { let base_addr = object::object_address(&base_coin); assert!( base_addr == pair_key.coin_a || base_addr == pair_key.coin_b, - error::invalid_argument(ECOIN_TYPE), + error::invalid_argument(ECOIN_TYPE) ); let is_base_a = base_addr == pair_key.coin_a; let (base_pool, quote_pool, base_weight, quote_weight) = @@ -261,16 +263,16 @@ module initia_std::dex { (coin_b_pool, coin_a_pool, coin_b_weight, coin_a_weight) }; - decimal128::from_ratio_u64( - decimal128::mul_u64(&base_weight, quote_pool), - decimal128::mul_u64("e_weight, base_pool), + bigdecimal::div( + bigdecimal::mul_by_u64(base_weight, quote_pool), + bigdecimal::mul_by_u64(quote_weight, base_pool) ) } #[view] public fun get_spot_price_by_denom( - pair_denom: String, base_coin: String, - ): Decimal128 acquires Config, Pool { + pair_denom: String, base_coin: String + ): BigDecimal acquires Config, Pool { let pair_metadata = coin::denom_to_metadata(pair_denom); let base_metadata = coin::denom_to_metadata(base_coin); get_spot_price(object::convert(pair_metadata), base_metadata) @@ -279,15 +281,13 @@ module initia_std::dex { #[view] /// Return swap simulation result public fun get_swap_simulation( - pair: Object, - offer_metadata: Object, - offer_amount: u64, + pair: Object, offer_metadata: Object, offer_amount: u64 ): u64 acquires Config, Pool { let pair_key = generate_pair_key(pair); let offer_address = object::object_address(&offer_metadata); assert!( offer_address == pair_key.coin_a || offer_address == pair_key.coin_b, - error::invalid_argument(ECOIN_TYPE), + error::invalid_argument(ECOIN_TYPE) ); let is_offer_a = offer_address == pair_key.coin_a; let (pool_a, pool_b, weight_a, weight_b, swap_fee_rate) = pool_info(pair, true); @@ -304,7 +304,7 @@ module initia_std::dex { offer_weight, return_weight, offer_amount, - swap_fee_rate, + swap_fee_rate ); return_amount @@ -312,31 +312,27 @@ module initia_std::dex { #[view] public fun get_swap_simulation_by_denom( - pair_denom: String, - offer_denom: String, - offer_amount: u64, + pair_denom: String, offer_denom: String, offer_amount: u64 ): u64 acquires Config, Pool { let pair_metadata = coin::denom_to_metadata(pair_denom); let offer_metadata = coin::denom_to_metadata(offer_denom); get_swap_simulation( object::convert(pair_metadata), offer_metadata, - offer_amount, + offer_amount ) } #[view] /// Return swap simulation result public fun get_swap_simulation_given_out( - pair: Object, - offer_metadata: Object, - return_amount: u64, + pair: Object, offer_metadata: Object, return_amount: u64 ): u64 acquires Config, Pool { let pair_key = generate_pair_key(pair); let offer_address = object::object_address(&offer_metadata); assert!( offer_address == pair_key.coin_a || offer_address == pair_key.coin_b, - error::invalid_argument(ECOIN_TYPE), + error::invalid_argument(ECOIN_TYPE) ); let is_offer_a = offer_address == pair_key.coin_a; let (pool_a, pool_b, weight_a, weight_b, swap_fee_rate) = pool_info(pair, true); @@ -353,7 +349,7 @@ module initia_std::dex { offer_weight, return_weight, return_amount, - swap_fee_rate, + swap_fee_rate ); offer_amount @@ -361,19 +357,46 @@ module initia_std::dex { #[view] public fun get_swap_simulation_given_out_by_denom( - pair_denom: String, - offer_denom: String, - return_amount: u64, + pair_denom: String, offer_denom: String, return_amount: u64 ): u64 acquires Config, Pool { let pair_metadata = coin::denom_to_metadata(pair_denom); let offer_metadata = coin::denom_to_metadata(offer_denom); get_swap_simulation_given_out( object::convert(pair_metadata), offer_metadata, - return_amount, + return_amount ) } + #[view] + public fun get_provide_simulation( + pair: Object, + coin_a_amount_in: u64, + coin_b_amount_in: u64 + ): u64 acquires Pool { + let pool_addr = object::object_address(&pair); + let pool = borrow_global(pool_addr); + + calculate_provide_liquidity_return_amount( + pool, pair, coin_a_amount_in, coin_b_amount_in + ) + } + + #[view] + public fun get_single_asset_provide_simulation( + pair: Object, offer_asset_metadata: Object, amount_in: u64 + ): u64 acquires Config, Pool { + let pair_addr = object::object_address(&pair); + let pool = borrow_global(pair_addr); + + let (liquidity_amount, _, _) = + calculate_single_asset_provide_liquidity_return_amount( + pool, pair, offer_asset_metadata, amount_in + ); + + liquidity_amount + } + #[view] /// get pool info public fun get_pool_info(pair: Object): PoolInfoResponse acquires Pool { @@ -382,7 +405,7 @@ module initia_std::dex { PoolInfoResponse { coin_a_amount: fungible_asset::balance(pool.coin_a_store), coin_b_amount: fungible_asset::balance(pool.coin_b_store), - total_share: option::extract(&mut fungible_asset::supply(pair)), + total_share: option::extract(&mut fungible_asset::supply(pair)) } } @@ -399,7 +422,7 @@ module initia_std::dex { let pair_addr = object::object_address(&pair); let config = borrow_global(pair_addr); - ConfigResponse { weights: config.weights, swap_fee_rate: config.swap_fee_rate, } + ConfigResponse { weights: config.weights, swap_fee_rate: config.swap_fee_rate } } #[view] @@ -414,11 +437,13 @@ module initia_std::dex { let pair_addr = object::object_address(&pair); let config = borrow_global(pair_addr); let (coin_a_weight, coin_b_weight) = get_weight(&config.weights); - CurrentWeightResponse { coin_a_weight, coin_b_weight, } + CurrentWeightResponse { coin_a_weight, coin_b_weight } } #[view] - public fun get_current_weight_by_denom(pair_denom: String): CurrentWeightResponse acquires Config { + public fun get_current_weight_by_denom( + pair_denom: String + ): CurrentWeightResponse acquires Config { let pair_metadata = coin::denom_to_metadata(pair_denom); get_current_weight(object::convert(pair_metadata)) } @@ -430,17 +455,18 @@ module initia_std::dex { coin_a_start_after: Option
, coin_b_start_after: Option
, liquidity_token_start_after: Option
, - limit: u8, + limit: u8 ): vector acquires ModuleStore { if (limit > MAX_LIMIT) { limit = MAX_LIMIT; }; assert!( - option::is_some(&coin_a_start_after) == option::is_some(&coin_b_start_after) + option::is_some(&coin_a_start_after) + == option::is_some(&coin_b_start_after) && option::is_some(&coin_b_start_after) == option::is_some(&liquidity_token_start_after), - ESTART_AFTER, + ESTART_AFTER ); let module_store = borrow_global(@initia_std); @@ -451,12 +477,12 @@ module initia_std::dex { PairKey { coin_a: option::extract(&mut coin_a_start_after), coin_b: option::extract(&mut coin_b_start_after), - liquidity_token: option::extract(&mut liquidity_token_start_after), - }, + liquidity_token: option::extract(&mut liquidity_token_start_after) + } ) } else { option::some( - PairKey { coin_a: @0x0, coin_b: @0x0, liquidity_token: @0x0, }, + PairKey { coin_a: @0x0, coin_b: @0x0, liquidity_token: @0x0 } ) }; @@ -465,11 +491,11 @@ module initia_std::dex { &module_store.pairs, start_after, option::none(), - 1, + 1 ); while (vector::length(&res) < (limit as u64) - && table::prepare(pairs_iter)) { + && table::prepare(pairs_iter)) { let (key, value) = table::next(pairs_iter); if (&key != option::borrow(&start_after)) { vector::push_back(&mut res, *value) @@ -486,17 +512,18 @@ module initia_std::dex { coin_a_start_after: Option, coin_b_start_after: Option, liquidity_token_start_after: Option, - limit: u8, + limit: u8 ): vector acquires ModuleStore { if (limit > MAX_LIMIT) { limit = MAX_LIMIT; }; assert!( - option::is_some(&coin_a_start_after) == option::is_some(&coin_b_start_after) + option::is_some(&coin_a_start_after) + == option::is_some(&coin_b_start_after) && option::is_some(&coin_b_start_after) == option::is_some(&liquidity_token_start_after), - ESTART_AFTER, + ESTART_AFTER ); let module_store = borrow_global(@initia_std); @@ -517,12 +544,12 @@ module initia_std::dex { coin_b: object::object_address(&coin_b_start_after), liquidity_token: object::object_address( &liquidity_token_start_after - ), - }, + ) + } ) } else { option::some( - PairKey { coin_a: @0x0, coin_b: @0x0, liquidity_token: @0x0, }, + PairKey { coin_a: @0x0, coin_b: @0x0, liquidity_token: @0x0 } ) }; @@ -531,11 +558,11 @@ module initia_std::dex { &module_store.pairs, start_after, option::none(), - 1, + 1 ); while (vector::length(&res) < (limit as u64) - && table::prepare(pairs_iter)) { + && table::prepare(pairs_iter)) { let (key, value) = table::next(pairs_iter); if (&key != option::borrow(&start_after)) { vector::push_back( @@ -551,8 +578,8 @@ module initia_std::dex { object::address_to_object(value.liquidity_token) ), weights: value.weights, - swap_fee_rate: value.swap_fee_rate, - }, + swap_fee_rate: value.swap_fee_rate + } ) } }; @@ -567,7 +594,7 @@ module initia_std::dex { coin_a: address, coin_b: address, start_after: Option
, - limit: u8, + limit: u8 ): vector acquires ModuleStore { if (limit > MAX_LIMIT) { limit = MAX_LIMIT; @@ -581,13 +608,11 @@ module initia_std::dex { PairKey { coin_a, coin_b, - liquidity_token: option::extract(&mut start_after), - }, + liquidity_token: option::extract(&mut start_after) + } ) } else { - option::some( - PairKey { coin_a, coin_b, liquidity_token: @0x0, }, - ) + option::some(PairKey { coin_a, coin_b, liquidity_token: @0x0 }) }; let res = vector[]; @@ -595,14 +620,14 @@ module initia_std::dex { &module_store.pairs, start_after, option::none(), - 1, + 1 ); while (vector::length(&res) < (limit as u64) - && table::prepare(pairs_iter)) { + && table::prepare(pairs_iter)) { let (key, value) = table::next(pairs_iter); if (coin_a != key.coin_a || coin_b != key.coin_b) - break; + break; if (&key != option::borrow(&start_after)) { vector::push_back(&mut res, *value) } @@ -633,7 +658,7 @@ module initia_std::dex { public fun get_swap_fee_rate_from_config_response( res: &ConfigResponse - ): Decimal128 { + ): BigDecimal { res.swap_fee_rate } @@ -647,11 +672,11 @@ module initia_std::dex { res.weights.weights_after } - public fun get_coin_a_weight_from_weight(weight: &Weight): Decimal128 { + public fun get_coin_a_weight_from_weight(weight: &Weight): BigDecimal { weight.coin_a_weight } - public fun get_coin_b_weight_from_weight(weight: &Weight): Decimal128 { + public fun get_coin_b_weight_from_weight(weight: &Weight): BigDecimal { weight.coin_b_weight } @@ -659,10 +684,9 @@ module initia_std::dex { weight.timestamp } - public fun unpack_pair_response(pair_response: &PairResponse) - : ( - address, address, address, Weights, Decimal128 - ) { + public fun unpack_pair_response( + pair_response: &PairResponse + ): (address, address, address, Weights, BigDecimal) { ( pair_response.coin_a, pair_response.coin_b, @@ -674,22 +698,25 @@ module initia_std::dex { public fun unpack_current_weight_response( current_weight_response: &CurrentWeightResponse - ): (Decimal128, Decimal128) { - (current_weight_response.coin_a_weight, current_weight_response.coin_b_weight,) + ): (BigDecimal, BigDecimal) { + (current_weight_response.coin_a_weight, current_weight_response.coin_b_weight) } /// Check signer is chain fun check_chain_permission(chain: &signer) { assert!( signer::address_of(chain) == @initia_std, - error::permission_denied(EUNAUTHORIZED), + error::permission_denied(EUNAUTHORIZED) ); } fun init_module(chain: &signer) { move_to( chain, - ModuleStore { pairs: table::new(), pair_count: 0, }, + ModuleStore { + pairs: table::new(), + pair_count: 0 + } ); } @@ -697,13 +724,13 @@ module initia_std::dex { creator: &signer, name: String, symbol: String, - swap_fee_rate: Decimal128, - coin_a_weight: Decimal128, - coin_b_weight: Decimal128, + swap_fee_rate: BigDecimal, + coin_a_weight: BigDecimal, + coin_b_weight: BigDecimal, coin_a_metadata: Object, coin_b_metadata: Object, coin_a_amount: u64, - coin_b_amount: u64, + coin_b_amount: u64 ) acquires CoinCapabilities, Config, Pool, ModuleStore { let (_, timestamp) = get_block_info(); let weights = Weights { @@ -714,12 +741,12 @@ module initia_std::dex { let coin_a = coin::withdraw( creator, coin_a_metadata, - coin_a_amount, + coin_a_amount ); let coin_b = coin::withdraw( creator, coin_b_metadata, - coin_b_amount, + coin_b_amount ); let liquidity_token = @@ -730,7 +757,7 @@ module initia_std::dex { swap_fee_rate, coin_a, coin_b, - weights, + weights ); coin::deposit(signer::address_of(creator), liquidity_token); } @@ -742,49 +769,49 @@ module initia_std::dex { creator: &signer, name: String, symbol: String, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal, start_time: u64, - coin_a_start_weight: Decimal128, - coin_b_start_weight: Decimal128, + coin_a_start_weight: BigDecimal, + coin_b_start_weight: BigDecimal, end_time: u64, - coin_a_end_weight: Decimal128, - coin_b_end_weight: Decimal128, + coin_a_end_weight: BigDecimal, + coin_b_end_weight: BigDecimal, coin_a_metadata: Object, coin_b_metadata: Object, coin_a_amount: u64, - coin_b_amount: u64, + coin_b_amount: u64 ) acquires CoinCapabilities, Config, ModuleStore, Pool { let (_, timestamp) = get_block_info(); assert!( start_time > timestamp, - error::invalid_argument(ELBP_START_TIME), + error::invalid_argument(ELBP_START_TIME) ); assert!( end_time > start_time, - error::invalid_argument(EWEIGHTS_TIMESTAMP), + error::invalid_argument(EWEIGHTS_TIMESTAMP) ); let weights = Weights { weights_before: Weight { coin_a_weight: coin_a_start_weight, coin_b_weight: coin_b_start_weight, - timestamp: start_time, + timestamp: start_time }, weights_after: Weight { coin_a_weight: coin_a_end_weight, coin_b_weight: coin_b_end_weight, - timestamp: end_time, + timestamp: end_time } }; let coin_a = coin::withdraw( creator, coin_a_metadata, - coin_a_amount, + coin_a_amount ); let coin_b = coin::withdraw( creator, coin_b_metadata, - coin_b_amount, + coin_b_amount ); let liquidity_token = @@ -795,23 +822,25 @@ module initia_std::dex { swap_fee_rate, coin_a, coin_b, - weights, + weights ); coin::deposit(signer::address_of(creator), liquidity_token); } + fun max_fee_rate(): BigDecimal { + bigdecimal::from_ratio_u64(5, 100) + } + /// update swap fee rate public entry fun update_swap_fee_rate( - chain: &signer, - pair: Object, - swap_fee_rate: Decimal128, + chain: &signer, pair: Object, swap_fee_rate: BigDecimal ) acquires Config, Pool, ModuleStore { check_chain_permission(chain); let config = borrow_global_mut(object::object_address(&pair)); assert!( - decimal128::val(&swap_fee_rate) <= MAX_FEE_RATE, - error::invalid_argument(EOUT_OF_SWAP_FEE_RATE_RANGE), + bigdecimal::le(swap_fee_rate, max_fee_rate()), + error::invalid_argument(EOUT_OF_SWAP_FEE_RATE_RANGE) ); config.swap_fee_rate = swap_fee_rate; @@ -829,8 +858,8 @@ module initia_std::dex { coin_a: pair_key.coin_a, coin_b: pair_key.coin_b, liquidity_token: pair_key.liquidity_token, - swap_fee_rate, - }, + swap_fee_rate + } ); } @@ -847,7 +876,7 @@ module initia_std::dex { pair, coin_a_amount_in, coin_b_amount_in, - min_liquidity, + min_liquidity ); } @@ -872,27 +901,26 @@ module initia_std::dex { coin::withdraw( account, fungible_asset::store_metadata(pool.coin_a_store), - coin_a_amount_in, + coin_a_amount_in ), coin::withdraw( account, fungible_asset::store_metadata(pool.coin_b_store), - coin_b_amount_in, - ), + coin_b_amount_in + ) ) } else { let coin_a_share_ratio = - decimal128::from_ratio_u64(coin_a_amount_in, coin_a_amount); + bigdecimal::from_ratio_u64(coin_a_amount_in, coin_a_amount); let coin_b_share_ratio = - decimal128::from_ratio_u64(coin_b_amount_in, coin_b_amount); - if (decimal128::val(&coin_a_share_ratio) - > decimal128::val(&coin_b_share_ratio)) { - coin_a_amount_in = decimal128::mul_u64( - &coin_b_share_ratio, coin_a_amount + bigdecimal::from_ratio_u64(coin_b_amount_in, coin_b_amount); + if (bigdecimal::gt(coin_a_share_ratio, coin_b_share_ratio)) { + coin_a_amount_in = bigdecimal::mul_by_u64_truncate( + coin_b_share_ratio, coin_a_amount ); } else { - coin_b_amount_in = decimal128::mul_u64( - &coin_a_share_ratio, coin_b_amount + coin_b_amount_in = bigdecimal::mul_by_u64_truncate( + coin_a_share_ratio, coin_b_amount ); }; @@ -900,13 +928,13 @@ module initia_std::dex { coin::withdraw( account, fungible_asset::store_metadata(pool.coin_a_store), - coin_a_amount_in, + coin_a_amount_in ), coin::withdraw( account, fungible_asset::store_metadata(pool.coin_b_store), - coin_b_amount_in, - ), + coin_b_amount_in + ) ) }; @@ -924,11 +952,11 @@ module initia_std::dex { pair: Object, liquidity: u64, min_coin_a_amount: Option, - min_coin_b_amount: Option, + min_coin_b_amount: Option ) acquires CoinCapabilities, Config, Pool { assert!( liquidity != 0, - error::invalid_argument(EZERO_LIQUIDITY), + error::invalid_argument(EZERO_LIQUIDITY) ); let addr = signer::address_of(account); @@ -936,13 +964,13 @@ module initia_std::dex { coin::withdraw( account, object::convert(pair), - liquidity, + liquidity ); let (coin_a, coin_b) = withdraw_liquidity( liquidity_token, min_coin_a_amount, - min_coin_b_amount, + min_coin_b_amount ); coin::deposit(addr, coin_a); @@ -955,12 +983,12 @@ module initia_std::dex { pair: Object, offer_coin: Object, offer_coin_amount: u64, - min_return: Option, + min_return: Option ) acquires Config, Pool { let offer_coin = coin::withdraw( account, offer_coin, - offer_coin_amount, + offer_coin_amount ); let return_coin = swap(pair, offer_coin); @@ -969,7 +997,7 @@ module initia_std::dex { || *option::borrow(&min_return) <= fungible_asset::amount( &return_coin ), - error::invalid_state(EMIN_RETURN), + error::invalid_state(EMIN_RETURN) ); coin::deposit(signer::address_of(account), return_coin); @@ -996,7 +1024,7 @@ module initia_std::dex { public fun withdraw_liquidity( lp_token: FungibleAsset, min_coin_a_amount: Option, - min_coin_b_amount: Option, + min_coin_b_amount: Option ): (FungibleAsset, FungibleAsset) acquires CoinCapabilities, Config, Pool { let pair_addr = coin_address(&lp_token); let pool = borrow_global_mut(pair_addr); @@ -1005,33 +1033,35 @@ module initia_std::dex { option::extract( &mut fungible_asset::supply( fungible_asset::metadata_from_asset(&lp_token) - ), + ) ); let coin_a_amount = fungible_asset::balance(pool.coin_a_store); let given_token_amount = fungible_asset::amount(&lp_token); let coin_b_amount = fungible_asset::balance(pool.coin_b_store); let given_share_ratio = - decimal128::from_ratio((given_token_amount as u128), total_share); - let coin_a_amount_out = decimal128::mul_u64(&given_share_ratio, coin_a_amount); - let coin_b_amount_out = decimal128::mul_u64(&given_share_ratio, coin_b_amount); + bigdecimal::from_ratio_u128((given_token_amount as u128), total_share); + let coin_a_amount_out = + bigdecimal::mul_by_u64_truncate(given_share_ratio, coin_a_amount); + let coin_b_amount_out = + bigdecimal::mul_by_u64_truncate(given_share_ratio, coin_b_amount); check_lbp_ended(&config.weights); assert!( option::is_none(&min_coin_a_amount) || *option::borrow(&min_coin_a_amount) <= coin_a_amount_out, - error::invalid_state(EMIN_WITHDRAW), + error::invalid_state(EMIN_WITHDRAW) ); assert!( option::is_none(&min_coin_b_amount) || *option::borrow(&min_coin_b_amount) <= coin_b_amount_out, - error::invalid_state(EMIN_WITHDRAW), + error::invalid_state(EMIN_WITHDRAW) ); // burn liquidity token let liquidity_token_capabilities = borrow_global(pair_addr); coin::burn( &liquidity_token_capabilities.burn_cap, - lp_token, + lp_token ); // emit events @@ -1043,8 +1073,8 @@ module initia_std::dex { liquidity_token: pair_addr, coin_a_amount: coin_a_amount_out, coin_b_amount: coin_b_amount_out, - liquidity: given_token_amount, - }, + liquidity: given_token_amount + } ); let pool = borrow_global_mut(pair_addr); @@ -1054,13 +1084,13 @@ module initia_std::dex { fungible_asset::withdraw( pair_signer, pool.coin_a_store, - coin_a_amount_out, + coin_a_amount_out ), fungible_asset::withdraw( pair_signer, pool.coin_b_store, - coin_b_amount_out, - ), + coin_b_amount_out + ) ) } @@ -1070,96 +1100,33 @@ module initia_std::dex { public fun single_asset_provide_liquidity( pair: Object, provide_coin: FungibleAsset, - min_liquidity_amount: Option, + min_liquidity_amount: Option ): FungibleAsset acquires Config, CoinCapabilities, Pool { let pair_addr = object::object_address(&pair); - let config = borrow_global(pair_addr); - check_lbp_ended(&config.weights); - - // provide coin type must be one of coin a or coin b coin type - let provide_metadata = fungible_asset::metadata_from_asset(&provide_coin); - let provide_address = object::object_address(&provide_metadata); - let pair_key = generate_pair_key(pair); - assert!( - provide_address == pair_key.coin_a || provide_address == pair_key.coin_b, - error::invalid_argument(ECOIN_TYPE), - ); - let is_provide_a = provide_address == pair_key.coin_a; - - let total_share = option::extract(&mut fungible_asset::supply(pair)); - assert!( - total_share != 0, - error::invalid_state(EZERO_LIQUIDITY), - ); - - // load values for fee and increased liquidity amount calculation - let amount_in = fungible_asset::amount(&provide_coin); - let (coin_a_weight, coin_b_weight) = get_weight(&config.weights); let pool = borrow_global_mut(pair_addr); - let (normalized_weight, pool_amount_in, provide_coin_addr) = - if (is_provide_a) { - let normalized_weight = - decimal128::from_ratio( - decimal128::val(&coin_a_weight), - decimal128::val(&coin_a_weight) + decimal128::val(&coin_b_weight), - ); - - let pool_amount_in = fungible_asset::balance(pool.coin_a_store); - fungible_asset::deposit(pool.coin_a_store, provide_coin); - - (normalized_weight, pool_amount_in, pair_key.coin_a) - } else { - let normalized_weight = - decimal128::from_ratio( - decimal128::val(&coin_b_weight), - decimal128::val(&coin_a_weight) + decimal128::val(&coin_b_weight), - ); - - let pool_amount_in = fungible_asset::balance(pool.coin_b_store); - fungible_asset::deposit(pool.coin_b_store, provide_coin); - - (normalized_weight, pool_amount_in, pair_key.coin_b) - }; - // CONTRACT: cannot provide more than the pool amount to prevent huge price impact - assert!( - pool_amount_in > amount_in, - error::invalid_argument(EPRICE_IMPACT), - ); + let provide_metadata = fungible_asset::metadata_from_asset(&provide_coin); + let provide_amount = fungible_asset::amount(&provide_coin); - // compute fee amount with the assumption that we will swap (1 - normalized_weight) of amount_in - let adjusted_swap_amount = - decimal128::mul_u64( - &decimal128::sub( - &decimal128::one(), - &normalized_weight, - ), - amount_in, - ); - let fee_amount = - calculate_fee_with_minimum( - &config.swap_fee_rate, - adjusted_swap_amount, + let (liquidity, fee_amount, is_provide_a) = + calculate_single_asset_provide_liquidity_return_amount( + pool, pair, provide_metadata, provide_amount ); - // actual amount in after deducting fee amount - let adjusted_amount_in = amount_in - fee_amount; + // deposit token + if (is_provide_a) { + fungible_asset::deposit(pool.coin_a_store, provide_coin); + } else { + fungible_asset::deposit(pool.coin_b_store, provide_coin); + }; - // calculate new total share and new liquidity - let base = - decimal128::from_ratio_u64( - adjusted_amount_in + pool_amount_in, - pool_amount_in, - ); - let pool_ratio = pow(&base, &normalized_weight); - let new_total_share = decimal128::mul_u128(&pool_ratio, total_share); - let liquidity = (new_total_share - total_share as u64); + let pair_key = generate_pair_key(pair); // check min liquidity assertion assert!( option::is_none(&min_liquidity_amount) || *option::borrow(&min_liquidity_amount) <= liquidity, - error::invalid_state(EMIN_LIQUIDITY), + error::invalid_state(EMIN_LIQUIDITY) ); // emit events @@ -1167,31 +1134,33 @@ module initia_std::dex { SingleAssetProvideEvent { coin_a: pair_key.coin_a, coin_b: pair_key.coin_b, - provide_coin: provide_coin_addr, + provide_coin: object::object_address(&provide_metadata), liquidity_token: pair_addr, - provide_amount: amount_in, + provide_amount, fee_amount, - liquidity, - }, + liquidity + } ); // mint liquidity tokens to provider let liquidity_token_capabilities = borrow_global(pair_addr); coin::mint( &liquidity_token_capabilities.mint_cap, - liquidity, + liquidity ) } /// Swap directly - public fun swap(pair: Object, offer_coin: FungibleAsset,): FungibleAsset acquires Config, Pool { + public fun swap( + pair: Object, offer_coin: FungibleAsset + ): FungibleAsset acquires Config, Pool { let offer_amount = fungible_asset::amount(&offer_coin); let offer_metadata = fungible_asset::metadata_from_asset(&offer_coin); let offer_address = object::object_address(&offer_metadata); let pair_key = generate_pair_key(pair); assert!( offer_address == pair_key.coin_a || offer_address == pair_key.coin_b, - error::invalid_argument(ECOIN_TYPE), + error::invalid_argument(ECOIN_TYPE) ); let is_offer_a = offer_address == pair_key.coin_a; @@ -1216,7 +1185,7 @@ module initia_std::dex { offer_weight, return_weight, fungible_asset::amount(&offer_coin), - swap_fee_rate, + swap_fee_rate ); // apply swap result to pool @@ -1230,14 +1199,14 @@ module initia_std::dex { fungible_asset::withdraw( pair_signer, pool.coin_b_store, - return_amount, + return_amount ) } else { fungible_asset::deposit(pool.coin_b_store, offer_coin); fungible_asset::withdraw( pair_signer, pool.coin_a_store, - return_amount, + return_amount ) }; @@ -1249,21 +1218,45 @@ module initia_std::dex { liquidity_token: pair_addr, fee_amount, offer_amount, - return_amount, - }, + return_amount + } ); return_coin } + /// Sum of weights must be 1 + fun assert_weights(weights: Weights) { + assert!( + bigdecimal::eq( + bigdecimal::one(), + bigdecimal::add( + weights.weights_before.coin_a_weight, + weights.weights_before.coin_b_weight + ) + ), + EINVALID_WEIGHTS + ); + assert!( + bigdecimal::eq( + bigdecimal::one(), + bigdecimal::add( + weights.weights_after.coin_a_weight, + weights.weights_after.coin_b_weight + ) + ), + EINVALID_WEIGHTS + ); + } + public fun create_pair( creator: &signer, name: String, symbol: String, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal, coin_a: FungibleAsset, coin_b: FungibleAsset, - weights: Weights, + weights: Weights ): FungibleAsset acquires CoinCapabilities, Config, ModuleStore, Pool { let (mint_cap, burn_cap, freeze_cap, extend_ref) = coin::initialize_and_generate_extend_ref( @@ -1273,17 +1266,19 @@ module initia_std::dex { symbol, 6, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); + assert_weights(weights); + assert!( - decimal128::val(&swap_fee_rate) <= MAX_FEE_RATE, - error::invalid_argument(EOUT_OF_SWAP_FEE_RATE_RANGE), + bigdecimal::le(swap_fee_rate, max_fee_rate()), + error::invalid_argument(EOUT_OF_SWAP_FEE_RATE_RANGE) ); assert!( coin_address(&coin_a) != coin_address(&coin_b), - error::invalid_argument(ESAME_COIN_TYPE), + error::invalid_argument(ESAME_COIN_TYPE) ); let pair_signer = &object::generate_signer_for_extending(&extend_ref); @@ -1294,24 +1289,24 @@ module initia_std::dex { let coin_a_store = primary_fungible_store::create_primary_store( pair_address, - fungible_asset::asset_metadata(&coin_a), + fungible_asset::asset_metadata(&coin_a) ); let coin_b_store = primary_fungible_store::create_primary_store( pair_address, - fungible_asset::asset_metadata(&coin_b), + fungible_asset::asset_metadata(&coin_b) ); let coin_a_addr = coin_address(&coin_a); let coin_b_addr = coin_address(&coin_b); move_to( pair_signer, - Pool { coin_a_store, coin_b_store }, + Pool { coin_a_store, coin_b_store } ); move_to( pair_signer, - CoinCapabilities { mint_cap, freeze_cap, burn_cap }, + CoinCapabilities { mint_cap, freeze_cap, burn_cap } ); move_to( @@ -1321,18 +1316,18 @@ module initia_std::dex { // temp weights for initial provide weights: Weights { weights_before: Weight { - coin_a_weight: decimal128::one(), - coin_b_weight: decimal128::one(), - timestamp: 0, + coin_a_weight: bigdecimal::one(), + coin_b_weight: bigdecimal::one(), + timestamp: 0 }, weights_after: Weight { - coin_a_weight: decimal128::one(), - coin_b_weight: decimal128::one(), - timestamp: 0, + coin_a_weight: bigdecimal::one(), + coin_b_weight: bigdecimal::one(), + timestamp: 0 } }, - swap_fee_rate, - }, + swap_fee_rate + } ); let liquidity_token = @@ -1340,7 +1335,7 @@ module initia_std::dex { object::address_to_object(pair_address), coin_a, coin_b, - option::none(), + option::none() ); // update weights @@ -1369,8 +1364,8 @@ module initia_std::dex { coin_b: coin_b_addr, liquidity_token: pair_address, weights, - swap_fee_rate, - }, + swap_fee_rate + } ); // emit create pair event @@ -1380,8 +1375,8 @@ module initia_std::dex { coin_b: coin_b_addr, liquidity_token: pair_address, weights, - swap_fee_rate, - }, + swap_fee_rate + } ); liquidity_token @@ -1393,7 +1388,7 @@ module initia_std::dex { pair: Object, coin_a: FungibleAsset, coin_b: FungibleAsset, - min_liquidity_amount: Option, + min_liquidity_amount: Option ): FungibleAsset acquires Config, Pool, CoinCapabilities { let pool_addr = object::object_address(&pair); let config = borrow_global_mut(pool_addr); @@ -1401,35 +1396,20 @@ module initia_std::dex { check_lbp_ended(&config.weights); let coin_a_amount_in = fungible_asset::amount(&coin_a); - let coin_a_amount = fungible_asset::balance(pool.coin_a_store); let coin_b_amount_in = fungible_asset::amount(&coin_b); - let coin_b_amount = fungible_asset::balance(pool.coin_b_store); - let total_share = option::extract(&mut fungible_asset::supply(pair)); let liquidity = - if (total_share == 0) { - if (coin_a_amount_in > coin_b_amount_in) { - coin_a_amount_in - } else { - coin_b_amount_in - } - } else { - let coin_a_share_ratio = - decimal128::from_ratio_u64(coin_a_amount_in, coin_a_amount); - let coin_b_share_ratio = - decimal128::from_ratio_u64(coin_b_amount_in, coin_b_amount); - if (decimal128::val(&coin_a_share_ratio) - > decimal128::val(&coin_b_share_ratio)) { - (decimal128::mul_u128(&coin_b_share_ratio, total_share) as u64) - } else { - (decimal128::mul_u128(&coin_a_share_ratio, total_share) as u64) - } - }; + calculate_provide_liquidity_return_amount( + pool, + pair, + coin_a_amount_in, + coin_b_amount_in + ); assert!( option::is_none(&min_liquidity_amount) || *option::borrow(&min_liquidity_amount) <= liquidity, - error::invalid_state(EMIN_LIQUIDITY), + error::invalid_state(EMIN_LIQUIDITY) ); event::emit( @@ -1439,8 +1419,8 @@ module initia_std::dex { liquidity_token: pool_addr, coin_a_amount: coin_a_amount_in, coin_b_amount: coin_b_amount_in, - liquidity, - }, + liquidity + } ); fungible_asset::deposit(pool.coin_a_store, coin_a); @@ -1449,7 +1429,7 @@ module initia_std::dex { let liquidity_token_capabilities = borrow_global(pool_addr); coin::mint( &liquidity_token_capabilities.mint_cap, - liquidity, + liquidity ) } @@ -1463,7 +1443,7 @@ module initia_std::dex { assert!( timestamp >= weights.weights_after.timestamp, - error::invalid_state(ELBP_NOT_ENDED), + error::invalid_state(ELBP_NOT_ENDED) ) } @@ -1480,17 +1460,16 @@ module initia_std::dex { } /// return (coin_a_weight, coin_b_weight) - fun get_weight(weights: &Weights): (Decimal128, Decimal128) { + fun get_weight(weights: &Weights): (BigDecimal, BigDecimal) { let (_, timestamp) = get_block_info(); if (timestamp <= weights.weights_before.timestamp) { (weights.weights_before.coin_a_weight, weights.weights_before.coin_b_weight) } else if (timestamp < weights.weights_after.timestamp) { let interval = - ( - weights.weights_after.timestamp - weights.weights_before.timestamp as u128 - ); - let time_diff_after = (weights.weights_after.timestamp - timestamp as u128); - let time_diff_before = (timestamp - weights.weights_before.timestamp as u128); + weights.weights_after.timestamp - weights.weights_before.timestamp; + + let time_diff_after = weights.weights_after.timestamp - timestamp; + let time_diff_before = timestamp - weights.weights_before.timestamp; // when timestamp_before < timestamp < timestamp_after // weight is linearly change from before to after @@ -1505,35 +1484,150 @@ module initia_std::dex { // l = m + n = g * t * (t_a - t_b) + c * (t_a - t_b) // weight = l / (t_a - t_b) = g * t + c let coin_a_m = - decimal128::new( - decimal128::val(&weights.weights_after.coin_a_weight) * time_diff_before, + bigdecimal::mul_by_u64( + weights.weights_after.coin_a_weight, time_diff_before ); let coin_a_n = - decimal128::new( - decimal128::val(&weights.weights_before.coin_a_weight) * time_diff_after, + bigdecimal::mul_by_u64( + weights.weights_before.coin_a_weight, time_diff_after ); - let coin_a_l = decimal128::add(&coin_a_m, &coin_a_n); + let coin_a_l = bigdecimal::add(coin_a_m, coin_a_n); let coin_b_m = - decimal128::new( - decimal128::val(&weights.weights_after.coin_b_weight) * time_diff_before, + bigdecimal::mul_by_u64( + weights.weights_after.coin_b_weight, time_diff_before ); let coin_b_n = - decimal128::new( - decimal128::val(&weights.weights_before.coin_b_weight) * time_diff_after, + bigdecimal::mul_by_u64( + weights.weights_before.coin_b_weight, time_diff_after ); - let coin_b_l = decimal128::add(&coin_b_m, &coin_b_n); - (decimal128::div(&coin_a_l, interval), decimal128::div(&coin_b_l, interval)) + let coin_b_l = bigdecimal::add(coin_b_m, coin_b_n); + ( + bigdecimal::div_by_u64(coin_a_l, interval), + bigdecimal::div_by_u64(coin_b_l, interval) + ) } else { (weights.weights_after.coin_a_weight, weights.weights_after.coin_b_weight) } } + fun calculate_provide_liquidity_return_amount( + pool: &Pool, + pair: Object, + coin_a_amount_in: u64, + coin_b_amount_in: u64 + ): u64 { + let coin_a_amount = fungible_asset::balance(pool.coin_a_store); + let coin_b_amount = fungible_asset::balance(pool.coin_b_store); + let total_share = option::extract(&mut fungible_asset::supply(pair)); + + if (total_share == 0) { + if (coin_a_amount_in > coin_b_amount_in) { + coin_a_amount_in + } else { + coin_b_amount_in + } + } else { + let coin_a_share_ratio = + bigdecimal::from_ratio_u64(coin_a_amount_in, coin_a_amount); + let coin_b_share_ratio = + bigdecimal::from_ratio_u64(coin_b_amount_in, coin_b_amount); + if (bigdecimal::gt(coin_a_share_ratio, coin_b_share_ratio)) { + (bigdecimal::mul_by_u128_truncate(coin_b_share_ratio, total_share) as u64) + } else { + (bigdecimal::mul_by_u128_truncate(coin_a_share_ratio, total_share) as u64) + } + } + } + + fun calculate_single_asset_provide_liquidity_return_amount( + pool: &Pool, + pair: Object, + provide_metadata: Object, + amount_in: u64 + ): (u64, u64, bool) acquires Config { + let pair_addr = object::object_address(&pair); + let config = borrow_global(pair_addr); + check_lbp_ended(&config.weights); + + // provide coin type must be one of coin a or coin b coin type + assert!( + provide_metadata == fungible_asset::store_metadata(pool.coin_a_store) + || provide_metadata + == fungible_asset::store_metadata(pool.coin_b_store), + error::invalid_argument(ECOIN_TYPE) + ); + let is_provide_a = + provide_metadata == fungible_asset::store_metadata(pool.coin_a_store); + + let total_share = option::extract(&mut fungible_asset::supply(pair)); + assert!( + total_share != 0, + error::invalid_state(EZERO_LIQUIDITY) + ); + + // load values for fee and increased liquidity amount calculation + let (coin_a_weight, coin_b_weight) = get_weight(&config.weights); + let (normalized_weight, pool_amount_in) = + if (is_provide_a) { + let normalized_weight = + bigdecimal::div( + coin_a_weight, + bigdecimal::add(coin_a_weight, coin_b_weight) + ); + let pool_amount_in = fungible_asset::balance(pool.coin_a_store); + (normalized_weight, pool_amount_in) + } else { + let normalized_weight = + bigdecimal::div( + coin_b_weight, + bigdecimal::add(coin_a_weight, coin_b_weight) + ); + + let pool_amount_in = fungible_asset::balance(pool.coin_b_store); + + (normalized_weight, pool_amount_in) + }; + + // CONTRACT: cannot provide more than the pool amount to prevent huge price impact + assert!( + pool_amount_in >= amount_in, + error::invalid_argument(EPRICE_IMPACT) + ); + + // compute fee amount with the assumption that we will swap (1 - normalized_weight) of amount_in + let adjusted_swap_amount = + bigdecimal::mul_by_u64_truncate( + bigdecimal::sub( + bigdecimal::one(), + normalized_weight + ), + amount_in + ); + let fee_amount = + calculate_fee_with_minimum( + config.swap_fee_rate, + adjusted_swap_amount + ); + + // actual amount in after deducting fee amount + let adjusted_amount_in = amount_in - fee_amount; + + // calculate new total share and new liquidity + let base = + bigdecimal::from_ratio_u64( + adjusted_amount_in + pool_amount_in, + pool_amount_in + ); + let pool_ratio = pow(base, normalized_weight); + let new_total_share = bigdecimal::mul_by_u128_truncate(pool_ratio, total_share); + ((new_total_share - total_share as u64), fee_amount, is_provide_a) + } + /// get all pool info at once (a_amount, b_amount, a_weight, b_weight, fee_rate) - public fun pool_info(pair: Object, lbp_assertion: bool) - : ( - u64, u64, Decimal128, Decimal128, Decimal128 - ) acquires Config, Pool { + public fun pool_info( + pair: Object, lbp_assertion: bool + ): (u64, u64, BigDecimal, BigDecimal, BigDecimal) acquires Config, Pool { let pair_addr = object::object_address(&pair); let config = borrow_global(pair_addr); if (lbp_assertion) { @@ -1541,7 +1635,7 @@ module initia_std::dex { let (_, timestamp) = get_block_info(); assert!( timestamp >= config.weights.weights_before.timestamp, - error::invalid_state(ELBP_NOT_STARTED), + error::invalid_state(ELBP_NOT_STARTED) ); }; @@ -1553,15 +1647,15 @@ module initia_std::dex { fungible_asset::balance(pool.coin_b_store), coin_a_weight, coin_b_weight, - config.swap_fee_rate, + config.swap_fee_rate ) } // avoid zero fee amount to prevent fee bypass attack fun calculate_fee_with_minimum( - swap_fee_rate: &Decimal128, amount_in: u64 + swap_fee_rate: BigDecimal, amount_in: u64 ): u64 { - let fee_amount = decimal128::mul_u64_with_ceil(swap_fee_rate, amount_in); + let fee_amount = bigdecimal::mul_by_u64_ceil(swap_fee_rate, amount_in); if (fee_amount == 0) { fee_amount = 1; }; @@ -1575,35 +1669,31 @@ module initia_std::dex { public fun swap_simulation( pool_amount_in: u64, pool_amount_out: u64, - weight_in: Decimal128, - weight_out: Decimal128, + weight_in: BigDecimal, + weight_out: BigDecimal, amount_in: u64, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal ): (u64, u64) { assert!( amount_in > 0, - error::invalid_argument(EZERO_AMOUNT_IN), + error::invalid_argument(EZERO_AMOUNT_IN) ); - let one = decimal128::one(); - let exp = - decimal128::from_ratio( - decimal128::val(&weight_in), - decimal128::val(&weight_out), - ); + let one = bigdecimal::one(); + let exp = bigdecimal::div(weight_in, weight_out); - let fee_amount = calculate_fee_with_minimum(&swap_fee_rate, amount_in); + let fee_amount = calculate_fee_with_minimum(swap_fee_rate, amount_in); let adjusted_amount_in = amount_in - fee_amount; let base = - decimal128::from_ratio_u64( + bigdecimal::from_ratio_u64( pool_amount_in, - pool_amount_in + adjusted_amount_in, + pool_amount_in + adjusted_amount_in ); - let sub_amount = pow(&base, &exp); + let sub_amount = pow(base, exp); ( - decimal128::mul_u64( - &decimal128::sub(&one, &sub_amount), - pool_amount_out, + bigdecimal::mul_by_u64_truncate( + bigdecimal::sub(one, sub_amount), + pool_amount_out ), fee_amount ) @@ -1612,32 +1702,30 @@ module initia_std::dex { public fun swap_simulation_given_out( pool_amount_in: u64, pool_amount_out: u64, - weight_in: Decimal128, - weight_out: Decimal128, + weight_in: BigDecimal, + weight_out: BigDecimal, amount_out: u64, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal ): (u64, u64) { - let one = decimal128::one(); - let exp = - decimal128::from_ratio( - decimal128::val(&weight_out), - decimal128::val(&weight_in), - ); - let base = decimal128::from_ratio_u64( + let one = bigdecimal::one(); + let exp = bigdecimal::div(weight_out, weight_in); + let base = bigdecimal::from_ratio_u64( pool_amount_out, pool_amount_out - amount_out ); - let base_exp = pow(&base, &exp); + let base_exp = pow(base, exp); let adjusted_amount_in = - decimal128::val(&decimal128::sub(&base_exp, &one)) * (pool_amount_in as u128); - let sub_one_fee = decimal128::sub(&one, &swap_fee_rate); - - let amount_in = (adjusted_amount_in / decimal128::val(&sub_one_fee) as u64); - let fee_amount = calculate_fee_with_minimum(&swap_fee_rate, amount_in); + bigdecimal::mul_by_u64(bigdecimal::sub(base_exp, one), pool_amount_in); + let sub_one_fee = bigdecimal::sub(one, swap_fee_rate); + let amount_in = + bigdecimal::truncate_u64(bigdecimal::div(adjusted_amount_in, sub_one_fee)); + let fee_amount = calculate_fee_with_minimum(swap_fee_rate, amount_in); (amount_in, fee_amount) } - public fun pool_metadata(pair: Object): (Object, Object) acquires Pool { + public fun pool_metadata( + pair: Object + ): (Object, Object) acquires Pool { let pair_addr = object::object_address(&pair); let pool = borrow_global(pair_addr); ( @@ -1648,33 +1736,35 @@ module initia_std::dex { /// a^x = 1 + sigma[(k^n)/n!] /// k = x * ln(a) - fun pow(base: &Decimal128, exp: &Decimal128): Decimal128 { + fun pow(base: BigDecimal, exp: BigDecimal): BigDecimal { assert!( - decimal128::val(base) != 0 && decimal128::val(base) < 2000000000000000000, - error::invalid_argument(EOUT_OF_BASE_RANGE), + !bigdecimal::is_zero(base) && bigdecimal::lt(base, bigdecimal::from_u64(2)), + error::invalid_argument(EOUT_OF_BASE_RANGE) ); - let res = decimal128::one(); + let res = bigdecimal::one(); let (ln_a, neg) = ln(base); - let k = mul_decimal128s(&ln_a, exp); + let k = bigdecimal::mul(ln_a, exp); let comp = k; let index = 1; - let subs: vector = vector[]; - while (decimal128::val(&comp) > PRECISION) { + let subs: vector = vector[]; + + let precision = bigdecimal::from_scaled(biguint::from_u64(PRECISION)); + while (bigdecimal::gt(comp, precision)) { if (index & 1 == 1 && neg) { vector::push_back(&mut subs, comp) } else { - res = decimal128::add(&res, &comp) + res = bigdecimal::add(res, comp) }; - comp = decimal128::div(&mul_decimal128s(&comp, &k), index + 1); + comp = bigdecimal::div_by_u64(bigdecimal::mul(comp, k), index + 1); index = index + 1; }; let index = 0; while (index < vector::length(&subs)) { let comp = vector::borrow(&subs, index); - res = decimal128::sub(&res, comp); + res = bigdecimal::sub(res, *comp); index = index + 1; }; @@ -1683,32 +1773,32 @@ module initia_std::dex { /// ln(1 + a) = sigma[(-1) ^ (n + 1) * (a ^ n / n)] /// https://en.wikipedia.org/wiki/Taylor_series#Natural_logarithm - fun ln(num: &Decimal128): (Decimal128, bool) { - let one = decimal128::val(&decimal128::one()); - let num_val = decimal128::val(num); + fun ln(num: BigDecimal): (BigDecimal, bool) { + let one = bigdecimal::one(); let (a, a_neg) = - if (num_val >= one) { - (decimal128::sub(num, &decimal128::one()), false) + if (bigdecimal::ge(num, one)) { + (bigdecimal::sub(num, one), false) } else { - (decimal128::sub(&decimal128::one(), num), true) + (bigdecimal::sub(one, num), true) }; - let res = decimal128::zero(); + let res = bigdecimal::zero(); let comp = a; let index = 1; - while (decimal128::val(&comp) > PRECISION) { + let precision = bigdecimal::from_scaled(biguint::from_u64(PRECISION)); + while (bigdecimal::gt(comp, precision)) { if (index & 1 == 0 && !a_neg) { - res = decimal128::sub(&res, &comp); + res = bigdecimal::sub(res, comp); } else { - res = decimal128::add(&res, &comp); + res = bigdecimal::add(res, comp); }; // comp(old) = a ^ n / n // comp(new) = comp(old) * a * n / (n + 1) = a ^ (n + 1) / (n + 1) - comp = decimal128::div( - &decimal128::new(decimal128::val(&mul_decimal128s(&comp, &a)) * index), // comp * a * index - index + 1, + comp = bigdecimal::div_by_u64( + bigdecimal::mul_by_u64(bigdecimal::mul(comp, a), index), // comp * a * index + index + 1 ); index = index + 1; @@ -1717,16 +1807,6 @@ module initia_std::dex { (res, a_neg) } - fun mul_decimal128s( - decimal128_0: &Decimal128, decimal128_1: &Decimal128 - ): Decimal128 { - let one = (decimal128::val(&decimal128::one()) as u256); - let val_mul = - (decimal128::val(decimal128_0) as u256) - * (decimal128::val(decimal128_1) as u256); - decimal128::new((val_mul / one as u128)) - } - #[test_only] public fun init_module_for_test() { init_module(&initia_std::account::create_signer_for_test(@initia_std)); @@ -1739,21 +1819,20 @@ module initia_std::dex { struct CoinCapsInit has key { burn_cap: coin::BurnCapability, freeze_cap: coin::FreezeCapability, - mint_cap: coin::MintCapability, + mint_cap: coin::MintCapability } #[test_only] struct CoinCapsUsdc has key { burn_cap: coin::BurnCapability, freeze_cap: coin::FreezeCapability, - mint_cap: coin::MintCapability, + mint_cap: coin::MintCapability } #[test_only] - fun initialized_coin(account: &signer, symbol: String,) - : ( - coin::BurnCapability, coin::FreezeCapability, coin::MintCapability - ) { + fun initialized_coin( + account: &signer, symbol: String + ): (coin::BurnCapability, coin::FreezeCapability, coin::MintCapability) { let (mint_cap, burn_cap, freeze_cap, _) = coin::initialize_and_generate_extend_ref( account, @@ -1762,14 +1841,14 @@ module initia_std::dex { symbol, 6, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); return (burn_cap, freeze_cap, mint_cap) } #[test(chain = @0x1)] - fun end_to_end(chain: signer,) acquires Config, CoinCapabilities, ModuleStore, Pool { + fun end_to_end(chain: signer) acquires Config, CoinCapabilities, ModuleStore, Pool { init_module(&chain); initia_std::primary_fungible_store::init_module_for_test(); @@ -1785,12 +1864,12 @@ module initia_std::dex { coin::mint_to( &initia_mint_cap, chain_addr, - 100000000, + 100000000 ); coin::mint_to( &usdc_mint_cap, chain_addr, - 100000000, + 100000000 ); // spot price is 1 @@ -1798,13 +1877,13 @@ module initia_std::dex { &chain, std::string::utf8(b"name"), std::string::utf8(b"SYMBOL"), - decimal128::from_ratio(3, 1000), - decimal128::from_ratio(8, 10), - decimal128::from_ratio(2, 10), + bigdecimal::from_ratio_u64(3, 1000), + bigdecimal::from_ratio_u64(8, 10), + bigdecimal::from_ratio_u64(2, 10), coin::metadata(chain_addr, string::utf8(b"INIT")), coin::metadata(chain_addr, string::utf8(b"USDC")), 80000000, - 20000000, + 20000000 ); let lp_metadata = coin::metadata(chain_addr, string::utf8(b"SYMBOL")); @@ -1812,15 +1891,15 @@ module initia_std::dex { assert!( coin::balance(chain_addr, init_metadata) == 20000000, - 0, + 0 ); assert!( coin::balance(chain_addr, usdc_metadata) == 80000000, - 1, + 1 ); assert!( coin::balance(chain_addr, lp_metadata) == 80000000, - 2, + 2 ); // swap init to usdc @@ -1829,15 +1908,15 @@ module initia_std::dex { pair, init_metadata, 1000, - option::none(), + option::none() ); assert!( coin::balance(chain_addr, init_metadata) == 20000000 - 1000, - 3, + 3 ); assert!( coin::balance(chain_addr, usdc_metadata) == 80000000 + 996, - 4, + 4 ); // return 999 commission 3 // swap usdc to init @@ -1846,15 +1925,15 @@ module initia_std::dex { pair, usdc_metadata, 1000, - option::none(), + option::none() ); assert!( coin::balance(chain_addr, init_metadata) == 20000000 - 1000 + 997, - 5, + 5 ); // return 1000 commission 3 assert!( coin::balance(chain_addr, usdc_metadata) == 80000000 + 996 - 1000, - 6, + 6 ); // withdraw liquidity @@ -1863,15 +1942,17 @@ module initia_std::dex { pair, 40000000, option::none(), - option::none(), + option::none() ); assert!( - coin::balance(chain_addr, init_metadata) == 20000000 - 1000 + 997 + 40000001, - 7, + coin::balance(chain_addr, init_metadata) == 20000000 - 1000 + 997 + + 40000001, + 7 ); assert!( - coin::balance(chain_addr, usdc_metadata) == 80000000 + 996 - 1000 + 10000002, - 8, + coin::balance(chain_addr, usdc_metadata) == 80000000 + 996 - 1000 + + 10000002, + 8 ); // single asset provide liquidity (coin b) @@ -1881,11 +1962,11 @@ module initia_std::dex { pair, usdc_metadata, 100000, - option::none(), + option::none() ); assert!( coin::balance(chain_addr, lp_metadata) == 40000000 + 79491, - 9, + 9 ); // single asset provide liquidity (coin a) @@ -1895,11 +1976,11 @@ module initia_std::dex { pair, init_metadata, 100000, - option::none(), + option::none() ); assert!( coin::balance(chain_addr, lp_metadata) == 40000000 + 79491 + 80090, - 10, + 10 ); move_to( @@ -1907,8 +1988,8 @@ module initia_std::dex { CoinCapsInit { burn_cap: initia_burn_cap, freeze_cap: initia_freeze_cap, - mint_cap: initia_mint_cap, - }, + mint_cap: initia_mint_cap + } ); move_to( @@ -1916,13 +1997,13 @@ module initia_std::dex { CoinCapsUsdc { burn_cap: usdc_burn_cap, freeze_cap: usdc_freeze_cap, - mint_cap: usdc_mint_cap, - }, + mint_cap: usdc_mint_cap + } ); } #[test(chain = @0x1)] - fun lbp_end_to_end(chain: signer,) acquires Config, CoinCapabilities, ModuleStore, Pool { + fun lbp_end_to_end(chain: signer) acquires Config, CoinCapabilities, ModuleStore, Pool { init_module(&chain); initia_std::primary_fungible_store::init_module_for_test(); @@ -1938,12 +2019,12 @@ module initia_std::dex { coin::mint_to( &initia_mint_cap, chain_addr, - 100000000, + 100000000 ); coin::mint_to( &usdc_mint_cap, chain_addr, - 100000000, + 100000000 ); set_block_info(10, 1000); @@ -1952,54 +2033,52 @@ module initia_std::dex { &chain, std::string::utf8(b"name"), std::string::utf8(b"SYMBOL"), - decimal128::from_ratio(3, 1000), + bigdecimal::from_ratio_u64(3, 1000), 2000, - decimal128::from_ratio(99, 100), - decimal128::from_ratio(1, 100), + bigdecimal::from_ratio_u64(99, 100), + bigdecimal::from_ratio_u64(1, 100), 3000, - decimal128::from_ratio(61, 100), - decimal128::from_ratio(39, 100), + bigdecimal::from_ratio_u64(61, 100), + bigdecimal::from_ratio_u64(39, 100), init_metadata, usdc_metadata, 80000000, - 20000000, + 20000000 ); let lp_metadata = coin::metadata(chain_addr, string::utf8(b"SYMBOL")); let pair = object::convert(lp_metadata); assert!( - get_spot_price(pair, init_metadata) - == decimal128::from_string(&string::utf8(b"24.75")), - 0, + get_spot_price(pair, init_metadata) == bigdecimal::from_ratio_u64(2475, 100), + 0 ); // 0.8 : 0.2 set_block_info(11, 2500); assert!( - get_spot_price(pair, init_metadata) - == decimal128::from_string(&string::utf8(b"1")), - 1, + get_spot_price(pair, init_metadata) == bigdecimal::one(), + 1 ); // 0.61 : 0.39 set_block_info(12, 3500); assert!( get_spot_price(pair, init_metadata) - == decimal128::from_string(&string::utf8(b"0.391025641025641025")), - 2, + == bigdecimal::from_ratio_u64(391025641025641025, 1000000000000000000), + 2 ); assert!( coin::balance(chain_addr, init_metadata) == 20000000, - 0, + 0 ); assert!( coin::balance(chain_addr, usdc_metadata) == 80000000, - 1, + 1 ); assert!( coin::balance(chain_addr, lp_metadata) == 80000000, - 3, + 3 ); // swap test during LBP (0.8: 0.2) @@ -2011,15 +2090,15 @@ module initia_std::dex { pair, init_metadata, 1000, - option::none(), + option::none() ); assert!( coin::balance(chain_addr, init_metadata) == 20000000 - 1000, - 4, + 4 ); assert!( coin::balance(chain_addr, usdc_metadata) == 80000000 + 996, - 5, + 5 ); // return 999 commission 3 // swap usdc to init @@ -2028,15 +2107,15 @@ module initia_std::dex { pair, usdc_metadata, 1000, - option::none(), + option::none() ); assert!( coin::balance(chain_addr, init_metadata) == 20000000 - 1000 + 997, - 6, + 6 ); // return 1000 commission 3 assert!( coin::balance(chain_addr, usdc_metadata) == 80000000 + 996 - 1000, - 7, + 7 ); move_to( @@ -2044,8 +2123,8 @@ module initia_std::dex { CoinCapsInit { burn_cap: initia_burn_cap, freeze_cap: initia_freeze_cap, - mint_cap: initia_mint_cap, - }, + mint_cap: initia_mint_cap + } ); move_to( @@ -2053,8 +2132,8 @@ module initia_std::dex { CoinCapsUsdc { burn_cap: usdc_burn_cap, freeze_cap: usdc_freeze_cap, - mint_cap: usdc_mint_cap, - }, + mint_cap: usdc_mint_cap + } ); } @@ -2062,47 +2141,47 @@ module initia_std::dex { fun get_weight_test() { let weights = Weights { weights_before: Weight { - coin_a_weight: decimal128::from_ratio(2, 10), - coin_b_weight: decimal128::from_ratio(8, 10), - timestamp: 1000, + coin_a_weight: bigdecimal::from_ratio_u64(2, 10), + coin_b_weight: bigdecimal::from_ratio_u64(8, 10), + timestamp: 1000 }, weights_after: Weight { - coin_a_weight: decimal128::from_ratio(8, 10), - coin_b_weight: decimal128::from_ratio(2, 10), - timestamp: 2000, - }, + coin_a_weight: bigdecimal::from_ratio_u64(8, 10), + coin_b_weight: bigdecimal::from_ratio_u64(2, 10), + timestamp: 2000 + } }; set_block_info(10, 1000); let (coin_a_weight, coin_b_weight) = get_weight(&weights); assert!( - coin_a_weight == decimal128::from_ratio(2, 10) - && coin_b_weight == decimal128::from_ratio(8, 10), - 0, + coin_a_weight == bigdecimal::from_ratio_u64(2, 10) + && coin_b_weight == bigdecimal::from_ratio_u64(8, 10), + 0 ); set_block_info(15, 1500); let (coin_a_weight, coin_b_weight) = get_weight(&weights); assert!( - coin_a_weight == decimal128::from_ratio(5, 10) - && coin_b_weight == decimal128::from_ratio(5, 10), - 1, + coin_a_weight == bigdecimal::from_ratio_u64(5, 10) + && coin_b_weight == bigdecimal::from_ratio_u64(5, 10), + 1 ); set_block_info(20, 2000); let (coin_a_weight, coin_b_weight) = get_weight(&weights); assert!( - coin_a_weight == decimal128::from_ratio(8, 10) - && coin_b_weight == decimal128::from_ratio(2, 10), - 2, + coin_a_weight == bigdecimal::from_ratio_u64(8, 10) + && coin_b_weight == bigdecimal::from_ratio_u64(2, 10), + 2 ); set_block_info(30, 3000); let (coin_a_weight, coin_b_weight) = get_weight(&weights); assert!( - coin_a_weight == decimal128::from_ratio(8, 10) - && coin_b_weight == decimal128::from_ratio(2, 10), - 3, + coin_a_weight == bigdecimal::from_ratio_u64(8, 10) + && coin_b_weight == bigdecimal::from_ratio_u64(2, 10), + 3 ); } @@ -2127,30 +2206,30 @@ module initia_std::dex { coin::mint_to( &coin_a_mint_cap, chain_addr, - 100000000, + 100000000 ); coin::mint_to( &coin_b_mint_cap, chain_addr, - 100000000, + 100000000 ); coin::mint_to( &coin_c_mint_cap, chain_addr, - 100000000, + 100000000 ); create_pair_script( &chain, std::string::utf8(b"name"), std::string::utf8(b"SYMBOL1"), - decimal128::from_ratio(3, 1000), - decimal128::from_ratio(5, 10), - decimal128::from_ratio(5, 10), + bigdecimal::from_ratio_u64(3, 1000), + bigdecimal::from_ratio_u64(5, 10), + bigdecimal::from_ratio_u64(5, 10), a_metadata, b_metadata, 1, - 1, + 1 ); let lp_1_metadata = coin::metadata(chain_addr, string::utf8(b"SYMBOL1")); let pair_1 = object::convert(lp_1_metadata); @@ -2160,13 +2239,13 @@ module initia_std::dex { &chain, std::string::utf8(b"name"), std::string::utf8(b"SYMBOL2"), - decimal128::from_ratio(3, 1000), - decimal128::from_ratio(5, 10), - decimal128::from_ratio(5, 10), + bigdecimal::from_ratio_u64(3, 1000), + bigdecimal::from_ratio_u64(5, 10), + bigdecimal::from_ratio_u64(5, 10), a_metadata, b_metadata, 1, - 1, + 1 ); let lp_2_metadata = coin::metadata(chain_addr, string::utf8(b"SYMBOL2")); let pair_2 = object::convert(lp_2_metadata); @@ -2176,13 +2255,13 @@ module initia_std::dex { &chain, std::string::utf8(b"name"), std::string::utf8(b"SYMBOL3"), - decimal128::from_ratio(3, 1000), - decimal128::from_ratio(5, 10), - decimal128::from_ratio(5, 10), + bigdecimal::from_ratio_u64(3, 1000), + bigdecimal::from_ratio_u64(5, 10), + bigdecimal::from_ratio_u64(5, 10), a_metadata, c_metadata, 1, - 1, + 1 ); let lp_3_metadata = coin::metadata(chain_addr, string::utf8(b"SYMBOL3")); let pair_3 = object::convert(lp_3_metadata); @@ -2192,21 +2271,21 @@ module initia_std::dex { &chain, std::string::utf8(b"name"), std::string::utf8(b"SYMBOL4"), - decimal128::from_ratio(3, 1000), - decimal128::from_ratio(5, 10), - decimal128::from_ratio(5, 10), + bigdecimal::from_ratio_u64(3, 1000), + bigdecimal::from_ratio_u64(5, 10), + bigdecimal::from_ratio_u64(5, 10), a_metadata, c_metadata, 1, - 1, + 1 ); let lp_4_metadata = coin::metadata(chain_addr, string::utf8(b"SYMBOL4")); let pair_4 = object::convert(lp_4_metadata); let pair_4_addr = object::object_address(&pair_4); let (_, timestamp) = get_block_info(); - let weight = decimal128::from_ratio(5, 10); - let swap_fee_rate = decimal128::from_ratio(3, 1000); + let weight = bigdecimal::from_ratio_u64(5, 10); + let swap_fee_rate = bigdecimal::from_ratio_u64(3, 1000); let weights = Weights { weights_before: Weight { coin_a_weight: weight, @@ -2224,7 +2303,7 @@ module initia_std::dex { option::none(), option::none(), option::none(), - 10, + 10 ); assert!( res @@ -2234,30 +2313,31 @@ module initia_std::dex { coin_b: b_addr, liquidity_token: pair_1_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: b_addr, liquidity_token: pair_2_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: c_addr, liquidity_token: pair_3_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: c_addr, liquidity_token: pair_4_addr, weights, - swap_fee_rate, - },], - 0, + swap_fee_rate + } + ], + 0 ); let res = @@ -2265,7 +2345,7 @@ module initia_std::dex { option::some(a_addr), option::some(b_addr), option::some(pair_1_addr), - 10, + 10 ); assert!( res @@ -2275,23 +2355,24 @@ module initia_std::dex { coin_b: b_addr, liquidity_token: pair_2_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: c_addr, liquidity_token: pair_3_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: c_addr, liquidity_token: pair_4_addr, weights, - swap_fee_rate, - },], - 1, + swap_fee_rate + } + ], + 1 ); let res = @@ -2299,7 +2380,7 @@ module initia_std::dex { option::some(a_addr), option::some(a_addr), option::some(pair_1_addr), - 10, + 10 ); assert!( res @@ -2309,37 +2390,38 @@ module initia_std::dex { coin_b: b_addr, liquidity_token: pair_1_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: b_addr, liquidity_token: pair_2_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: c_addr, liquidity_token: pair_3_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: c_addr, liquidity_token: pair_4_addr, weights, - swap_fee_rate, - },], - 2, + swap_fee_rate + } + ], + 2 ); let res = get_pairs( a_addr, b_addr, option::none(), - 10, + 10 ); assert!( res @@ -2349,23 +2431,24 @@ module initia_std::dex { coin_b: b_addr, liquidity_token: pair_1_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: b_addr, liquidity_token: pair_2_addr, weights, - swap_fee_rate, - },], - 3, + swap_fee_rate + } + ], + 3 ); let res = get_pairs( a_addr, b_addr, option::some(pair_1_addr), - 10, + 10 ); assert!( res @@ -2375,9 +2458,10 @@ module initia_std::dex { coin_b: b_addr, liquidity_token: pair_2_addr, weights, - swap_fee_rate, - },], - 3, + swap_fee_rate + } + ], + 3 ); } } diff --git a/initia_stdlib/sources/event.move b/initia_stdlib/sources/event.move index 118ad82..d531cf3 100644 --- a/initia_stdlib/sources/event.move +++ b/initia_stdlib/sources/event.move @@ -18,12 +18,12 @@ module initia_std::event { #[test_only] struct TestEvent has copy, drop { - value: u64, + value: u64 } #[test_only] struct TestEvent2 has copy, drop { - value: u64, + value: u64 } #[test] diff --git a/initia_stdlib/sources/fa/dispatchable_fungible_asset.move b/initia_stdlib/sources/fa/dispatchable_fungible_asset.move index b03db72..89900c4 100644 --- a/initia_stdlib/sources/fa/dispatchable_fungible_asset.move +++ b/initia_stdlib/sources/fa/dispatchable_fungible_asset.move @@ -39,20 +39,20 @@ module initia_std::dispatchable_fungible_asset { constructor_ref: &ConstructorRef, withdraw_function: Option, deposit_function: Option, - derived_balance_function: Option, + derived_balance_function: Option ) { fungible_asset::register_dispatch_functions( constructor_ref, withdraw_function, deposit_function, - derived_balance_function, + derived_balance_function ); let store_obj = &object::generate_signer(constructor_ref); move_to( store_obj, TransferRefStore { - transfer_ref: fungible_asset::generate_transfer_ref(constructor_ref), - }, + transfer_ref: fungible_asset::generate_transfer_ref(constructor_ref) + } ); } @@ -68,9 +68,7 @@ module initia_std::dispatchable_fungible_asset { /// /// The semantics of deposit will be governed by the function specified in DispatchFunctionStore. public fun withdraw( - owner: &signer, - store: Object, - amount: u64, + owner: &signer, store: Object, amount: u64 ): FungibleAsset acquires TransferRefStore { fungible_asset::withdraw_sanity_check(owner, store, false); let func_opt = fungible_asset::withdraw_dispatch_function(store); @@ -82,12 +80,12 @@ module initia_std::dispatchable_fungible_asset { store, amount, borrow_transfer_ref(store), - func, + func ); let end_balance = fungible_asset::balance(store); assert!( amount <= start_balance - end_balance, - error::aborted(EAMOUNT_MISMATCH), + error::aborted(EAMOUNT_MISMATCH) ); fa } else { @@ -108,7 +106,7 @@ module initia_std::dispatchable_fungible_asset { store, fa, borrow_transfer_ref(store), - func, + func ) } else { fungible_asset::deposit_internal(object::object_address(&store), fa) @@ -121,7 +119,7 @@ module initia_std::dispatchable_fungible_asset { sender: &signer, from: Object, to: Object, - amount: u64, + amount: u64 ) acquires TransferRefStore { let fa = withdraw(sender, from, amount); deposit(to, fa); @@ -174,28 +172,37 @@ module initia_std::dispatchable_fungible_asset { } } - inline fun borrow_transfer_ref(metadata: Object): &TransferRef acquires TransferRefStore { + inline fun borrow_transfer_ref( + metadata: Object + ): &TransferRef acquires TransferRefStore { let metadata_addr = object::object_address(&fungible_asset::store_metadata(metadata)); assert!( exists(metadata_addr), - error::not_found(ESTORE_NOT_FOUND), + error::not_found(ESTORE_NOT_FOUND) ); &borrow_global(metadata_addr).transfer_ref } native fun dispatchable_withdraw( - store: Object, amount: u64, transfer_ref: &TransferRef, function: &FunctionInfo, + store: Object, + amount: u64, + transfer_ref: &TransferRef, + function: &FunctionInfo ): FungibleAsset; native fun dispatchable_deposit( store: Object, fa: FungibleAsset, transfer_ref: &TransferRef, - function: &FunctionInfo, + function: &FunctionInfo ); - native fun dispatchable_derived_balance(store: Object, function: &FunctionInfo,): u64; + native fun dispatchable_derived_balance( + store: Object, function: &FunctionInfo + ): u64; - native fun dispatchable_derived_supply(store: Object, function: &FunctionInfo,): Option; + native fun dispatchable_derived_supply( + store: Object, function: &FunctionInfo + ): Option; } diff --git a/initia_stdlib/sources/fa/fungible_asset.move b/initia_stdlib/sources/fa/fungible_asset.move index 66f73fb..3618fed 100644 --- a/initia_stdlib/sources/fa/fungible_asset.move +++ b/initia_stdlib/sources/fa/fungible_asset.move @@ -97,7 +97,7 @@ module initia_std::fungible_asset { struct Supply has key { current: u128, // option::none() means unlimited supply. - maximum: Option, + maximum: Option } /// Metadata of a Fungible asset @@ -115,7 +115,7 @@ module initia_std::fungible_asset { /// asset. icon_uri: String, /// The Uniform Resource Identifier (uri) pointing to the website for the fungible asset. - project_uri: String, + project_uri: String } /// The store object that holds fungible assets of a specific type associated with an account. @@ -125,20 +125,20 @@ module initia_std::fungible_asset { /// The balance of the fungible metadata. balance: u64, /// If true, owner transfer is disabled that only `TransferRef` can move in/out from this store. - frozen: bool, + frozen: bool } /// FungibleAsset can be passed into function for type safety and to guarantee a specific amount. /// FungibleAsset is ephemeral and cannot be stored directly. It must be deposited back into a store. struct FungibleAsset { metadata: Object, - amount: u64, + amount: u64 } struct DispatchFunctionStore has key { withdraw_function: Option, deposit_function: Option, - derived_balance_function: Option, + derived_balance_function: Option } struct DeriveSupply has key { @@ -171,7 +171,7 @@ module initia_std::fungible_asset { struct DepositEvent has drop, store { store_addr: address, metadata_addr: address, - amount: u64, + amount: u64 } #[event] @@ -179,7 +179,7 @@ module initia_std::fungible_asset { struct WithdrawEvent has drop, store { store_addr: address, metadata_addr: address, - amount: u64, + amount: u64 } #[event] @@ -187,21 +187,21 @@ module initia_std::fungible_asset { struct FrozenEvent has drop, store { store_addr: address, metadata_addr: address, - frozen: bool, + frozen: bool } #[event] /// Emitted when fungible assets are burnt. struct BurnEvent has drop, store { metadata_addr: address, - amount: u64, + amount: u64 } #[event] /// Emitted when fungible assets are minted. struct MintEvent has drop, store { metadata_addr: address, - amount: u64, + amount: u64 } /// Make an existing object fungible by adding the Metadata resource. @@ -216,46 +216,46 @@ module initia_std::fungible_asset { symbol: String, decimals: u8, icon_uri: String, - project_uri: String, + project_uri: String ): Object { assert!( !object::can_generate_delete_ref(constructor_ref), - error::invalid_argument(EOBJECT_IS_DELETABLE), + error::invalid_argument(EOBJECT_IS_DELETABLE) ); let metadata_object_signer = &object::generate_signer(constructor_ref); // metadata validations assert!( string::length(&name) <= MAX_NAME_LENGTH, - error::out_of_range(ENAME_TOO_LONG), + error::out_of_range(ENAME_TOO_LONG) ); assert!( string::length(&symbol) <= MAX_SYMBOL_LENGTH, - error::out_of_range(ESYMBOL_TOO_LONG), + error::out_of_range(ESYMBOL_TOO_LONG) ); assert!( decimals <= MAX_DECIMALS, - error::out_of_range(EDECIMALS_TOO_LARGE), + error::out_of_range(EDECIMALS_TOO_LARGE) ); assert!( string::length(&icon_uri) <= MAX_URI_LENGTH, - error::out_of_range(EURI_TOO_LONG), + error::out_of_range(EURI_TOO_LONG) ); assert!( string::length(&project_uri) <= MAX_URI_LENGTH, - error::out_of_range(EURI_TOO_LONG), + error::out_of_range(EURI_TOO_LONG) ); // store metadata move_to( metadata_object_signer, - Metadata { name, symbol, decimals, icon_uri, project_uri, }, + Metadata { name, symbol, decimals, icon_uri, project_uri } ); // store supply move_to( metadata_object_signer, - Supply { current: 0, maximum: maximum_supply }, + Supply { current: 0, maximum: maximum_supply } ); // return metadata object @@ -267,7 +267,7 @@ module initia_std::fungible_asset { constructor_ref: &ConstructorRef, withdraw_function: Option, deposit_function: Option, - derived_balance_function: Option, + derived_balance_function: Option ) { // Verify that caller type matches callee type so wrongly typed function cannot be registered. option::for_each_ref( @@ -277,17 +277,17 @@ module initia_std::fungible_asset { function_info::new_function_info_from_address( @initia_std, string::utf8(b"dispatchable_fungible_asset"), - string::utf8(b"dispatchable_withdraw"), + string::utf8(b"dispatchable_withdraw") ); assert!( function_info::check_dispatch_type_compatibility( &dispatcher_withdraw_function_info, - withdraw_function, + withdraw_function ), - error::invalid_argument(EWITHDRAW_FUNCTION_SIGNATURE_MISMATCH), + error::invalid_argument(EWITHDRAW_FUNCTION_SIGNATURE_MISMATCH) ); - }, + } ); option::for_each_ref( @@ -297,17 +297,17 @@ module initia_std::fungible_asset { function_info::new_function_info_from_address( @initia_std, string::utf8(b"dispatchable_fungible_asset"), - string::utf8(b"dispatchable_deposit"), + string::utf8(b"dispatchable_deposit") ); // Verify that caller type matches callee type so wrongly typed function cannot be registered. assert!( function_info::check_dispatch_type_compatibility( &dispatcher_deposit_function_info, - deposit_function, + deposit_function ), - error::invalid_argument(EDEPOSIT_FUNCTION_SIGNATURE_MISMATCH), + error::invalid_argument(EDEPOSIT_FUNCTION_SIGNATURE_MISMATCH) ); - }, + } ); option::for_each_ref( @@ -317,26 +317,26 @@ module initia_std::fungible_asset { function_info::new_function_info_from_address( @initia_std, string::utf8(b"dispatchable_fungible_asset"), - string::utf8(b"dispatchable_derived_balance"), + string::utf8(b"dispatchable_derived_balance") ); // Verify that caller type matches callee type so wrongly typed function cannot be registered. assert!( function_info::check_dispatch_type_compatibility( &dispatcher_derived_balance_function_info, - balance_function, + balance_function ), error::invalid_argument( EDERIVED_BALANCE_FUNCTION_SIGNATURE_MISMATCH - ), + ) ); - }, + } ); register_dispatch_function_sanity_check(constructor_ref); assert!( !exists( object::address_from_constructor_ref(constructor_ref) ), - error::already_exists(EALREADY_REGISTERED), + error::already_exists(EALREADY_REGISTERED) ); let store_obj = &object::generate_signer(constructor_ref); @@ -347,8 +347,8 @@ module initia_std::fungible_asset { DispatchFunctionStore { withdraw_function, deposit_function, - derived_balance_function, - }, + derived_balance_function + } ); } @@ -364,53 +364,50 @@ module initia_std::fungible_asset { function_info::new_function_info_from_address( @initia_std, string::utf8(b"dispatchable_fungible_asset"), - string::utf8(b"dispatchable_derived_supply"), + string::utf8(b"dispatchable_derived_supply") ); // Verify that caller type matches callee type so wrongly typed function cannot be registered. assert!( function_info::check_dispatch_type_compatibility( &function_info, - supply_function, + supply_function ), error::invalid_argument( EDERIVED_SUPPLY_FUNCTION_SIGNATURE_MISMATCH - ), + ) ); - }, + } ); register_dispatch_function_sanity_check(constructor_ref); assert!( !exists( object::address_from_constructor_ref(constructor_ref) ), - error::already_exists(EALREADY_REGISTERED), + error::already_exists(EALREADY_REGISTERED) ); let store_obj = &object::generate_signer(constructor_ref); // Store the overload function hook. - move_to( - store_obj, - DeriveSupply { dispatch_function }, - ); + move_to(store_obj, DeriveSupply { dispatch_function }); } /// Check the requirements for registering a dispatchable function. inline fun register_dispatch_function_sanity_check( - constructor_ref: &ConstructorRef, + constructor_ref: &ConstructorRef ) { // Cannot register hook for APT. assert!( object::address_from_constructor_ref(constructor_ref) != @initia_std, - error::permission_denied(EAPT_NOT_DISPATCHABLE), + error::permission_denied(EAPT_NOT_DISPATCHABLE) ); assert!( !object::can_generate_delete_ref(constructor_ref), - error::invalid_argument(EOBJECT_IS_DELETABLE), + error::invalid_argument(EOBJECT_IS_DELETABLE) ); assert!( exists(object::address_from_constructor_ref(constructor_ref)), - error::not_found(EFUNGIBLE_METADATA_EXISTENCE), + error::not_found(EFUNGIBLE_METADATA_EXISTENCE) ); } @@ -485,7 +482,13 @@ module initia_std::fungible_asset { #[view] /// Get the symbol of the fungible asset from the `metadata` object. public fun symbol(metadata: Object): String acquires Metadata { - borrow_fungible_metadata(&metadata).symbol + let md = borrow_fungible_metadata(&metadata); + if (object::is_owner(metadata, @initia_std) + && md.symbol == string::utf8(b"uinit")) { + return string::utf8(b"INIT") + }; + + md.symbol } #[view] @@ -509,7 +512,13 @@ module initia_std::fungible_asset { #[view] /// Get the decimals from the `metadata` object. public fun decimals(metadata: Object): u8 acquires Metadata { - borrow_fungible_metadata(&metadata).decimals + let md = borrow_fungible_metadata(&metadata); + if (object::is_owner(metadata, @initia_std) + && md.symbol == string::utf8(b"uinit")) { + return 6 + }; + + md.decimals } #[view] @@ -547,7 +556,8 @@ module initia_std::fungible_asset { /// /// If the store has not been created, we default to returning false so deposits can be sent to it. public fun is_frozen(store: Object): bool acquires FungibleStore { - store_exists(object::object_address(&store)) && borrow_store_resource(&store).frozen + store_exists(object::object_address(&store)) + && borrow_store_resource(&store).frozen } #[view] @@ -558,7 +568,9 @@ module initia_std::fungible_asset { exists(metadata_addr) } - public fun deposit_dispatch_function(store: Object): Option acquires FungibleStore, DispatchFunctionStore { + public fun deposit_dispatch_function( + store: Object + ): Option acquires FungibleStore, DispatchFunctionStore { let fa_store = borrow_store_resource(&store); let metadata_addr = object::object_address(&fa_store.metadata); if (exists(metadata_addr)) { @@ -568,17 +580,22 @@ module initia_std::fungible_asset { } } - fun has_deposit_dispatch_function(metadata: Object): bool acquires DispatchFunctionStore { + fun has_deposit_dispatch_function( + metadata: Object + ): bool acquires DispatchFunctionStore { let metadata_addr = object::object_address(&metadata); // Short circuit on APT for better perf - if (metadata_addr != @initia_std && exists(metadata_addr)) { + if (metadata_addr != @initia_std + && exists(metadata_addr)) { option::is_some( &borrow_global(metadata_addr).deposit_function ) } else { false } } - public fun withdraw_dispatch_function(store: Object): Option acquires FungibleStore, DispatchFunctionStore { + public fun withdraw_dispatch_function( + store: Object + ): Option acquires FungibleStore, DispatchFunctionStore { let fa_store = borrow_store_resource(&store); let metadata_addr = object::object_address(&fa_store.metadata); if (exists(metadata_addr)) { @@ -588,10 +605,13 @@ module initia_std::fungible_asset { } } - fun has_withdraw_dispatch_function(metadata: Object): bool acquires DispatchFunctionStore { + fun has_withdraw_dispatch_function( + metadata: Object + ): bool acquires DispatchFunctionStore { let metadata_addr = object::object_address(&metadata); // Short circuit on APT for better perf - if (metadata_addr != @initia_std && exists(metadata_addr)) { + if (metadata_addr != @initia_std + && exists(metadata_addr)) { option::is_some( &borrow_global(metadata_addr).withdraw_function ) @@ -651,7 +671,7 @@ module initia_std::fungible_asset { sender: &signer, from: Object, to: Object, - amount: u64, + amount: u64 ) acquires FungibleStore, DispatchFunctionStore { let fa = withdraw(sender, from, amount); deposit(to, fa); @@ -660,16 +680,12 @@ module initia_std::fungible_asset { /// Allow an object to hold a store for fungible assets. /// Applications can use this to create multiple stores for isolating fungible assets for different purposes. public fun create_store( - constructor_ref: &ConstructorRef, metadata: Object, + constructor_ref: &ConstructorRef, metadata: Object ): Object { let store_obj = &object::generate_signer(constructor_ref); move_to( store_obj, - FungibleStore { - metadata: object::convert(metadata), - balance: 0, - frozen: false, - }, + FungibleStore { metadata: object::convert(metadata), balance: 0, frozen: false } ); object::object_from_constructor_ref(constructor_ref) @@ -678,16 +694,12 @@ module initia_std::fungible_asset { /// Allow an object to hold a store for fungible assets. /// Applications can use this to create multiple stores for isolating fungible assets for different purposes. public fun create_store_with_extend_ref( - extend_ref: &ExtendRef, metadata: Object, + extend_ref: &ExtendRef, metadata: Object ): Object { let store_obj = &object::generate_signer_for_extending(extend_ref); move_to( store_obj, - FungibleStore { - metadata: object::convert(metadata), - balance: 0, - frozen: false, - }, + FungibleStore { metadata: object::convert(metadata), balance: 0, frozen: false } ); let obj_addr = object::address_from_extend_ref(extend_ref); @@ -702,24 +714,22 @@ module initia_std::fungible_asset { move_from(addr); assert!( balance == 0, - error::permission_denied(EBALANCE_IS_NOT_ZERO), + error::permission_denied(EBALANCE_IS_NOT_ZERO) ); } /// Check the permission for withdraw operation. public(friend) fun withdraw_sanity_check( - owner: &signer, - store: Object, - abort_on_dispatch: bool, + owner: &signer, store: Object, abort_on_dispatch: bool ) acquires FungibleStore, DispatchFunctionStore { assert!( object::owns(store, signer::address_of(owner)), - error::permission_denied(ENOT_STORE_OWNER), + error::permission_denied(ENOT_STORE_OWNER) ); let fa_store = borrow_store_resource(&store); assert!( !abort_on_dispatch || !has_withdraw_dispatch_function(fa_store.metadata), - error::invalid_argument(EINVALID_DISPATCHABLE_OPERATIONS), + error::invalid_argument(EINVALID_DISPATCHABLE_OPERATIONS) ); assert!(!fa_store.frozen, error::permission_denied(ESTORE_IS_FROZEN)); } @@ -731,7 +741,7 @@ module initia_std::fungible_asset { let fa_store = borrow_store_resource(&store); assert!( !abort_on_dispatch || !has_deposit_dispatch_function(fa_store.metadata), - error::invalid_argument(EINVALID_DISPATCHABLE_OPERATIONS), + error::invalid_argument(EINVALID_DISPATCHABLE_OPERATIONS) ); assert!(!fa_store.frozen, error::permission_denied(ESTORE_IS_FROZEN)); @@ -740,22 +750,22 @@ module initia_std::fungible_asset { let store_addr = object::object_address(&store); assert!( !is_blocked_store_addr(store_addr), - error::invalid_argument(ECANNOT_DEPOSIT_TO_BLOCKED_ACCOUNT), + error::invalid_argument(ECANNOT_DEPOSIT_TO_BLOCKED_ACCOUNT) ); } /// Withdraw `amount` of the fungible asset from `store` by the owner. public fun withdraw( - owner: &signer, - store: Object, - amount: u64, + owner: &signer, store: Object, amount: u64 ): FungibleAsset acquires FungibleStore, DispatchFunctionStore { withdraw_sanity_check(owner, store, true); withdraw_internal(object::object_address(&store), amount) } /// Deposit `amount` of the fungible asset to `store`. - public fun deposit(store: Object, fa: FungibleAsset) acquires FungibleStore, DispatchFunctionStore { + public fun deposit( + store: Object, fa: FungibleAsset + ) acquires FungibleStore, DispatchFunctionStore { deposit_sanity_check(store, true); deposit_internal(object::object_address(&store), fa); } @@ -784,13 +794,11 @@ module initia_std::fungible_asset { /// Enable/disable a store's ability to do direct transfers of the fungible asset. public fun set_frozen_flag( - ref: &TransferRef, - store: Object, - frozen: bool, + ref: &TransferRef, store: Object, frozen: bool ) acquires FungibleStore { assert!( ref.metadata == store_metadata(store), - error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH), + error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH) ); let metadata_addr = object::object_address(&ref.metadata); @@ -799,7 +807,7 @@ module initia_std::fungible_asset { // cannot freeze module account store assert!( !is_module_account_store_addr(store_addr), - error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE), + error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE) ); borrow_global_mut(store_addr).frozen = frozen; @@ -810,10 +818,10 @@ module initia_std::fungible_asset { /// Burns a fungible asset public fun burn(ref: &BurnRef, fa: FungibleAsset) acquires Supply { - let FungibleAsset { metadata, amount, } = fa; + let FungibleAsset { metadata, amount } = fa; assert!( ref.metadata == metadata, - error::invalid_argument(EBURN_REF_AND_FUNGIBLE_ASSET_MISMATCH), + error::invalid_argument(EBURN_REF_AND_FUNGIBLE_ASSET_MISMATCH) ); decrease_supply(metadata, amount); @@ -829,7 +837,7 @@ module initia_std::fungible_asset { let metadata = ref.metadata; assert!( metadata == store_metadata(store), - error::invalid_argument(EBURN_REF_AND_STORE_MISMATCH), + error::invalid_argument(EBURN_REF_AND_STORE_MISMATCH) ); let store_addr = object::object_address(&store); @@ -837,7 +845,7 @@ module initia_std::fungible_asset { // cannot burn module account funds assert!( !is_module_account_store_addr(store_addr), - error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE), + error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE) ); burn(ref, withdraw_internal(store_addr, amount)); @@ -849,14 +857,14 @@ module initia_std::fungible_asset { ): FungibleAsset acquires FungibleStore { assert!( ref.metadata == store_metadata(store), - error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH), + error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH) ); // cannot withdraw module account funds let store_addr = object::object_address(&store); assert!( !is_module_account_store_addr(store_addr), - error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE), + error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE) ); withdraw_internal(object::object_address(&store), amount) @@ -868,14 +876,14 @@ module initia_std::fungible_asset { ) acquires FungibleStore { assert!( ref.metadata == fa.metadata, - error::invalid_argument(ETRANSFER_REF_AND_FUNGIBLE_ASSET_MISMATCH), + error::invalid_argument(ETRANSFER_REF_AND_FUNGIBLE_ASSET_MISMATCH) ); // cannot deposit to blocked account let store_addr = object::object_address(&store); assert!( !is_blocked_store_addr(store_addr), - error::invalid_argument(ECANNOT_DEPOSIT_TO_BLOCKED_ACCOUNT), + error::invalid_argument(ECANNOT_DEPOSIT_TO_BLOCKED_ACCOUNT) ); deposit_internal(object::object_address(&store), fa); @@ -886,7 +894,7 @@ module initia_std::fungible_asset { transfer_ref: &TransferRef, from: Object, to: Object, - amount: u64, + amount: u64 ) acquires FungibleStore { let fa = withdraw_with_ref(transfer_ref, from, amount); deposit_with_ref(transfer_ref, to, fa); @@ -899,7 +907,7 @@ module initia_std::fungible_asset { symbol: Option, decimals: Option, icon_uri: Option, - project_uri: Option, + project_uri: Option ) acquires Metadata { let metadata_address = object::object_address(&metadata_ref.metadata); let mutable_metadata = borrow_global_mut(metadata_address); @@ -929,7 +937,7 @@ module initia_std::fungible_asset { sender: &signer, from: Object, to: Object, - amount: u64, + amount: u64 ) acquires FungibleStore, DispatchFunctionStore { let fa = withdraw(sender, from, amount); sudo_deposit(to, fa); @@ -943,7 +951,7 @@ module initia_std::fungible_asset { ) acquires FungibleStore { assert!( !is_frozen(store), - error::invalid_argument(ESTORE_IS_FROZEN), + error::invalid_argument(ESTORE_IS_FROZEN) ); deposit_internal(object::object_address(&store), fa); @@ -952,17 +960,17 @@ module initia_std::fungible_asset { /// Create a fungible asset with zero amount. /// This can be useful when starting a series of computations where the initial value is 0. public fun zero(metadata: Object): FungibleAsset { - FungibleAsset { metadata: object::convert(metadata), amount: 0, } + FungibleAsset { metadata: object::convert(metadata), amount: 0 } } /// Extract a given amount from the given fungible asset and return a new one. public fun extract(fungible_asset: &mut FungibleAsset, amount: u64): FungibleAsset { assert!( fungible_asset.amount >= amount, - error::invalid_argument(EINSUFFICIENT_BALANCE), + error::invalid_argument(EINSUFFICIENT_BALANCE) ); fungible_asset.amount = fungible_asset.amount - amount; - FungibleAsset { metadata: fungible_asset.metadata, amount, } + FungibleAsset { metadata: fungible_asset.metadata, amount } } /// "Merges" the two given fungible assets. The fungible asset passed in as `dst_fungible_asset` will have a value @@ -973,7 +981,7 @@ module initia_std::fungible_asset { let FungibleAsset { metadata, amount } = src_fungible_asset; assert!( metadata == dst_fungible_asset.metadata, - error::invalid_argument(EFUNGIBLE_ASSET_MISMATCH), + error::invalid_argument(EFUNGIBLE_ASSET_MISMATCH) ); dst_fungible_asset.amount = dst_fungible_asset.amount + amount; } @@ -983,7 +991,7 @@ module initia_std::fungible_asset { let FungibleAsset { amount, metadata: _ } = fungible_asset; assert!( amount == 0, - error::invalid_argument(EAMOUNT_IS_NOT_ZERO), + error::invalid_argument(EAMOUNT_IS_NOT_ZERO) ); } @@ -993,12 +1001,12 @@ module initia_std::fungible_asset { let FungibleAsset { metadata, amount } = fa; assert!( exists(store_addr), - error::not_found(EFUNGIBLE_STORE_EXISTENCE), + error::not_found(EFUNGIBLE_STORE_EXISTENCE) ); let store = borrow_global_mut(store_addr); assert!( metadata == store.metadata, - error::invalid_argument(EFUNGIBLE_ASSET_AND_STORE_MISMATCH), + error::invalid_argument(EFUNGIBLE_ASSET_AND_STORE_MISMATCH) ); if (amount == 0) return; @@ -1012,7 +1020,7 @@ module initia_std::fungible_asset { /// Extract `amount` of the fungible asset from `store`. public(friend) fun withdraw_internal( - store_addr: address, amount: u64, + store_addr: address, amount: u64 ): FungibleAsset acquires FungibleStore { let store = borrow_global_mut(store_addr); let metadata = store.metadata; @@ -1020,7 +1028,7 @@ module initia_std::fungible_asset { assert!( store.balance >= amount, - error::invalid_argument(EINSUFFICIENT_BALANCE), + error::invalid_argument(EINSUFFICIENT_BALANCE) ); store.balance = store.balance - amount; @@ -1038,14 +1046,14 @@ module initia_std::fungible_asset { let metadata_address = object::object_address(&metadata); assert!( exists(metadata_address), - error::not_found(ESUPPLY_NOT_FOUND), + error::not_found(ESUPPLY_NOT_FOUND) ); let supply = borrow_global_mut(metadata_address); if (option::is_some(&supply.maximum)) { let max = *option::borrow_mut(&mut supply.maximum); assert!( max - supply.current >= (amount as u128), - error::out_of_range(EMAX_SUPPLY_EXCEEDED), + error::out_of_range(EMAX_SUPPLY_EXCEEDED) ) }; supply.current = supply.current + (amount as u128); @@ -1058,12 +1066,12 @@ module initia_std::fungible_asset { let metadata_address = object::object_address(&metadata); assert!( exists(metadata_address), - error::not_found(ESUPPLY_NOT_FOUND), + error::not_found(ESUPPLY_NOT_FOUND) ); let supply = borrow_global_mut(metadata_address); assert!( supply.current >= (amount as u128), - error::invalid_state(ESUPPLY_UNDERFLOW), + error::invalid_state(ESUPPLY_UNDERFLOW) ); supply.current = supply.current - (amount as u128); } @@ -1087,12 +1095,16 @@ module initia_std::fungible_asset { borrow_global(addr) } - inline fun borrow_fungible_metadata_mut(metadata: &Object): &mut Metadata acquires Metadata { + inline fun borrow_fungible_metadata_mut( + metadata: &Object + ): &mut Metadata acquires Metadata { let addr = object::object_address(metadata); borrow_global_mut(addr) } - inline fun borrow_store_resource(store: &Object): &FungibleStore acquires FungibleStore { + inline fun borrow_store_resource( + store: &Object + ): &FungibleStore acquires FungibleStore { borrow_global(object::object_address(store)) } @@ -1110,10 +1122,9 @@ module initia_std::fungible_asset { } #[test_only] - public fun init_test_metadata(constructor_ref: &ConstructorRef) - : ( - MintRef, TransferRef, BurnRef, MutateMetadataRef - ) { + public fun init_test_metadata( + constructor_ref: &ConstructorRef + ): (MintRef, TransferRef, BurnRef, MutateMetadataRef) { add_fungibility( constructor_ref, option::some(100) /* max supply */, @@ -1123,7 +1134,7 @@ module initia_std::fungible_asset { string::utf8( b"http://www.example.com/favicon.ico" ), - string::utf8(b"http://www.example.com"), + string::utf8(b"http://www.example.com") ); let mint_ref = generate_mint_ref(constructor_ref); let burn_ref = generate_burn_ref(constructor_ref); @@ -1133,10 +1144,9 @@ module initia_std::fungible_asset { } #[test_only] - public fun create_fungible_asset(creator: &signer) - : ( - MintRef, TransferRef, BurnRef, MutateMetadataRef, Object - ) { + public fun create_fungible_asset( + creator: &signer + ): (MintRef, TransferRef, BurnRef, MutateMetadataRef, Object) { let (creator_ref, token_object) = create_test_token(creator); let (mint, transfer, burn, mutate_metadata) = init_test_metadata(&creator_ref); (mint, transfer, burn, mutate_metadata, object::convert(token_object)) @@ -1149,7 +1159,7 @@ module initia_std::fungible_asset { let owner_addr = signer::address_of(owner); create_store( &object::create_object(owner_addr, true), - metadata, + metadata ) } @@ -1187,7 +1197,9 @@ module initia_std::fungible_asset { } #[test(creator = @0xcafe, aaron = @0xface)] - fun test_e2e_basic_flow(creator: &signer, aaron: &signer,) acquires FungibleStore, Supply, DispatchFunctionStore, Metadata { + fun test_e2e_basic_flow( + creator: &signer, aaron: &signer + ) acquires FungibleStore, Supply, DispatchFunctionStore, Metadata { let (mint_ref, transfer_ref, burn_ref, mutate_metadata_ref, test_token) = create_fungible_asset(creator); let metadata = mint_ref.metadata; @@ -1212,7 +1224,7 @@ module initia_std::fungible_asset { creator, creator_store, aaron_store, - 10, + 10 ); assert!(balance(creator_store) == 10, 5); assert!(balance(aaron_store) == 60, 6); @@ -1227,14 +1239,14 @@ module initia_std::fungible_asset { option::some(string::utf8(b"mutated_symbol")), option::none(), option::none(), - option::none(), + option::none() ); assert!(name(metadata) == string::utf8(b"mutated_name"), 8); assert!(symbol(metadata) == string::utf8(b"mutated_symbol"), 9); assert!(decimals(metadata) == 0, 10); assert!( icon_uri(metadata) == string::utf8(b"http://www.example.com/favicon.ico"), - 11, + 11 ); assert!(project_uri(metadata) == string::utf8(b"http://www.example.com"), 12); } @@ -1252,7 +1264,7 @@ module initia_std::fungible_asset { } #[test(creator = @0xcafe, aaron = @0xface)] - fun test_transfer_with_ref(creator: &signer, aaron: &signer,) acquires FungibleStore, Supply { + fun test_transfer_with_ref(creator: &signer, aaron: &signer) acquires FungibleStore, Supply { let (mint_ref, transfer_ref, _burn_ref, _mutate_metadata_ref, _) = create_fungible_asset(creator); let metadata = mint_ref.metadata; @@ -1267,7 +1279,7 @@ module initia_std::fungible_asset { &transfer_ref, creator_store, aaron_store, - 80, + 80 ); assert!(balance(creator_store) == 20, 1); assert!(balance(aaron_store) == 80, 2); @@ -1304,7 +1316,7 @@ module initia_std::fungible_asset { ) { let (_, _, _, _, metadata1) = create_fungible_asset(creator); let (_, _, _, _, metadata2) = create_fungible_asset(aaron); - let base = FungibleAsset { metadata: metadata1, amount: 1, }; + let base = FungibleAsset { metadata: metadata1, amount: 1 }; let addon = FungibleAsset { metadata: metadata2, amount: 1 }; merge(&mut base, addon); let FungibleAsset { metadata: _, amount: _ } = base; @@ -1325,13 +1337,13 @@ module initia_std::fungible_asset { 10, 0, 3, - false, + false ); set_frozen_flag( &transfer_ref, module_acc_store, - true, + true ); } @@ -1350,7 +1362,7 @@ module initia_std::fungible_asset { 10, 0, 3, - false, + false ); let fa = mint(&mint_ref, 100); @@ -1373,7 +1385,7 @@ module initia_std::fungible_asset { 10, 0, 3, - false, + false ); let fa = mint(&mint_ref, 100); @@ -1397,7 +1409,7 @@ module initia_std::fungible_asset { 10, 0, 3, - true, + true ); let fa = mint(&mint_ref, 100); @@ -1419,7 +1431,7 @@ module initia_std::fungible_asset { 10, 0, 3, - true, + true ); let fa = mint(&mint_ref, 100); diff --git a/initia_stdlib/sources/fa/primary_fungible_store.move b/initia_stdlib/sources/fa/primary_fungible_store.move index 26bead1..88343af 100644 --- a/initia_stdlib/sources/fa/primary_fungible_store.move +++ b/initia_stdlib/sources/fa/primary_fungible_store.move @@ -38,25 +38,28 @@ module initia_std::primary_fungible_store { /// stores for users with deterministic addresses so that users can easily deposit/withdraw/transfer fungible /// assets. struct DeriveRefPod has key { - metadata_derive_ref: DeriveRef, + metadata_derive_ref: DeriveRef } struct ModuleStore has key { issuers: Table
, - user_stores: Table
>, + user_stores: Table
> } #[event] struct PrimaryStoreCreatedEvent has drop, store { owner_addr: address, store_addr: address, - metadata_addr: address, + metadata_addr: address } fun init_module(chain: &signer) { move_to( chain, - ModuleStore { issuers: table::new(), user_stores: table::new(), }, + ModuleStore { + issuers: table::new(), + user_stores: table::new() + } ) } @@ -70,7 +73,7 @@ module initia_std::primary_fungible_store { symbol: String, decimals: u8, icon_uri: String, - project_uri: String, + project_uri: String ) acquires ModuleStore { fungible_asset::add_fungibility( constructor_ref, @@ -79,7 +82,7 @@ module initia_std::primary_fungible_store { symbol, decimals, icon_uri, - project_uri, + project_uri ); let metadata = object::object_from_constructor_ref(constructor_ref); @@ -87,8 +90,8 @@ module initia_std::primary_fungible_store { move_to( metadata_signer, DeriveRefPod { - metadata_derive_ref: object::generate_derive_ref(constructor_ref), - }, + metadata_derive_ref: object::generate_derive_ref(constructor_ref) + } ); // record issuers for cosmos side query @@ -97,14 +100,14 @@ module initia_std::primary_fungible_store { table::add( &mut module_store.issuers, object::object_address(&metadata), - object::owner(metadata), + object::owner(metadata) ); } } /// Ensure that the primary store object for the given address exists. If it doesn't, create it. public fun ensure_primary_store_exists( - owner: address, metadata: Object, + owner: address, metadata: Object ): Object acquires DeriveRefPod, ModuleStore { if (!primary_store_exists(owner, metadata)) { create_primary_store(owner, metadata) @@ -115,7 +118,7 @@ module initia_std::primary_fungible_store { /// Create a primary store object to hold fungible asset for the given address. public fun create_primary_store( - owner_addr: address, metadata: Object, + owner_addr: address, metadata: Object ): Object acquires DeriveRefPod, ModuleStore { let metadata_addr = object::object_address(&metadata); object::address_to_object(metadata_addr); @@ -135,13 +138,13 @@ module initia_std::primary_fungible_store { if (exists(@initia_std)) { let module_store = borrow_global_mut(@initia_std); if (!table::contains( - &module_store.user_stores, - owner_addr, - )) { + &module_store.user_stores, + owner_addr + )) { table::add( &mut module_store.user_stores, owner_addr, - table::new(), + table::new() ); }; @@ -150,14 +153,12 @@ module initia_std::primary_fungible_store { table::add( user_stores, metadata_addr, - store_addr, + store_addr ); }; // emit store created event - event::emit( - PrimaryStoreCreatedEvent { owner_addr, store_addr, metadata_addr, }, - ); + event::emit(PrimaryStoreCreatedEvent { owner_addr, store_addr, metadata_addr }); store } @@ -167,7 +168,7 @@ module initia_std::primary_fungible_store { let module_store = borrow_global(@initia_std); *table::borrow( &module_store.issuers, - object::object_address(&metadata), + object::object_address(&metadata) ) } @@ -182,8 +183,8 @@ module initia_std::primary_fungible_store { #[view] /// Get the primary store object for the given account. - public fun primary_store(owner: address, metadata: Object) - : Object { + public fun primary_store(owner: address, metadata: Object): + Object { let store = primary_store_address(owner, metadata); object::address_to_object(store) } @@ -215,9 +216,7 @@ module initia_std::primary_fungible_store { #[view] /// Get the balances of `account`'s primary store of all fungible assets. public fun balances( - account: address, - start_after: Option
, - limit: u8, + account: address, start_after: Option
, limit: u8 ): (vector>, vector) acquires ModuleStore { let module_store = borrow_global(@initia_std); let account_stores = table::borrow(&module_store.user_stores, account); @@ -225,14 +224,14 @@ module initia_std::primary_fungible_store { account_stores, option::none(), start_after, - 2, + 2 ); let metadata_vec: vector> = vector[]; let balance_vec: vector = vector[]; while (table::prepare(iter) - && vector::length(&balance_vec) < (limit as u64)) { + && vector::length(&balance_vec) < (limit as u64)) { let (metadata_addr, store_addr) = table::next(iter); let metadata = object::address_to_object(metadata_addr); let store = object::address_to_object(*store_addr); @@ -240,7 +239,7 @@ module initia_std::primary_fungible_store { vector::push_back(&mut metadata_vec, metadata); vector::push_back( &mut balance_vec, - fungible_asset::balance(store), + fungible_asset::balance(store) ); }; @@ -250,7 +249,9 @@ module initia_std::primary_fungible_store { /// Deposit fungible asset `fa` to the given account's primary store. /// /// This function is only callable by the chain. - public(friend) fun sudo_deposit(owner: address, fa: FungibleAsset) acquires DeriveRefPod, ModuleStore { + public(friend) fun sudo_deposit( + owner: address, fa: FungibleAsset + ) acquires DeriveRefPod, ModuleStore { let metadata = fungible_asset::asset_metadata(&fa); let store = ensure_primary_store_exists(owner, metadata); fungible_asset::sudo_deposit(store, fa); @@ -268,7 +269,7 @@ module initia_std::primary_fungible_store { sender: &signer, metadata: Object, recipient: address, - amount: u64, + amount: u64 ) acquires DeriveRefPod, ModuleStore { let sender_store = ensure_primary_store_exists(signer::address_of(sender), metadata); @@ -277,7 +278,7 @@ module initia_std::primary_fungible_store { sender, sender_store, recipient_store, - amount, + amount ); } @@ -310,7 +311,7 @@ module initia_std::primary_fungible_store { sender: &signer, metadata: Object, recipient: address, - amount: u64, + amount: u64 ) acquires DeriveRefPod, ModuleStore { let sender_store = ensure_primary_store_exists(signer::address_of(sender), metadata); @@ -332,7 +333,7 @@ module initia_std::primary_fungible_store { metadata: Object, recipient: address, amount: u64, - expected: u64, + expected: u64 ) acquires DeriveRefPod, ModuleStore { let sender_store = ensure_primary_store_exists(signer::address_of(sender), metadata); @@ -342,7 +343,7 @@ module initia_std::primary_fungible_store { sender_store, recipient_store, amount, - expected, + expected ); } @@ -351,7 +352,7 @@ module initia_std::primary_fungible_store { let primary_store = ensure_primary_store_exists( owner, - fungible_asset::mint_ref_metadata(mint_ref), + fungible_asset::mint_ref_metadata(mint_ref) ); fungible_asset::mint_to(mint_ref, primary_store, amount); @@ -367,7 +368,7 @@ module initia_std::primary_fungible_store { let primary_store = primary_store( owner, - fungible_asset::burn_ref_metadata(burn_ref), + fungible_asset::burn_ref_metadata(burn_ref) ); fungible_asset::burn_from(burn_ref, primary_store, amount); } @@ -379,7 +380,7 @@ module initia_std::primary_fungible_store { let primary_store = ensure_primary_store_exists( owner, - fungible_asset::transfer_ref_metadata(transfer_ref), + fungible_asset::transfer_ref_metadata(transfer_ref) ); fungible_asset::set_frozen_flag(transfer_ref, primary_store, frozen); } @@ -391,12 +392,12 @@ module initia_std::primary_fungible_store { let from_primary_store = primary_store( owner, - fungible_asset::transfer_ref_metadata(transfer_ref), + fungible_asset::transfer_ref_metadata(transfer_ref) ); fungible_asset::withdraw_with_ref( transfer_ref, from_primary_store, - amount, + amount ) } @@ -407,7 +408,7 @@ module initia_std::primary_fungible_store { let from_primary_store = ensure_primary_store_exists( owner, - fungible_asset::transfer_ref_metadata(transfer_ref), + fungible_asset::transfer_ref_metadata(transfer_ref) ); fungible_asset::deposit_with_ref(transfer_ref, from_primary_store, fa); @@ -427,18 +428,18 @@ module initia_std::primary_fungible_store { let from_primary_store = primary_store( from, - fungible_asset::transfer_ref_metadata(transfer_ref), + fungible_asset::transfer_ref_metadata(transfer_ref) ); let to_primary_store = ensure_primary_store_exists( to, - fungible_asset::transfer_ref_metadata(transfer_ref), + fungible_asset::transfer_ref_metadata(transfer_ref) ); fungible_asset::transfer_with_ref( transfer_ref, from_primary_store, to_primary_store, - amount, + amount ); // create cosmos side account @@ -476,7 +477,7 @@ module initia_std::primary_fungible_store { string::utf8(b"@T"), 0, string::utf8(b"http://example.com/icon"), - string::utf8(b"http://example.com"), + string::utf8(b"http://example.com") ); let mint_ref = generate_mint_ref(constructor_ref); let burn_ref = generate_burn_ref(constructor_ref); @@ -492,11 +493,11 @@ module initia_std::primary_fungible_store { let aaron_address = signer::address_of(aaron); assert!( !primary_store_exists(creator_address, metadata), - 1, + 1 ); assert!( !primary_store_exists(aaron_address, metadata), - 2, + 2 ); assert!(balance(creator_address, metadata) == 0, 3); assert!(balance(aaron_address, metadata) == 0, 4); @@ -506,16 +507,16 @@ module initia_std::primary_fungible_store { ensure_primary_store_exists(aaron_address, metadata); assert!( primary_store_exists(creator_address, metadata), - 7, + 7 ); assert!( primary_store_exists(aaron_address, metadata), - 8, + 8 ); } #[test(creator = @0xcafe, aaron = @0xface)] - fun test_basic_flow(creator: &signer, aaron: &signer,) acquires DeriveRefPod, ModuleStore { + fun test_basic_flow(creator: &signer, aaron: &signer) acquires DeriveRefPod, ModuleStore { let (creator_ref, metadata) = create_test_token(creator); let (mint_ref, transfer_ref, burn_ref) = init_test_metadata_with_primary_store_enabled(&creator_ref); @@ -537,7 +538,7 @@ module initia_std::primary_fungible_store { &transfer_ref, aaron_address, creator_address, - 20, + 20 ); set_frozen_flag(&transfer_ref, aaron_address, false); assert!(!is_frozen(aaron_address, metadata), 6); diff --git a/initia_stdlib/sources/fixed_point64.move b/initia_stdlib/sources/fixed_point64.move index c83d8df..6cff2d2 100644 --- a/initia_stdlib/sources/fixed_point64.move +++ b/initia_stdlib/sources/fixed_point64.move @@ -17,6 +17,7 @@ module initia_std::fixed_point64 { } const MAX_U128: u256 = 340282366920938463463374607431768211455; + const MAX_U64: u128 = 18446744073709551615; /// The denominator provided was zero const EDENOMINATOR: u64 = 0x10001; @@ -28,6 +29,86 @@ module initia_std::fixed_point64 { const EDIVISION_BY_ZERO: u64 = 0x10004; /// The computed ratio when converting to a `FixedPoint64` would be unrepresentable const ERATIO_OUT_OF_RANGE: u64 = 0x20005; + /// Abort code on calculation result is negative. + const ENEGATIVE_RESULT: u64 = 0x10006; + + public fun one(): FixedPoint64 { + create_from_raw_value(1 << 64) + } + + public fun zero(): FixedPoint64 { + create_from_raw_value(0) + } + + public fun rev(self: FixedPoint64): FixedPoint64 { + create_from_raw_value(((1u256 << 128) / (get_raw_value(self) as u256) as u128)) + } + + /// Returns self - y. self must be not less than y. + public fun sub(self: FixedPoint64, y: FixedPoint64): FixedPoint64 { + let x_raw = get_raw_value(self); + let y_raw = get_raw_value(y); + assert!(x_raw >= y_raw, ENEGATIVE_RESULT); + create_from_raw_value(x_raw - y_raw) + } + + public fun sub_u64(self: FixedPoint64, y: u64): FixedPoint64 { + sub_u128(self, (y as u128)) + } + + public fun sub_u128(self: FixedPoint64, y: u128): FixedPoint64 { + let x_raw = (get_raw_value(self) as u256); + let y_raw = (y as u256) << 64; + assert!(x_raw >= y_raw, ENEGATIVE_RESULT); + create_from_raw_value(((x_raw - y_raw) as u128)) + } + + spec sub { + pragma opaque; + aborts_if self.value < y.value with ENEGATIVE_RESULT; + ensures result.value == self.value - y.value; + } + + /// Returns self + y. The result cannot be greater than MAX_U128. + public fun add(self: FixedPoint64, y: FixedPoint64): FixedPoint64 { + let x_raw = get_raw_value(self); + let y_raw = get_raw_value(y); + let result = (x_raw as u256) + (y_raw as u256); + assert!(result <= MAX_U128, ERATIO_OUT_OF_RANGE); + create_from_raw_value((result as u128)) + } + + public fun add_u64(self: FixedPoint64, y: u64): FixedPoint64 { + add_u128(self, (y as u128)) + } + + public fun add_u128(self: FixedPoint64, y: u128): FixedPoint64 { + let x_raw = (get_raw_value(self) as u256); + let y_raw = (y as u256) << 64; + let result = x_raw + y_raw; + assert!(result <= MAX_U128, ERATIO_OUT_OF_RANGE); + create_from_raw_value((result as u128)) + } + + spec add { + pragma opaque; + aborts_if (self.value as u256) + (y.value as u256) > MAX_U128 with ERATIO_OUT_OF_RANGE; + ensures result.value == self.value + y.value; + } + + public fun multiply(self: FixedPoint64, y: FixedPoint64): FixedPoint64 { + let x_raw = get_raw_value(self); + let y_raw = get_raw_value(y); + let result = ((x_raw as u256) * (y_raw as u256)) >> 64; + assert!(result <= MAX_U128, EMULTIPLICATION); + create_from_raw_value((result as u128)) + } + + public fun multiply_u64(val: u64, multiplier: FixedPoint64): u64 { + let res = multiply_u128((val as u128), multiplier); + assert!(res <= MAX_U64, EMULTIPLICATION); + (res as u64) + } /// Multiply a u128 integer by a fixed-point number, truncating any /// fractional part of the product. This will abort if the product @@ -61,6 +142,29 @@ module initia_std::fixed_point64 { (val * multiplier.value) >> 64 } + public fun divide(self: FixedPoint64, divisor: FixedPoint64): FixedPoint64 { + // Check for division by zero. + assert!(divisor.value != 0, EDIVISION_BY_ZERO); + // Perform the division with 256 bits to avoid losing accuracy. + let result = ((self.value as u256) << 64) / (divisor.value as u256); + assert!(result <= MAX_U128, EDIVISION); + create_from_raw_value((result as u128)) + } + + /// Divide a u64 integer by a fixed-point number, truncating any + /// fractional part of the quotient. This will abort if the divisor + /// is zero or if the quotient overflows. + public fun divide_u64(val: u64, divisor: FixedPoint64): u64 { + let res = divide_u128((val as u128), divisor); + assert!(res <= MAX_U64, EDIVISION); + (res as u64) + } + + /// Divide a fixed-point number by a u64 integer. + public fun divide_by_u64(val: FixedPoint64, divisor: u64): FixedPoint64 { + divide_by_u128(val, (divisor as u128)) + } + /// Divide a u128 integer by a fixed-point number, truncating any /// fractional part of the quotient. This will abort if the divisor /// is zero or if the quotient overflows. @@ -78,6 +182,13 @@ module initia_std::fixed_point64 { (quotient as u128) } + /// Divide a fixed-point number by a u128 integer. + public fun divide_by_u128(val: FixedPoint64, divisor: u128): FixedPoint64 { + // Check for division by zero. + assert!(divisor != 0, EDIVISION_BY_ZERO); + create_from_raw_value(get_raw_value(val) / divisor) + } + spec divide_u128 { pragma opaque; include DivideAbortsIf; @@ -112,10 +223,7 @@ module initia_std::fixed_point64 { let scaled_numerator = (numerator as u256) << 64; assert!(denominator != 0, EDENOMINATOR); let quotient = scaled_numerator / (denominator as u256); - assert!( - quotient != 0 || numerator == 0, - ERATIO_OUT_OF_RANGE, - ); + assert!(quotient != 0 || numerator == 0, ERATIO_OUT_OF_RANGE); // Return the quotient as a fixed-point number. We first need to check whether the cast // can succeed. assert!(quotient <= MAX_U128, ERATIO_OUT_OF_RANGE); @@ -124,7 +232,7 @@ module initia_std::fixed_point64 { spec create_from_rational { pragma opaque; - pragma verify = false; // TODO: set to false because of timeout (property proved). + pragma verify_duration_estimate = 1000; // TODO: set because of timeout (property proved). include CreateFromRationalAbortsIf; ensures result == spec_create_from_rational(numerator, denominator); } @@ -141,7 +249,9 @@ module initia_std::fixed_point64 { } spec fun spec_create_from_rational(numerator: num, denominator: num): FixedPoint64 { - FixedPoint64 { value: (numerator << 128) / (denominator << 64) } + FixedPoint64 { + value: (numerator << 128) / (denominator << 64) + } } /// Create a fixedpoint value from a raw value. @@ -158,13 +268,13 @@ module initia_std::fixed_point64 { /// Accessor for the raw u128 value. Other less common operations, such as /// adding or subtracting FixedPoint64 values, can be done using the raw /// values directly. - public fun get_raw_value(num: FixedPoint64): u128 { - num.value + public fun get_raw_value(self: FixedPoint64): u128 { + self.value } /// Returns true if the ratio is zero. - public fun is_zero(num: FixedPoint64): bool { - num.value == 0 + public fun is_zero(self: FixedPoint64): bool { + self.value == 0 } /// Returns the smaller of the two FixedPoint64 numbers. @@ -201,6 +311,106 @@ module initia_std::fixed_point64 { else { num2 } } + /// Returns true if self <= num2 + public fun less_or_equal(self: FixedPoint64, num2: FixedPoint64): bool { + self.value <= num2.value + } + + spec less_or_equal { + pragma opaque; + aborts_if false; + ensures result == spec_less_or_equal(self, num2); + } + + spec fun spec_less_or_equal(self: FixedPoint64, num2: FixedPoint64): bool { + self.value <= num2.value + } + + /// Returns true if self < num2 + public fun less(self: FixedPoint64, num2: FixedPoint64): bool { + self.value < num2.value + } + + spec less { + pragma opaque; + aborts_if false; + ensures result == spec_less(self, num2); + } + + spec fun spec_less(self: FixedPoint64, num2: FixedPoint64): bool { + self.value < num2.value + } + + /// Returns true if self >= num2 + public fun greater_or_equal(self: FixedPoint64, num2: FixedPoint64): bool { + self.value >= num2.value + } + + spec greater_or_equal { + pragma opaque; + aborts_if false; + ensures result == spec_greater_or_equal(self, num2); + } + + spec fun spec_greater_or_equal(self: FixedPoint64, num2: FixedPoint64): bool { + self.value >= num2.value + } + + /// Returns true if self > num2 + public fun greater(self: FixedPoint64, num2: FixedPoint64): bool { + self.value > num2.value + } + + spec greater { + pragma opaque; + aborts_if false; + ensures result == spec_greater(self, num2); + } + + spec fun spec_greater(self: FixedPoint64, num2: FixedPoint64): bool { + self.value > num2.value + } + + /// Returns true if self = num2 + public fun equal(self: FixedPoint64, num2: FixedPoint64): bool { + self.value == num2.value + } + + spec equal { + pragma opaque; + aborts_if false; + ensures result == spec_equal(self, num2); + } + + spec fun spec_equal(self: FixedPoint64, num2: FixedPoint64): bool { + self.value == num2.value + } + + /// Returns true if self almost equals to num2, which means abs(num1-num2) <= precision + public fun almost_equal( + self: FixedPoint64, num2: FixedPoint64, precision: FixedPoint64 + ): bool { + if (self.value > num2.value) { + (self.value - num2.value <= precision.value) + } else { + (num2.value - self.value <= precision.value) + } + } + + spec almost_equal { + pragma opaque; + aborts_if false; + ensures result == spec_almost_equal(self, num2, precision); + } + + spec fun spec_almost_equal(self: FixedPoint64, num2: FixedPoint64, precision: FixedPoint64): bool { + if (self.value > num2.value) { + (self.value - num2.value <= precision.value) + } else { + (num2.value - self.value <= precision.value) + } + } + /// Create a fixedpoint value from a u128 value. public fun create_from_u128(val: u128): FixedPoint64 { let value = (val as u256) << 64; @@ -225,29 +435,29 @@ module initia_std::fixed_point64 { } /// Returns the largest integer less than or equal to a given number. - public fun floor(num: FixedPoint64): u128 { - num.value >> 64 + public fun floor(self: FixedPoint64): u128 { + self.value >> 64 } spec floor { pragma opaque; aborts_if false; - ensures result == spec_floor(num); + ensures result == spec_floor(self); } - spec fun spec_floor(val: FixedPoint64): u128 { - let fractional = val.value % (1 << 64); + spec fun spec_floor(self: FixedPoint64): u128 { + let fractional = self.value % (1 << 64); if (fractional == 0) { - val.value >> 64 + self.value >> 64 } else { - (val.value - fractional) >> 64 + (self.value - fractional) >> 64 } } /// Rounds up the given FixedPoint64 to the next largest integer. - public fun ceil(num: FixedPoint64): u128 { - let floored_num = floor(num) << 64; - if (num.value == floored_num) { + public fun ceil(self: FixedPoint64): u128 { + let floored_num = floor(self) << 64; + if (self.value == floored_num) { return floored_num >> 64 }; let val = ((floored_num as u256) + (1 << 64)); @@ -255,48 +465,48 @@ module initia_std::fixed_point64 { } spec ceil { - /// TODO: worked in the past but started to time out since last z3 update - pragma verify = false; + // TODO: set because of timeout (property proved). + pragma verify_duration_estimate = 1000; pragma opaque; aborts_if false; - ensures result == spec_ceil(num); + ensures result == spec_ceil(self); } - spec fun spec_ceil(val: FixedPoint64): u128 { - let fractional = val.value % (1 << 64); + spec fun spec_ceil(self: FixedPoint64): u128 { + let fractional = self.value % (1 << 64); let one = 1 << 64; if (fractional == 0) { - val.value >> 64 + self.value >> 64 } else { - (val.value - fractional + one) >> 64 + (self.value - fractional + one) >> 64 } } /// Returns the value of a FixedPoint64 to the nearest integer. - public fun round(num: FixedPoint64): u128 { - let floored_num = floor(num) << 64; + public fun round(self: FixedPoint64): u128 { + let floored_num = floor(self) << 64; let boundary = floored_num + ((1 << 64) / 2); - if (num.value < boundary) { + if (self.value < boundary) { floored_num >> 64 } else { - ceil(num) + ceil(self) } } spec round { pragma opaque; aborts_if false; - ensures result == spec_round(num); + ensures result == spec_round(self); } - spec fun spec_round(val: FixedPoint64): u128 { - let fractional = val.value % (1 << 64); + spec fun spec_round(self: FixedPoint64): u128 { + let fractional = self.value % (1 << 64); let boundary = (1 << 64) / 2; let one = 1 << 64; if (fractional < boundary) { - (val.value - fractional) >> 64 + (self.value - fractional) >> 64 } else { - (val.value - fractional + one) >> 64 + (self.value - fractional + one) >> 64 } } @@ -307,4 +517,172 @@ module initia_std::fixed_point64 { spec module { pragma aborts_if_is_strict; } + + #[test] + public entry fun test_sub() { + let x = create_from_rational(9, 7); + let y = create_from_rational(1, 3); + let result = sub(x, y); + // 9/7 - 1/3 = 20/21 + let expected_result = create_from_rational(20, 21); + assert_approx_the_same( + (get_raw_value(result) as u256), + (get_raw_value(expected_result) as u256), + 16 + ); + } + + #[test] + #[expected_failure(abort_code = 0x10006, location = Self)] + public entry fun test_sub_should_abort() { + let x = create_from_rational(1, 3); + let y = create_from_rational(9, 7); + let _ = sub(x, y); + } + + #[test_only] + /// For functions that approximate a value it's useful to test a value is close + /// to the most correct value up to last digit + fun assert_approx_the_same(x: u256, y: u256, precission: u128) { + if (x < y) { + let tmp = x; + x = y; + y = tmp; + }; + let mult = 1u256; + let n = 10u256; + while (precission > 0) { + if (precission % 2 == 1) { + mult = mult * n; + }; + precission = precission / 2; + n = n * n; + }; + assert!((x - y) * mult < x, 0); + } + + #[test] + public entry fun test_div() { + let x = create_from_rational(9, 7); + let y = create_from_rational(1, 3); + let result = divide(x, y); + // 9/7 / 1/3 = 27/7 + let expected_result = create_from_rational(27, 7); + assert_approx_the_same( + (get_raw_value(result) as u256), + (get_raw_value(expected_result) as u256), + 16 + ); + } + + #[test] + public entry fun test_div_u64() { + let x = create_from_rational(9, 7); + let y = 3u64; + let result = divide_u64(y, x); + // 3 / 9/7 = 21/9 + let expected_result = create_from_rational(21, 9); + assert_approx_the_same( + (result as u256), + (get_raw_value(expected_result) as u256) >> 64, + 16 + ); + } + + #[test] + public entry fun test_div_u128() { + let x = create_from_rational(9, 7); + let y = 3u128; + let result = divide_u128(y, x); + // 3 / 9/7 = 21/9 + let expected_result = create_from_rational(21, 9); + assert_approx_the_same( + (result as u256), + (get_raw_value(expected_result) as u256) >> 64, + 16 + ); + } + + #[test] + public entry fun test_multiply() { + let x = create_from_rational(9, 7); + let y = create_from_rational(1, 3); + let result = multiply(x, y); + // 9/7 * 1/3 = 3/7 + let expected_result = create_from_rational(3, 7); + assert_approx_the_same( + (get_raw_value(result) as u256), + (get_raw_value(expected_result) as u256), + 16 + ); + } + + #[test] + public entry fun test_multiply_u64() { + let x = create_from_rational(9, 7); + let y = 3u64; + let result = multiply_u64(y, x); + // 3 * 9/7 = 27/7 + let expected_result = create_from_rational(27, 7); + assert_approx_the_same( + (result as u256), + (get_raw_value(expected_result) as u256) >> 64, + 16 + ); + } + + #[test] + public entry fun test_multiply_u128() { + let x = create_from_rational(9, 7); + let y = 3u128; + let result = multiply_u128(y, x); + // 3 * 9/7 = 27/7 + let expected_result = create_from_rational(27, 7); + assert_approx_the_same( + (result as u256), + (get_raw_value(expected_result) as u256) >> 64, + 16 + ); + } + + #[test] + public entry fun test_rev() { + let x = create_from_rational(9, 7); + let result = rev(x); + // 1 / 9/7 = 7/9 + let expected_result = create_from_rational(7, 9); + assert_approx_the_same( + (get_raw_value(result) as u256), + (get_raw_value(expected_result) as u256), + 16 + ); + } + + #[test] + public entry fun test_divide_by_u64() { + let x = create_from_rational(9, 7); + let y = 3u64; + let result = divide_by_u64(x, y); + // 9/7 / 3 = 3/7 + let expected_result = create_from_rational(3, 7); + assert_approx_the_same( + (get_raw_value(result) as u256), + (get_raw_value(expected_result) as u256), + 16 + ); + } + + #[test] + public entry fun test_divide_by_u128() { + let x = create_from_rational(9, 7); + let y = 3u128; + let result = divide_by_u128(x, y); + // 9/7 / 3 = 3/7 + let expected_result = create_from_rational(3, 7); + assert_approx_the_same( + (get_raw_value(result) as u256), + (get_raw_value(expected_result) as u256), + 16 + ); + } } diff --git a/initia_stdlib/sources/from_bcs.move b/initia_stdlib/sources/from_bcs.move index cbb160e..8fe7854 100644 --- a/initia_stdlib/sources/from_bcs.move +++ b/initia_stdlib/sources/from_bcs.move @@ -64,9 +64,9 @@ module initia_std::from_bcs { |s| { assert!( string::internal_check_utf8(string::bytes(s)), - EINVALID_UTF8, + EINVALID_UTF8 ); - }, + } ); vec_string } @@ -76,7 +76,7 @@ module initia_std::from_bcs { let s = from_bytes(v); assert!( string::internal_check_utf8(string::bytes(&s)), - EINVALID_UTF8, + EINVALID_UTF8 ); s } diff --git a/initia_stdlib/sources/function_info.move b/initia_stdlib/sources/function_info.move index fbd5da4..bc37445 100644 --- a/initia_stdlib/sources/function_info.move +++ b/initia_stdlib/sources/function_info.move @@ -17,36 +17,32 @@ module initia_std::function_info { struct FunctionInfo has copy, drop, store { module_address: address, module_name: String, - function_name: String, + function_name: String } /// Creates a new function info from names. public fun new_function_info( - module_signer: &signer, - module_name: String, - function_name: String, + module_signer: &signer, module_name: String, function_name: String ): FunctionInfo { new_function_info_from_address( signer::address_of(module_signer), module_name, - function_name, + function_name ) } public(friend) fun new_function_info_from_address( - module_address: address, - module_name: String, - function_name: String, + module_address: address, module_name: String, function_name: String ): FunctionInfo { assert!( is_identifier(string::bytes(&module_name)), - EINVALID_IDENTIFIER, + EINVALID_IDENTIFIER ); assert!( is_identifier(string::bytes(&function_name)), - EINVALID_IDENTIFIER, + EINVALID_IDENTIFIER ); - FunctionInfo { module_address, module_name, function_name, } + FunctionInfo { module_address, module_name, function_name } } /// Check if the dispatch target function meets the type requirements of the disptach entry point. @@ -60,7 +56,7 @@ module initia_std::function_info { /// /// dispatch_target also needs to be public so the type signature will remain unchanged. public(friend) fun check_dispatch_type_compatibility( - framework_function: &FunctionInfo, dispatch_target: &FunctionInfo, + framework_function: &FunctionInfo, dispatch_target: &FunctionInfo ): bool { load_function_impl(dispatch_target); check_dispatch_type_compatibility_impl(framework_function, dispatch_target) @@ -79,7 +75,9 @@ module initia_std::function_info { load_function_impl(f) } - native fun check_dispatch_type_compatibility_impl(lhs: &FunctionInfo, r: &FunctionInfo): bool; + native fun check_dispatch_type_compatibility_impl( + lhs: &FunctionInfo, r: &FunctionInfo + ): bool; native fun is_identifier(s: &vector): bool; native fun load_function_impl(f: &FunctionInfo); diff --git a/initia_stdlib/sources/hex.move b/initia_stdlib/sources/hex.move index 4e6bbd2..a4c0050 100644 --- a/initia_stdlib/sources/hex.move +++ b/initia_stdlib/sources/hex.move @@ -36,11 +36,11 @@ module initia_std::hex { let val = *vector::borrow(bz, index); vector::push_back( &mut vec, - encode_to_char_with_option(val / 0x10, is_upper), + encode_to_char_with_option(val / 0x10, is_upper) ); vector::push_back( &mut vec, - encode_to_char_with_option(val % 0x10, is_upper), + encode_to_char_with_option(val % 0x10, is_upper) ); index = index + 1; }; @@ -52,7 +52,7 @@ module initia_std::hex { public fun decode_string(str: &String): vector { assert!( is_hex_string(str), - error::invalid_argument(ENOT_HEXSTRING), + error::invalid_argument(ENOT_HEXSTRING) ); let vec: vector = vector[]; @@ -128,12 +128,13 @@ module initia_std::hex { } fun is_hex_char(char: u8): bool { - if ((char >= ZERO + if ( + (char >= ZERO && char <= ZERO + 9) // 0 - 9 - || (char >= UPPERA - && char <= UPPERA + 5) // A - F - || (char >= LOWERA - && char <= LOWERA + 5)) { // a - f + || (char >= UPPERA + && char <= UPPERA + 5) // A - F + || (char >= LOWERA + && char <= LOWERA + 5)) { // a - f return true }; false @@ -145,7 +146,7 @@ module initia_std::hex { let hex_string = encode_to_string(&raw_bytes); assert!( *string::bytes(&hex_string) == b"68656c6c6f20776f726c6421", - 0, + 0 ); // test odd bytes diff --git a/initia_stdlib/sources/json.move b/initia_stdlib/sources/json.move index 76f69b9..0aa2a8a 100644 --- a/initia_stdlib/sources/json.move +++ b/initia_stdlib/sources/json.move @@ -1,5 +1,76 @@ module initia_std::json { - use std::string::String; + use std::vector; + use std::string::{Self, String}; + use std::option::{Self, Option}; + + /// JSONValue is a struct to hold any JSON value which is unknown at compile time. + struct JSONValue has copy, drop { + value: vector + } + + /// JSONObject is a struct to hold any json object which is unknown at compile time. + struct JSONObject has copy, drop { + elems: vector + } + + /// Element is a struct to hold key-value pair in JSON object. + struct Element has copy, drop { + key: vector, + value: vector + } + + /// Unmarshal JSON value to the given type. + public fun unmarshal_json_value(json_value: JSONValue): T { + unmarshal(json_value.value) + } + + /// Get the list of keys from the JSON object. + public fun keys(obj: &JSONObject): vector { + vector::map_ref(&obj.elems, |elem| { + use_elem(elem); + string::utf8(elem.key) + }) + } + + /// Get the value of the given key from the JSON object. + public fun get_elem(obj: &JSONObject, key: String): Option { + let key_bytes = string::bytes(&key); + let (found, idx) = vector::find(&obj.elems, |elem| { + use_elem(elem); + elem.key == *key_bytes + }); + + if (!found) { + return option::none() + }; + + let elem = vector::borrow(&obj.elems, idx); + option::some(unmarshal(elem.value)) + } + + /// Set or overwrite the element in the JSON object. + public fun set_elem(obj: &mut JSONObject, key: String, value: &T) { + let key_bytes = string::bytes(&key); + let (found, idx) = vector::find(&obj.elems, |elem| { + use_elem(elem); + elem.key == *key_bytes + }); + + if (!found) { + vector::push_back(&mut obj.elems, Element { + key: *key_bytes, + value: marshal(value) + }); + } else { + let elem = vector::borrow_mut(&mut obj.elems, idx); + elem.value = marshal(value); + } + } + + // + // (only on compiler v1) for preventing compile error; because of inferring type issue + // + inline fun use_elem(_elem: &Element) {} /// Marshal data to JSON bytes. /// @@ -20,16 +91,10 @@ module initia_std::json { native public fun unmarshal(json: vector): T; #[test_only] - use std::string; - - #[test_only] - use std::option::{Self, Option}; + use std::biguint::{Self, BigUint}; #[test_only] - use std::decimal128::{Self, Decimal128}; - - #[test_only] - use std::decimal256::{Self, Decimal256}; + use std::bigdecimal::{Self, BigDecimal}; #[test_only] struct TestObject has copy, drop { @@ -41,15 +106,27 @@ module initia_std::json { f: Option, _type_: String, _move_: String, - decimal128: Decimal128, - decimal256: Decimal256, + biguint: BigUint, + bigdecimal: BigDecimal } #[test_only] struct TestObject2 has copy, drop { a: u64, b: bool, - c: vector, + c: vector + } + + #[test_only] + struct EmptyObject has copy, drop {} + + #[test] + fun test_empty_marshal_unmarshal_empty() { + let json = marshal(&EmptyObject {}); + assert!(json == b"{}", 1); + + let val = unmarshal(json); + assert!(val == EmptyObject {}, 2); } #[test] @@ -78,28 +155,47 @@ module initia_std::json { c: vector[1, 2, 3], d: @0x1, e: option::some( - TestObject2 { a: 42, b: true, c: vector[1, 2, 3], }, + TestObject2 { a: 42, b: true, c: vector[1, 2, 3] } ), f: option::none(), _type_: string::utf8(b"/cosmos.gov.v1.MsgVote"), _move_: string::utf8(b"move"), - decimal128: decimal128::from_ratio(1, 100), - decimal256: decimal256::from_ratio(123, 10000), + biguint: biguint::from_u64(42), + bigdecimal: bigdecimal::from_ratio_u64(123, 10000) }; let json = marshal(&obj); assert!( json - == b"{\"@type\":\"/cosmos.gov.v1.MsgVote\",\"a\":\"42\",\"b\":true,\"c\":\"010203\",\"d\":\"0x1\",\"decimal128\":\"0.01\",\"decimal256\":\"0.0123\",\"e\":{\"a\":\"42\",\"b\":true,\"c\":\"010203\"},\"f\":null,\"move\":\"move\"}", - 1, + == b"{\"@type\":\"/cosmos.gov.v1.MsgVote\",\"a\":\"42\",\"b\":true,\"bigdecimal\":\"0.0123\",\"biguint\":\"42\",\"c\":\"010203\",\"d\":\"0x1\",\"e\":{\"a\":\"42\",\"b\":true,\"c\":\"010203\"},\"f\":null,\"move\":\"move\"}", + 1 ); let obj2 = unmarshal(json); let json2 = marshal(&obj2); - assert!( - json2 - == b"{\"@type\":\"/cosmos.gov.v1.MsgVote\",\"a\":\"42\",\"b\":true,\"c\":\"010203\",\"d\":\"0x1\",\"decimal128\":\"0.01\",\"decimal256\":\"0.0123\",\"e\":{\"a\":\"42\",\"b\":true,\"c\":\"010203\"},\"f\":null,\"move\":\"move\"}", - 1, - ); + assert!(json2 == json, 1); + + let json_val = unmarshal(json); + let json3 = marshal(&json_val); + assert!(json3 == json, 2); + + let obj3 = unmarshal_json_value(json_val); + let json4 = marshal(&obj3); + assert!(json4 == json, 3); + + let json_obj = unmarshal(json); + let json5 = marshal(&json_obj); + assert!(json5 == json, 4); + + assert!(option::extract(&mut get_elem(&json_obj, string::utf8(b"a"))) == 42, 4); + assert!(option::extract(&mut get_elem(&json_obj, string::utf8(b"b"))) == true, 5); + assert!(option::extract(&mut get_elem>(&json_obj, string::utf8(b"c"))) == vector[1, 2, 3], 6); + assert!(option::extract(&mut get_elem
(&json_obj, string::utf8(b"d"))) == @0x1, 7); + + set_elem(&mut json_obj, string::utf8(b"c"), &string::utf8(b"hello")); + assert!(option::extract(&mut get_elem(&json_obj, string::utf8(b"c"))) == string::utf8(b"hello"), 8); + + let json5 = marshal(&json_obj); + assert!(json5 == b"{\"@type\":\"/cosmos.gov.v1.MsgVote\",\"a\":\"42\",\"b\":true,\"bigdecimal\":\"0.0123\",\"biguint\":\"42\",\"c\":\"hello\",\"d\":\"0x1\",\"e\":{\"a\":\"42\",\"b\":true,\"c\":\"010203\"},\"f\":null,\"move\":\"move\"}", 9); } } diff --git a/initia_stdlib/sources/keccak.move b/initia_stdlib/sources/keccak.move index c9f2f8a..a9770ec 100644 --- a/initia_stdlib/sources/keccak.move +++ b/initia_stdlib/sources/keccak.move @@ -12,11 +12,12 @@ module initia_std::keccak { #[test] fun keccak256_test() { - let inputs = vector[b"testing", b"",]; + let inputs = vector[b"testing", b""]; let outputs = vector[ x"5f16f4c7f149ac4f9510d9cf8cf384038ad348b3bcdc01915f95de12df9d1b02", - x"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",]; + x"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + ]; let i = 0; while (i < std::vector::length(&inputs)) { diff --git a/initia_stdlib/sources/managed_coin.move b/initia_stdlib/sources/managed_coin.move index c6cb24f..6a90072 100644 --- a/initia_stdlib/sources/managed_coin.move +++ b/initia_stdlib/sources/managed_coin.move @@ -30,7 +30,7 @@ module initia_std::managed_coin { struct Capabilities has key { mint_cap: MintCapability, burn_cap: BurnCapability, - freeze_cap: FreezeCapability, + freeze_cap: FreezeCapability } // @@ -40,7 +40,7 @@ module initia_std::managed_coin { fun check_sudo(account: &signer) { assert!( signer::address_of(account) == @initia_std, - error::permission_denied(EUNAUTHORIZED), + error::permission_denied(EUNAUTHORIZED) ); } @@ -49,20 +49,20 @@ module initia_std::managed_coin { account: &signer, dst_addr: address, metadata: Object, - amount: u64, + amount: u64 ) acquires Capabilities { check_sudo(account); let account_addr = signer::address_of(account); assert!( object::is_owner(metadata, account_addr), - error::not_found(EUNAUTHORIZED), + error::not_found(EUNAUTHORIZED) ); let object_addr = object::object_address(&metadata); assert!( exists(object_addr), - error::not_found(ENO_CAPABILITIES), + error::not_found(ENO_CAPABILITIES) ); let capabilities = borrow_global(object_addr); @@ -83,7 +83,7 @@ module initia_std::managed_coin { symbol: String, decimals: u8, icon_uri: String, - project_uri: String, + project_uri: String ) { let (mint_cap, burn_cap, freeze_cap, extend_ref) = coin::initialize_and_generate_extend_ref( @@ -93,33 +93,31 @@ module initia_std::managed_coin { symbol, decimals, icon_uri, - project_uri, + project_uri ); let metadata_signer = object::generate_signer_for_extending(&extend_ref); move_to( &metadata_signer, - Capabilities { mint_cap, burn_cap, freeze_cap, }, + Capabilities { mint_cap, burn_cap, freeze_cap } ); } /// Withdraw an `amount` of metadata coin from `account` and burn it. public entry fun burn( - account: &signer, - metadata: Object, - amount: u64, + account: &signer, metadata: Object, amount: u64 ) acquires Capabilities { let account_addr = signer::address_of(account); assert!( object::is_owner(metadata, account_addr), - error::not_found(EUNAUTHORIZED), + error::not_found(EUNAUTHORIZED) ); let object_addr = object::object_address(&metadata); assert!( exists(object_addr), - error::not_found(ENO_CAPABILITIES), + error::not_found(ENO_CAPABILITIES) ); let capabilities = borrow_global(object_addr); @@ -130,21 +128,19 @@ module initia_std::managed_coin { /// Create new metadata coins. public fun mint( - account: &signer, - metadata: Object, - amount: u64, + account: &signer, metadata: Object, amount: u64 ): FungibleAsset acquires Capabilities { let account_addr = signer::address_of(account); assert!( object::is_owner(metadata, account_addr), - error::not_found(EUNAUTHORIZED), + error::not_found(EUNAUTHORIZED) ); let object_addr = object::object_address(&metadata); assert!( exists(object_addr), - error::not_found(ENO_CAPABILITIES), + error::not_found(ENO_CAPABILITIES) ); let capabilities = borrow_global(object_addr); @@ -156,7 +152,7 @@ module initia_std::managed_coin { account: &signer, dst_addr: address, metadata: Object, - amount: u64, + amount: u64 ) acquires Capabilities { let fa = mint(account, metadata, amount); @@ -200,7 +196,7 @@ module initia_std::managed_coin { string::utf8(TEST_SYMBOL), 10, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); let metadata = test_metadata(); @@ -210,18 +206,18 @@ module initia_std::managed_coin { &mod_account, source_addr, metadata, - 50, + 50 ); mint_to( &mod_account, destination_addr, metadata, - 10, + 10 ); assert!(coin::balance(source_addr, metadata) == 50, 1); assert!( coin::balance(destination_addr, metadata) == 10, - 2, + 2 ); let supply = coin::supply(metadata); @@ -231,19 +227,19 @@ module initia_std::managed_coin { &source, destination_addr, metadata, - 10, + 10 ); assert!(coin::balance(source_addr, metadata) == 40, 3); assert!( coin::balance(destination_addr, metadata) == 20, - 4, + 4 ); coin::transfer( &source, signer::address_of(&mod_account), metadata, - 40, + 40 ); burn(&mod_account, metadata, 40); @@ -256,9 +252,7 @@ module initia_std::managed_coin { #[test(source = @0xa11ce, destination = @0xb0b, mod_account = @0x1)] #[expected_failure(abort_code = 0x60002, location = Self)] public entry fun fail_mint( - source: signer, - destination: signer, - mod_account: signer, + source: signer, destination: signer, mod_account: signer ) acquires Capabilities { primary_fungible_store::init_module_for_test(); @@ -271,7 +265,7 @@ module initia_std::managed_coin { string::utf8(TEST_SYMBOL), 10, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); let metadata = test_metadata(); @@ -279,16 +273,14 @@ module initia_std::managed_coin { &destination, source_addr, metadata, - 100, + 100 ); } #[test(source = @0xa11ce, destination = @0xb0b, mod_account = @0x1)] #[expected_failure(abort_code = 0x60002, location = Self)] public entry fun fail_burn( - source: signer, - destination: signer, - mod_account: signer, + source: signer, destination: signer, mod_account: signer ) acquires Capabilities { primary_fungible_store::init_module_for_test(); @@ -301,7 +293,7 @@ module initia_std::managed_coin { string::utf8(TEST_SYMBOL), 10, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); let metadata = test_metadata(); @@ -309,7 +301,7 @@ module initia_std::managed_coin { &mod_account, source_addr, metadata, - 100, + 100 ); burn(&destination, metadata, 10); } diff --git a/initia_stdlib/sources/math128.move b/initia_stdlib/sources/math128.move index 81a1614..5fdf088 100644 --- a/initia_stdlib/sources/math128.move +++ b/initia_stdlib/sources/math128.move @@ -60,7 +60,7 @@ module initia_std::math128 { let res = 0; assert!( x != 0, - std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2), + std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2) ); // Effectively the position of the most significant set bit let n = 64; @@ -167,9 +167,9 @@ module initia_std::math128 { assert!( ceil_div( (((1u256 << 128) - 9) as u128), - 11, + 11 ) == 30934760629176223951215873402888019223, - 0, + 0 ); } @@ -232,10 +232,8 @@ module initia_std::math128 { idx = 1; while (idx <= 128) { assert!( - floor_log2( - (((1u256 << idx) - 1) as u128) - ) == idx - 1, - 0, + floor_log2((((1u256 << idx) - 1) as u128)) == idx - 1, + 0 ); idx = idx + 1; }; @@ -248,7 +246,7 @@ module initia_std::math128 { let res = log2(1 << idx); assert!( fixed_point32::get_raw_value(res) == (idx as u64) << 32, - 0, + 0 ); idx = idx + 1; }; @@ -267,7 +265,7 @@ module initia_std::math128 { assert_approx_the_same( (fixed_point32::get_raw_value(res) as u128), expected, - 8, + 8 ); idx = idx + 1; }; @@ -280,15 +278,13 @@ module initia_std::math128 { let res = log2_64(1 << idx); assert!( fixed_point64::get_raw_value(res) == (idx as u128) << 64, - 0, + 0 ); idx = idx + 1; }; idx = 10; while (idx <= 128) { - let res = log2_64( - (((1u256 << idx) - 1) as u128) - ); + let res = log2_64((((1u256 << idx) - 1) as u128)); // idx + log2 (1 - 1/2^idx) = idx + ln (1-1/2^idx)/ln2 // Use 3rd order taylor to approximate expected result let expected = (idx as u256) << 64; @@ -304,7 +300,7 @@ module initia_std::math128 { assert_approx_the_same( fixed_point64::get_raw_value(res), (expected as u128), - 14, + 14 ); idx = idx + 1; }; diff --git a/initia_stdlib/sources/math64.move b/initia_stdlib/sources/math64.move index d6c219b..4e92276 100644 --- a/initia_stdlib/sources/math64.move +++ b/initia_stdlib/sources/math64.move @@ -58,7 +58,7 @@ module initia_std::math64 { let res = 0; assert!( x != 0, - std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2), + std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2) ); // Effectively the position of the most significant set bit let n = 32; @@ -140,9 +140,9 @@ module initia_std::math64 { assert!( ceil_div( (((1u128 << 64) - 9) as u64), - 11, + 11 ) == 1676976733973595601, - 0, + 0 ); } @@ -211,10 +211,8 @@ module initia_std::math64 { idx = 1; while (idx <= 64) { assert!( - floor_log2( - (((1u128 << idx) - 1) as u64) - ) == idx - 1, - 0, + floor_log2((((1u128 << idx) - 1) as u64)) == idx - 1, + 0 ); idx = idx + 1; }; @@ -227,7 +225,7 @@ module initia_std::math64 { let res = log2(1 << idx); assert!( fixed_point32::get_raw_value(res) == (idx as u64) << 32, - 0, + 0 ); idx = idx + 1; }; @@ -246,7 +244,7 @@ module initia_std::math64 { assert_approx_the_same( (fixed_point32::get_raw_value(res) as u128), expected, - 8, + 8 ); idx = idx + 1; }; diff --git a/initia_stdlib/sources/minitswap.move b/initia_stdlib/sources/minitswap.move index a2de6e3..b1091c8 100644 --- a/initia_stdlib/sources/minitswap.move +++ b/initia_stdlib/sources/minitswap.move @@ -11,7 +11,7 @@ module initia_std::minitswap { use initia_std::bcs; use initia_std::block; use initia_std::cosmos; - use initia_std::decimal128::{Self, Decimal128}; + use initia_std::bigdecimal::{Self, BigDecimal}; use initia_std::table::{Self, Table}; use initia_std::table_key; use initia_std::object::{Self, ExtendRef, Object}; @@ -59,7 +59,7 @@ module initia_std::minitswap { /// List of pools pools: Table, Pools>, /// Max pool size change rate - max_change_rate: Decimal128, + max_change_rate: BigDecimal, /// If this state is True, every depositor related transaction sent to Minitswap will fail emergency_state: bool, /// admin address who can change emergency_state and pool active @@ -83,14 +83,14 @@ module initia_std::minitswap { /// ANN stableswap_ann: u64, /// swap fee rate - stableswap_swap_fee_rate: Decimal128, + stableswap_swap_fee_rate: BigDecimal, // swap related configs /// Swap fee rate - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal, /// Swap fee rate - arb_fee_rate: Decimal128, + arb_fee_rate: BigDecimal, // in house arb configs @@ -107,7 +107,7 @@ module initia_std::minitswap { /// global arb map. index => Virtual Pool global_arb_batch_map: Table, Object>, /// arb batc index - arb_batch_index: u64, + arb_batch_index: u64 } struct VirtualPool has key { @@ -118,11 +118,11 @@ module initia_std::minitswap { /// Z. Virtual pool size pool_size: u64, /// V. Recover velocity. Real recover amount = Vt - recover_velocity: Decimal128, + recover_velocity: BigDecimal, /// R_max max recover ratio - max_ratio: Decimal128, + max_ratio: BigDecimal, /// f. Flexibility - recover_param: Decimal128, + recover_param: BigDecimal, /// Virtual pool amount of INIT init_pool_amount: u64, /// Virtual pool amount of ibc_op_INIT @@ -151,14 +151,14 @@ module initia_std::minitswap { /// hook contract hook_contract: String, /// ongoing in house arb info - arb_batch_map: Table, ArbInfo>, + arb_batch_map: Table, ArbInfo> } struct Pools has store { op_bridge_id: u64, ibc_channel: String, virtual_pool: Option>, - stableswap_pool: Option>, + stableswap_pool: Option> } struct UnbondEntity has store { @@ -169,7 +169,7 @@ module initia_std::minitswap { // init withdraw amount withdraw_amount: u64, // release timestamp - release_time: u64, + release_time: u64 } struct ArbInfo has store { @@ -180,18 +180,18 @@ module initia_std::minitswap { // amount of ibc op init sent ibc_op_init_sent: u64, // triggering fee - triggering_fee: u64, + triggering_fee: u64 } #[event] /// Event emitted when virtual pool created struct CreatePoolEvent has drop, store { ibc_op_init_metadata: Object, - recover_velocity: Decimal128, + recover_velocity: BigDecimal, pool_size: u64, ann: u64, - max_ratio: Decimal128, - recover_param: Decimal128, + max_ratio: BigDecimal, + recover_param: BigDecimal } #[event] @@ -199,25 +199,25 @@ module initia_std::minitswap { struct ChangePoolSizeEvent has drop, store { ibc_op_init_metadata: Object, pool_size: u64, - depositor_owned_init_increase: u64, + depositor_owned_init_increase: u64 } #[event] /// Event emitted when update param of virtual pool struct UpdatePoolParamsEvent has drop, store { ibc_op_init_metadata: Object, - recover_velocity: Option, + recover_velocity: Option, ann: Option, - max_ratio: Option, - recover_param: Option, - hook_contract: Option, + max_ratio: Option, + recover_param: Option, + hook_contract: Option } #[event] /// Event emitted when provide. struct ProvideEvent has drop, store { provide_amount: u64, - share_amount: u64, + share_amount: u64 } #[event] @@ -226,7 +226,7 @@ module initia_std::minitswap { account: address, share_amount: u64, withdraw_amount: u64, - release_time: u64, + release_time: u64 } #[event] @@ -235,7 +235,7 @@ module initia_std::minitswap { account: address, share_amount: u64, withdraw_amount: u64, - release_time: u64, + release_time: u64 } #[event] @@ -250,14 +250,14 @@ module initia_std::minitswap { init_swap_fee_amount: u64, init_arb_fee_amount: u64, ibc_op_init_swap_fee_amount: u64, - ibc_op_init_arb_fee_amount: u64, + ibc_op_init_arb_fee_amount: u64 } #[event] /// Event emitted when stable swap pool created struct CreateStableswapPoolEvent has drop, store { ibc_op_init_metadata: Object, - pool: Object, + pool: Object } #[event] @@ -268,7 +268,7 @@ module initia_std::minitswap { executed_time: u64, init_used: u64, ibc_op_init_sent: u64, - triggering_fee: u64, + triggering_fee: u64 } #[event] @@ -278,7 +278,7 @@ module initia_std::minitswap { pool: Object, init_used: u64, ibc_op_init_sent: u64, - triggering_fee: u64, + triggering_fee: u64 } #[event] @@ -288,7 +288,7 @@ module initia_std::minitswap { pool: Object, init_used: u64, ibc_op_init_sent: u64, - triggering_fee: u64, + triggering_fee: u64 } fun init_module(chain: &signer) { @@ -303,7 +303,7 @@ module initia_std::minitswap { string::utf8(SYMBOL), 6, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); move_to( @@ -311,7 +311,7 @@ module initia_std::minitswap { ModuleStore { extend_ref, pools: table::new(), - max_change_rate: decimal128::from_ratio(1, 10), // 10% + max_change_rate: bigdecimal::from_ratio_u64(1, 10), // 10% emergency_state: false, admin: @initia_std, depositor_owned_init: 0, @@ -320,17 +320,17 @@ module initia_std::minitswap { mint_cap, burn_cap, stableswap_ann: 3000, - stableswap_swap_fee_rate: decimal128::from_ratio(1, 1000), // 0.1% - swap_fee_rate: decimal128::from_ratio(1, 1000), // 0.1% - arb_fee_rate: decimal128::from_ratio(1, 1000), // 0.1% TODO: set initial value + stableswap_swap_fee_rate: bigdecimal::from_ratio_u64(1, 1000), // 0.1% + swap_fee_rate: bigdecimal::from_ratio_u64(1, 1000), // 0.1% + arb_fee_rate: bigdecimal::from_ratio_u64(1, 1000), // 0.1% TODO: set initial value trigger_fee: 50000, // 0.5 init TODO: set initial value min_arb_profit: 1000000, // 1 init TODO: set initial value ibc_timeout: 60 * 10, // 10 mins max_arb_batch: 20, min_arb_interval: 60 * 60 * 24, // 1 day TODO: set initial value global_arb_batch_map: table::new(), - arb_batch_index: 0, - }, + arb_batch_index: 0 + } ); } @@ -340,13 +340,13 @@ module initia_std::minitswap { #[view] public fun get_pool_amount( - ibc_op_init_metadata: Object, after_peg_keeper_swap: bool, + ibc_op_init_metadata: Object, after_peg_keeper_swap: bool ): (u64, u64) acquires ModuleStore, VirtualPool { let virtual_pool_exists = virtual_pool_exists(ibc_op_init_metadata); assert!( virtual_pool_exists, - error::invalid_argument(EPOOL_NOT_FOUND), + error::invalid_argument(EPOOL_NOT_FOUND) ); let module_store = borrow_global_mut(@initia_std); @@ -361,14 +361,14 @@ module initia_std::minitswap { calc_peg_keeper_swap(pool) } else { (0, 0) }; return ( - pool.init_pool_amount + swap_amount, pool.ibc_op_init_pool_amount - - return_amount + pool.init_pool_amount + swap_amount, + pool.ibc_op_init_pool_amount - return_amount ) } #[view] public fun get_pool_amount_by_denom( - ibc_op_init_denom: String, after_peg_keeper_swap: bool, + ibc_op_init_denom: String, after_peg_keeper_swap: bool ): (u64, u64) acquires ModuleStore, VirtualPool { let ibc_op_init_metadata = coin::denom_to_metadata(ibc_op_init_denom); get_pool_amount(ibc_op_init_metadata, after_peg_keeper_swap) @@ -376,7 +376,7 @@ module initia_std::minitswap { #[view] public fun get_peg_keeper_balance( - ibc_op_init_metadata: Object, after_peg_keeper_swap: bool, + ibc_op_init_metadata: Object, after_peg_keeper_swap: bool ): (u64, u64) acquires ModuleStore, VirtualPool { let (_, pool) = borrow_all(ibc_op_init_metadata); assert!(pool.active, error::invalid_state(EINACTIVE)); @@ -393,7 +393,7 @@ module initia_std::minitswap { #[view] public fun get_peg_keeper_balance_by_denom( - ibc_op_init_denom: String, after_peg_keeper_swap: bool, + ibc_op_init_denom: String, after_peg_keeper_swap: bool ): (u64, u64) acquires ModuleStore, VirtualPool { let ibc_op_init_metadata = coin::denom_to_metadata(ibc_op_init_denom); get_peg_keeper_balance(ibc_op_init_metadata, after_peg_keeper_swap) @@ -403,17 +403,17 @@ module initia_std::minitswap { public fun swap_simulation( offer_metadata: Object, return_metadata: Object, - offer_amount: u64, + offer_amount: u64 ): (u64, u64) acquires ModuleStore, VirtualPool { let (return_amount, fee_amount) = safe_swap_simulation( offer_metadata, return_metadata, - offer_amount, + offer_amount ); assert!( return_amount != 0, - error::invalid_state(EIBC_OP_INIT_PRICE_TOO_LOW), + error::invalid_state(EIBC_OP_INIT_PRICE_TOO_LOW) ); (return_amount, fee_amount) } @@ -422,40 +422,38 @@ module initia_std::minitswap { public fun swap_simulation_given_out( offer_metadata: Object, return_metadata: Object, - return_amount: u64, + return_amount: u64 ): (u64, u64) acquires ModuleStore, VirtualPool { let (return_amount, fee_amount) = safe_swap_simulation_given_out( offer_metadata, return_metadata, - return_amount, + return_amount ); assert!( return_amount != (U64_MAX as u64), - error::invalid_state(EIBC_OP_INIT_PRICE_TOO_LOW), + error::invalid_state(EIBC_OP_INIT_PRICE_TOO_LOW) ); (return_amount, fee_amount) } #[view] public fun swap_simulation_by_denom( - offer_denom: String, - return_denom: String, - offer_amount: u64, + offer_denom: String, return_denom: String, offer_amount: u64 ): (u64, u64) acquires ModuleStore, VirtualPool { let offer_metadata = coin::denom_to_metadata(offer_denom); let return_metadata = coin::denom_to_metadata(return_denom); swap_simulation( offer_metadata, return_metadata, - offer_amount, + offer_amount ) } #[view] public fun spot_price( - base_metadata: Object, quote_metadata: Object, - ): Decimal128 acquires ModuleStore, VirtualPool { + base_metadata: Object, quote_metadata: Object + ): BigDecimal acquires ModuleStore, VirtualPool { let is_init_quote = is_init_metadata(quote_metadata); let ibc_op_init_metadata = if (is_init_quote) { base_metadata @@ -467,7 +465,7 @@ module initia_std::minitswap { assert!( virtual_pool_exists, - error::invalid_argument(EPOOL_NOT_FOUND), + error::invalid_argument(EPOOL_NOT_FOUND) ); let (init_pool_amount, ibc_op_init_pool_amount) = @@ -481,7 +479,7 @@ module initia_std::minitswap { init_pool_amount, ibc_op_init_pool_amount, pool.pool_size, - pool.ann, + pool.ann ); let init_return_amount = get_return_amount( @@ -489,34 +487,32 @@ module initia_std::minitswap { ibc_op_init_pool_amount, init_pool_amount, pool.pool_size, - pool.ann, + pool.ann ); if (is_init_quote) { - decimal128::from_ratio_u64( + bigdecimal::from_ratio_u64( init_return_amount + swap_amount, - ibc_op_init_return_amount + swap_amount, + ibc_op_init_return_amount + swap_amount ) } else { - decimal128::from_ratio_u64( + bigdecimal::from_ratio_u64( ibc_op_init_return_amount + swap_amount, - init_return_amount + swap_amount, + init_return_amount + swap_amount ) } } #[view] public fun get_unbond_list( - account: address, - start_after: Option, - limit: u64, + account: address, start_after: Option, limit: u64 ): vector acquires ModuleStore { let module_store = borrow_global(@initia_std); let start_key = if (option::is_some(&start_after)) { generate_unbond_key( account, - *option::borrow(&start_after) + 1, + *option::borrow(&start_after) + 1 ) } else { generate_unbond_key(account, 0) @@ -531,7 +527,7 @@ module initia_std::minitswap { &module_store.unbond_wait_list, option::some(start_key), option::none(), - 1, + 1 ); let i = 0; @@ -546,8 +542,8 @@ module initia_std::minitswap { account: value.account, share_amount: value.share_amount, withdraw_amount: value.withdraw_amount, - release_time: value.release_time, - }, + release_time: value.release_time + } ); }; @@ -555,17 +551,17 @@ module initia_std::minitswap { } #[view] - public fun get_arb_info(id: u64,): ArbResponse acquires ModuleStore, VirtualPool { + public fun get_arb_info(id: u64): ArbResponse acquires ModuleStore, VirtualPool { let module_store = borrow_global(@initia_std); let pool_obj = table::borrow( &module_store.global_arb_batch_map, - table_key::encode_u64(id), + table_key::encode_u64(id) ); let pool = borrow_global(object::object_address(&*pool_obj)); let arb_info = table::borrow( &pool.arb_batch_map, - table_key::encode_u64(id), + table_key::encode_u64(id) ); return ArbResponse { @@ -574,15 +570,13 @@ module initia_std::minitswap { executed_time: arb_info.executed_time, init_used: arb_info.init_used, ibc_op_init_sent: arb_info.ibc_op_init_sent, - triggering_fee: arb_info.triggering_fee, + triggering_fee: arb_info.triggering_fee } } #[view] public fun get_arb_infos( - ibc_op_init_metadata: Object, - start_after: Option, - limit: u64, + ibc_op_init_metadata: Object, start_after: Option, limit: u64 ): vector acquires ModuleStore, VirtualPool { let (_, pool) = borrow_all(ibc_op_init_metadata); let start_key = @@ -601,7 +595,7 @@ module initia_std::minitswap { &pool.arb_batch_map, option::some(start_key), option::none(), - 1, + 1 ); let i = 0; @@ -618,8 +612,8 @@ module initia_std::minitswap { executed_time: arb_info.executed_time, init_used: arb_info.init_used, ibc_op_init_sent: arb_info.ibc_op_init_sent, - triggering_fee: arb_info.triggering_fee, - }, + triggering_fee: arb_info.triggering_fee + } ); }; @@ -643,7 +637,7 @@ module initia_std::minitswap { ibc_timeout: module_store.ibc_timeout, max_arb_batch: module_store.max_arb_batch, min_arb_interval: module_store.min_arb_interval, - arb_batch_index: module_store.arb_batch_index, + arb_batch_index: module_store.arb_batch_index } } @@ -657,7 +651,7 @@ module initia_std::minitswap { op_bridge_id: pools.op_bridge_id, ibc_channel: pools.ibc_channel, virtual_pool: pools.virtual_pool, - stableswap_pool: pools.stableswap_pool, + stableswap_pool: pools.stableswap_pool } } @@ -675,7 +669,7 @@ module initia_std::minitswap { &module_store.pools, option::none(), start_after, - 2, + 2 ); let i = 0; @@ -691,8 +685,8 @@ module initia_std::minitswap { op_bridge_id: pools.op_bridge_id, ibc_channel: pools.ibc_channel, virtual_pool: pools.virtual_pool, - stableswap_pool: pools.stableswap_pool, - }, + stableswap_pool: pools.stableswap_pool + } ); }; @@ -700,7 +694,9 @@ module initia_std::minitswap { } #[view] - public fun get_pools_detail(ibc_op_init_metadata: Object): PoolsDetailResponse acquires ModuleStore, VirtualPool { + public fun get_pools_detail( + ibc_op_init_metadata: Object + ): PoolsDetailResponse acquires ModuleStore, VirtualPool { let module_store = borrow_global(@initia_std); let pools = table::borrow(&module_store.pools, ibc_op_init_metadata); let virtual_pool = @@ -722,8 +718,8 @@ module initia_std::minitswap { virtual_ibc_op_init_balance: vp.virtual_ibc_op_init_balance, peg_keeper_owned_ibc_op_init_balance: vp.peg_keeper_owned_ibc_op_init_balance, ann: vp.ann, - active: vp.active, - }, + active: vp.active + } ) } else { option::none() @@ -744,7 +740,7 @@ module initia_std::minitswap { op_bridge_id: pools.op_bridge_id, ibc_channel: pools.ibc_channel, virtual_pool: virtual_pool, - stableswap_pool, + stableswap_pool } } @@ -762,7 +758,7 @@ module initia_std::minitswap { &module_store.pools, option::none(), start_after, - 2, + 2 ); let i = 0; @@ -776,7 +772,7 @@ module initia_std::minitswap { borrow_global( object::object_address( &*option::borrow(&pools.virtual_pool) - ), + ) ); option::some( VirtualPoolDetail { @@ -791,8 +787,8 @@ module initia_std::minitswap { virtual_ibc_op_init_balance: vp.virtual_ibc_op_init_balance, peg_keeper_owned_ibc_op_init_balance: vp.peg_keeper_owned_ibc_op_init_balance, ann: vp.ann, - active: vp.active, - }, + active: vp.active + } ) } else { option::none() @@ -815,8 +811,8 @@ module initia_std::minitswap { op_bridge_id: pools.op_bridge_id, ibc_channel: pools.ibc_channel, virtual_pool: virtual_pool, - stableswap_pool, - }, + stableswap_pool + } ) }; @@ -832,7 +828,7 @@ module initia_std::minitswap { account: address, share_amount: u64, withdraw_amount: u64, - release_time: u64, + release_time: u64 } public fun unpack_unbond_response(res: UnbondResponse): (address, u64, u64, u64) { @@ -845,11 +841,11 @@ module initia_std::minitswap { executed_time: u64, init_used: u64, ibc_op_init_sent: u64, - triggering_fee: u64, + triggering_fee: u64 } - public fun unpack_arb_response(res: ArbResponse) - : (Object, u64, u64, u64, u64, u64) { + public fun unpack_arb_response(res: ArbResponse): + (Object, u64, u64, u64, u64, u64) { return ( res.ibc_op_init_metadata, res.id, @@ -861,30 +857,31 @@ module initia_std::minitswap { } struct ModuleStoreResponse has drop { - max_change_rate: Decimal128, + max_change_rate: BigDecimal, emergency_state: bool, admin: address, depositor_owned_init: u64, unbond_period: u64, - swap_fee_rate: Decimal128, - arb_fee_rate: Decimal128, + swap_fee_rate: BigDecimal, + arb_fee_rate: BigDecimal, trigger_fee: u64, min_arb_profit: u64, ibc_timeout: u64, max_arb_batch: u64, min_arb_interval: u64, - arb_batch_index: u64, + arb_batch_index: u64 } - public fun unpack_module_store_response(res: ModuleStoreResponse) - : ( - Decimal128, + public fun unpack_module_store_response( + res: ModuleStoreResponse + ): ( + BigDecimal, bool, address, u64, u64, - Decimal128, - Decimal128, + BigDecimal, + BigDecimal, u64, u64, u64, @@ -905,7 +902,7 @@ module initia_std::minitswap { res.ibc_timeout, res.max_arb_batch, res.min_arb_interval, - res.arb_batch_index, + res.arb_batch_index ) } @@ -915,11 +912,12 @@ module initia_std::minitswap { op_bridge_id: u64, ibc_channel: String, virtual_pool: Option>, - stableswap_pool: Option>, + stableswap_pool: Option> } - public fun unpack_pools_response(res: PoolsResponse) - : ( + public fun unpack_pools_response( + res: PoolsResponse + ): ( Object, String, u64, @@ -943,11 +941,12 @@ module initia_std::minitswap { op_bridge_id: u64, ibc_channel: String, virtual_pool: Option, - stableswap_pool: Option, + stableswap_pool: Option } - public fun unpack_pools_detail_response(res: PoolsDetailResponse) - : ( + public fun unpack_pools_detail_response( + res: PoolsDetailResponse + ): ( Object, String, u64, @@ -975,9 +974,9 @@ module initia_std::minitswap { struct VirtualPoolDetail has drop { pool_size: u64, - recover_velocity: Decimal128, - max_ratio: Decimal128, - recover_param: Decimal128, + recover_velocity: BigDecimal, + max_ratio: BigDecimal, + recover_param: BigDecimal, init_pool_amount: u64, ibc_op_init_pool_amount: u64, last_recovered_timestamp: u64, @@ -985,13 +984,12 @@ module initia_std::minitswap { virtual_ibc_op_init_balance: u64, peg_keeper_owned_ibc_op_init_balance: u64, ann: u64, - active: bool, + active: bool } - public fun unpack_virtual_pool_detail(res: VirtualPoolDetail) - : ( - u64, Decimal128, Decimal128, Decimal128, u64, u64, u64, u64, u64, u64, u64, bool - ) { + public fun unpack_virtual_pool_detail( + res: VirtualPoolDetail + ): (u64, BigDecimal, BigDecimal, BigDecimal, u64, u64, u64, u64, u64, u64, u64, bool) { return ( res.pool_size, res.recover_velocity, @@ -1004,7 +1002,7 @@ module initia_std::minitswap { res.virtual_ibc_op_init_balance, res.peg_keeper_owned_ibc_op_init_balance, res.ann, - res.active, + res.active ) } @@ -1016,20 +1014,20 @@ module initia_std::minitswap { public entry fun create_pool( chain: &signer, ibc_op_init_metadata: Object, - recover_velocity: Decimal128, + recover_velocity: BigDecimal, pool_size: u64, ann: u64, - max_ratio: Decimal128, - recover_param: Decimal128, + max_ratio: BigDecimal, + recover_param: BigDecimal, vm_type: u8, hook_contract: String, op_bridge_id: u64, - ibc_channel: String, + ibc_channel: String ) acquires ModuleStore { assert_is_chain(chain, false); assert!( pool_size > 0, - error::invalid_argument(EPOOL_SIZE), + error::invalid_argument(EPOOL_SIZE) ); let constructor_ref = object::create_object(@initia_std, false); let extend_ref = object::generate_extend_ref(&constructor_ref); @@ -1038,13 +1036,13 @@ module initia_std::minitswap { assert!( vm_type == MOVE || vm_type == COSMWASM, - error::invalid_argument(EVM_TYPE), + error::invalid_argument(EVM_TYPE) ); check_bridge_info( op_bridge_id, ibc_channel, - ibc_op_init_metadata, + ibc_op_init_metadata ); move_to( @@ -1068,8 +1066,8 @@ module initia_std::minitswap { ibc_channel, vm_type, hook_contract, - arb_batch_map: table::new(), - }, + arb_batch_map: table::new() + } ); let module_store = borrow_global_mut(@initia_std); @@ -1078,12 +1076,12 @@ module initia_std::minitswap { module_store, ibc_op_init_metadata, op_bridge_id, - ibc_channel, + ibc_channel ); assert!( option::is_none(&pools.virtual_pool), - error::already_exists(EVIRTUAL_POOL_EXISTS), + error::already_exists(EVIRTUAL_POOL_EXISTS) ); pools.virtual_pool = option::some( object::object_from_constructor_ref(&constructor_ref) @@ -1096,8 +1094,8 @@ module initia_std::minitswap { pool_size, ann, max_ratio, - recover_param, - }, + recover_param + } ) } @@ -1143,7 +1141,7 @@ module initia_std::minitswap { assert_is_chain(chain, false); assert!( new_pool_size > 0, - error::invalid_argument(EPOOL_SIZE), + error::invalid_argument(EPOOL_SIZE) ); let module_store = borrow_global_mut(@initia_std); let pools = table::borrow(&mut module_store.pools, ibc_op_init_metadata); @@ -1154,22 +1152,20 @@ module initia_std::minitswap { let change_rate = if (new_pool_size > pool.pool_size) { - decimal128::from_ratio_u64( + bigdecimal::from_ratio_u64( new_pool_size - pool.pool_size, - pool.pool_size, + pool.pool_size ) } else { - decimal128::from_ratio_u64( + bigdecimal::from_ratio_u64( pool.pool_size - new_pool_size, - pool.pool_size, + pool.pool_size ) }; assert!( - decimal128::val(&module_store.max_change_rate) >= decimal128::val( - &change_rate - ), - error::invalid_argument(EMAX_CHANGE), + bigdecimal::ge(module_store.max_change_rate, change_rate), + error::invalid_argument(EMAX_CHANGE) ); let depositor_owned_init_increase = @@ -1190,11 +1186,13 @@ module initia_std::minitswap { let current_ibc_op_init_delta = pool.ibc_op_init_pool_amount - pool.pool_size; - let ratio = decimal128::from_ratio_u64(new_pool_size, pool.pool_size); - pool.init_pool_amount = decimal128::mul_u64(&ratio, pool.init_pool_amount); - pool.ibc_op_init_pool_amount = decimal128::mul_u64( - &ratio, - pool.ibc_op_init_pool_amount, + let ratio = bigdecimal::from_ratio_u64(new_pool_size, pool.pool_size); + pool.init_pool_amount = bigdecimal::mul_by_u64_truncate( + ratio, pool.init_pool_amount + ); + pool.ibc_op_init_pool_amount = bigdecimal::mul_by_u64_truncate( + ratio, + pool.ibc_op_init_pool_amount ); pool.pool_size = new_pool_size; @@ -1202,7 +1200,8 @@ module initia_std::minitswap { let ibc_op_init_delta = pool.ibc_op_init_pool_amount - pool.pool_size; let net_init_delta = current_init_delta - init_delta; - let net_ibc_op_init_delta = current_ibc_op_init_delta - ibc_op_init_delta; + let net_ibc_op_init_delta = current_ibc_op_init_delta + - ibc_op_init_delta; pool.virtual_init_balance = pool.virtual_init_balance + net_init_delta; pool.virtual_ibc_op_init_balance = pool.virtual_ibc_op_init_balance @@ -1225,10 +1224,12 @@ module initia_std::minitswap { // 1. swap to make 5:5 let init_swap_amount = pool.pool_size - pool.init_pool_amount; - let ibc_op_init_swap_amount = pool.ibc_op_init_pool_amount - pool.pool_size; + let ibc_op_init_swap_amount = pool.ibc_op_init_pool_amount + - pool.pool_size; // pool.init_pool_amount = pool.pool_size; // pool.ibc_op_init_pool_amount = pool.pool_size; - pool.virtual_init_balance = pool.virtual_init_balance + init_swap_amount; + pool.virtual_init_balance = pool.virtual_init_balance + + init_swap_amount; pool.virtual_ibc_op_init_balance = pool.virtual_ibc_op_init_balance + ibc_op_init_swap_amount; pool.peg_keeper_owned_ibc_op_init_balance = pool.peg_keeper_owned_ibc_op_init_balance @@ -1246,7 +1247,7 @@ module initia_std::minitswap { pool.ibc_op_init_pool_amount, pool.init_pool_amount, pool.pool_size, - pool.ann, + pool.ann ); pool.ibc_op_init_pool_amount = pool.ibc_op_init_pool_amount + ibc_op_init_swap_amount; @@ -1263,7 +1264,8 @@ module initia_std::minitswap { pool.virtual_init_balance = 0; remain } else { - pool.virtual_init_balance = pool.virtual_init_balance - return_amount; + pool.virtual_init_balance = pool.virtual_init_balance + - return_amount; 0 } }; @@ -1272,23 +1274,23 @@ module initia_std::minitswap { ChangePoolSizeEvent { ibc_op_init_metadata, pool_size: new_pool_size, - depositor_owned_init_increase, - }, + depositor_owned_init_increase + } ) } public entry fun update_module_params( chain: &signer, - max_change_rate: Option, + max_change_rate: Option, admin: Option
, unbond_period: Option, - swap_fee_rate: Option, - arb_fee_rate: Option, + swap_fee_rate: Option, + arb_fee_rate: Option, trigger_fee: Option, min_arb_profit: Option, ibc_timeout: Option, max_arb_batch: Option, - min_arb_interval: Option, + min_arb_interval: Option ) acquires ModuleStore { assert_is_chain(chain, false); let module_store = borrow_global_mut(@initia_std); @@ -1335,18 +1337,18 @@ module initia_std::minitswap { assert!( module_store.min_arb_profit > module_store.trigger_fee, - error::invalid_argument(ESMALL_ARB_PROFIT), + error::invalid_argument(ESMALL_ARB_PROFIT) ) } public entry fun update_pool_params( chain: &signer, ibc_op_init_metadata: Object, - recover_velocity: Option, + recover_velocity: Option, ann: Option, - max_ratio: Option, - recover_param: Option, - hook_contract: Option, + max_ratio: Option, + recover_param: Option, + hook_contract: Option ) acquires ModuleStore, VirtualPool { assert_is_chain(chain, false); let module_store = borrow_global_mut(@initia_std); @@ -1384,8 +1386,8 @@ module initia_std::minitswap { ann, max_ratio, recover_param, - hook_contract, - }, + hook_contract + } ) } @@ -1407,7 +1409,7 @@ module initia_std::minitswap { primary_fungible_store::withdraw( account, share_token_metadata(), - amount, + amount ); unbond_internal(account, share_token); } @@ -1419,7 +1421,7 @@ module initia_std::minitswap { // check emergency assert!( !module_store.emergency_state, - error::invalid_state(EEMERGENCY), + error::invalid_state(EEMERGENCY) ); // remove unbond entity @@ -1431,7 +1433,7 @@ module initia_std::minitswap { let (_, timestamp) = block::get_block_info(); assert!( timestamp >= release_time, - error::invalid_state(ERELEASE_TIME), + error::invalid_state(ERELEASE_TIME) ); // release init @@ -1441,7 +1443,7 @@ module initia_std::minitswap { &module_signer, init_metadata(), addr, - withdraw_amount, + withdraw_amount ); event::emit( @@ -1449,8 +1451,8 @@ module initia_std::minitswap { account: addr, share_amount, withdraw_amount, - release_time, - }, + release_time + } ); } @@ -1465,7 +1467,7 @@ module initia_std::minitswap { primary_fungible_store::withdraw( account, offer_asset_metadata, - amount, + amount ); let return_asset = swap_internal(offer_asset, return_asset_metadata); @@ -1484,20 +1486,20 @@ module initia_std::minitswap { version: String, state_root: String, storage_root: String, - latest_block_hash: String, + latest_block_hash: String ) acquires ModuleStore, VirtualPool { // check arb info let module_store = borrow_global(@initia_std); let pool_obj = table::borrow( &module_store.global_arb_batch_map, - table_key::encode_u64(arb_index), + table_key::encode_u64(arb_index) ); let pool = borrow_global(object::object_address(&*pool_obj)); let arb_info = table::borrow( &pool.arb_batch_map, - table_key::encode_u64(arb_index), + table_key::encode_u64(arb_index) ); // execute finalize token withdrawal @@ -1515,7 +1517,7 @@ module initia_std::minitswap { version, state_root, storage_root, - latest_block_hash, + latest_block_hash ); cosmos::stargate(&pool_signer, withdrawal_msg); @@ -1530,32 +1532,31 @@ module initia_std::minitswap { vector[], vector[ bcs::to_bytes(&arb_index), - bcs::to_bytes(&signer::address_of(account)),], + bcs::to_bytes(&signer::address_of(account)) + ] ); } public entry fun finalize_arb_hook( - module_signer: &signer, - arb_index: u64, - executor: address, + module_signer: &signer, arb_index: u64, executor: address ) acquires ModuleStore, VirtualPool { let module_store = borrow_global_mut(@initia_std); assert!( signer::address_of(module_signer) == object::address_from_extend_ref(&module_store.extend_ref), - error::permission_denied(EUNAUTHORIZED), + error::permission_denied(EUNAUTHORIZED) ); let pool_obj = table::remove( &mut module_store.global_arb_batch_map, - table_key::encode_u64(arb_index), + table_key::encode_u64(arb_index) ); let pool = borrow_global_mut(object::object_address(&pool_obj)); let ArbInfo { executed_time: _, init_used, ibc_op_init_sent, triggering_fee } = table::remove( &mut pool.arb_batch_map, - table_key::encode_u64(arb_index), + table_key::encode_u64(arb_index) ); assert!(pool.active, error::invalid_state(EINACTIVE)); @@ -1571,7 +1572,7 @@ module initia_std::minitswap { &pool_signer, init_metadata(), executor, - triggering_fee, + triggering_fee ); // transfer leftover to module_addr @@ -1580,7 +1581,7 @@ module initia_std::minitswap { &pool_signer, init_metadata(), signer::address_of(module_signer), - leftover_amount, + leftover_amount ); // update depositor owned init @@ -1595,8 +1596,8 @@ module initia_std::minitswap { pool: pool_obj, init_used, ibc_op_init_sent, - triggering_fee, - }, + triggering_fee + } ); } @@ -1608,14 +1609,14 @@ module initia_std::minitswap { ibc_channel: String, ibc_op_init_metadata: Object, init_amount: u64, - ibc_op_init_amount: u64, + ibc_op_init_amount: u64 ) acquires ModuleStore { let module_store = borrow_global_mut(@initia_std); let (_, ibc_denom) = check_bridge_info( op_bridge_id, ibc_channel, - ibc_op_init_metadata, + ibc_op_init_metadata ); let creator = object::generate_signer_for_extending(&module_store.extend_ref); @@ -1626,13 +1627,14 @@ module initia_std::minitswap { coin::withdraw( account, init_metadata(), - init_amount, + init_amount ), coin::withdraw( account, ibc_op_init_metadata, - ibc_op_init_amount, - ),]; + ibc_op_init_amount + ) + ]; let liquidity_token = stableswap::create_pool( @@ -1641,7 +1643,7 @@ module initia_std::minitswap { symbol, module_store.stableswap_swap_fee_rate, coins, - module_store.stableswap_ann, + module_store.stableswap_ann ); let metadata = fungible_asset::metadata_from_asset(&liquidity_token); let pool = object::convert(metadata); @@ -1651,19 +1653,19 @@ module initia_std::minitswap { module_store, ibc_op_init_metadata, op_bridge_id, - ibc_channel, + ibc_channel ); pools.stableswap_pool = option::some(object::convert(metadata)); primary_fungible_store::deposit(signer::address_of(account), liquidity_token); - event::emit(CreateStableswapPoolEvent { ibc_op_init_metadata, pool, }); + event::emit(CreateStableswapPoolEvent { ibc_op_init_metadata, pool }); } public fun provide_internal(init: FungibleAsset): FungibleAsset acquires ModuleStore { // check asset metadata assert!( is_init(&init), - error::invalid_argument(ENOT_INIT), + error::invalid_argument(ENOT_INIT) ); let provide_amount = fungible_asset::amount(&init); @@ -1672,7 +1674,7 @@ module initia_std::minitswap { // check emergency assert!( !module_store.emergency_state, - error::invalid_state(EEMERGENCY), + error::invalid_state(EEMERGENCY) ); // calculate share amount @@ -1684,7 +1686,7 @@ module initia_std::minitswap { mul_div( provide_amount, (total_share as u64), - module_store.depositor_owned_init, + module_store.depositor_owned_init ) }; @@ -1697,7 +1699,7 @@ module initia_std::minitswap { primary_fungible_store::deposit(module_addr, init); // emit event - event::emit(ProvideEvent { provide_amount, share_amount, }); + event::emit(ProvideEvent { provide_amount, share_amount }); // mint share token coin::mint(&module_store.mint_cap, share_amount) @@ -1711,14 +1713,14 @@ module initia_std::minitswap { // check emergency assert!( !module_store.emergency_state, - error::invalid_state(EEMERGENCY), + error::invalid_state(EEMERGENCY) ); // check metdata let share_token_metadata = fungible_asset::metadata_from_asset(&share_token); assert!( share_token_metadata == share_token_metadata(), - error::invalid_argument(ENOT_SHARE_TOKEN), + error::invalid_argument(ENOT_SHARE_TOKEN) ); // calculate withdraw amount @@ -1728,7 +1730,7 @@ module initia_std::minitswap { mul_div( share_amount, module_store.depositor_owned_init, - total_share, + total_share ); // decrease depositor owned init @@ -1747,13 +1749,13 @@ module initia_std::minitswap { account: signer::address_of(account), share_amount, withdraw_amount, - release_time, + release_time }; let key = generate_unbond_key(signer::address_of(account), release_time); table::add( &mut module_store.unbond_wait_list, key, - withdraw_entity, + withdraw_entity ); // emit event @@ -1762,13 +1764,13 @@ module initia_std::minitswap { account: signer::address_of(account), share_amount, withdraw_amount, - release_time, - }, + release_time + } ); } public fun swap_internal( - offer_asset: FungibleAsset, return_metadata: Object, + offer_asset: FungibleAsset, return_metadata: Object ): FungibleAsset acquires ModuleStore, VirtualPool { let is_init_offered = is_init(&offer_asset); let offer_metadata = fungible_asset::metadata_from_asset(&offer_asset); @@ -1791,7 +1793,7 @@ module initia_std::minitswap { init_swap_fee_amount, init_arb_fee_amount, ibc_op_init_swap_fee_amount, - ibc_op_init_arb_fee_amount, + ibc_op_init_arb_fee_amount ) = if (is_init_offered) { // user swap @@ -1805,7 +1807,7 @@ module initia_std::minitswap { pool, module_signer, pool_signer, - is_init_offered, + is_init_offered ); // peg keeper swap @@ -1819,11 +1821,12 @@ module initia_std::minitswap { mul_div( depositor_return_amount, arb_fee_amount, - arb_fee_amount + swap_fee_amount, + arb_fee_amount + swap_fee_amount ) }; - let init_swap_fee_amount = depositor_return_amount - init_arb_fee_amount; + let init_swap_fee_amount = depositor_return_amount + - init_arb_fee_amount; ( peg_keeper_offer_amount, @@ -1849,7 +1852,7 @@ module initia_std::minitswap { pool, module_signer, pool_signer, - is_init_offered, + is_init_offered ); ( @@ -1867,7 +1870,7 @@ module initia_std::minitswap { check_arb( module_store, pool, - ibc_op_init_metadata, + ibc_op_init_metadata ); event::emit( @@ -1881,8 +1884,8 @@ module initia_std::minitswap { init_swap_fee_amount, init_arb_fee_amount, ibc_op_init_swap_fee_amount, - ibc_op_init_arb_fee_amount, - }, + ibc_op_init_arb_fee_amount + } ); return_asset @@ -1899,13 +1902,13 @@ module initia_std::minitswap { let pool_obj = table::borrow( &mut module_store.global_arb_batch_map, - table_key::encode_u64(callback_id), + table_key::encode_u64(callback_id) ); let pool = borrow_global_mut(object::object_address(&*pool_obj)); assert!( signer::address_of(pool_signer) == object::address_from_extend_ref(&pool.extend_ref), - error::permission_denied(EUNAUTHORIZED), + error::permission_denied(EUNAUTHORIZED) ); // do nothing @@ -1914,18 +1917,20 @@ module initia_std::minitswap { revert_arb_state(callback_id); } - public entry fun ibc_timeout(pool_signer: &signer, callback_id: u64) acquires ModuleStore, VirtualPool { + public entry fun ibc_timeout( + pool_signer: &signer, callback_id: u64 + ) acquires ModuleStore, VirtualPool { let module_store = borrow_global_mut(@initia_std); let pool_obj = table::borrow( &mut module_store.global_arb_batch_map, - table_key::encode_u64(callback_id), + table_key::encode_u64(callback_id) ); let pool = borrow_global_mut(object::object_address(&*pool_obj)); assert!( signer::address_of(pool_signer) == object::address_from_extend_ref(&pool.extend_ref), - error::permission_denied(EUNAUTHORIZED), + error::permission_denied(EUNAUTHORIZED) ); revert_arb_state(callback_id); @@ -1936,13 +1941,13 @@ module initia_std::minitswap { let pool_obj = table::remove( &mut module_store.global_arb_batch_map, - table_key::encode_u64(callback_id), + table_key::encode_u64(callback_id) ); let pool = borrow_global_mut(object::object_address(&pool_obj)); - let ArbInfo { executed_time: _, init_used, ibc_op_init_sent, triggering_fee, } = + let ArbInfo { executed_time: _, init_used, ibc_op_init_sent, triggering_fee } = table::remove( &mut pool.arb_batch_map, - table_key::encode_u64(callback_id), + table_key::encode_u64(callback_id) ); pool.virtual_init_balance = pool.virtual_init_balance + init_used; pool.virtual_ibc_op_init_balance = pool.virtual_ibc_op_init_balance @@ -1954,8 +1959,8 @@ module initia_std::minitswap { pool: pool_obj, init_used, ibc_op_init_sent, // always ibc op init - triggering_fee, - }, + triggering_fee + } ); } @@ -1964,10 +1969,9 @@ module initia_std::minitswap { // Helper function // - inline fun borrow_all_mut(metadata: Object) - : ( - &mut ModuleStore, &mut VirtualPool, signer, signer - ) acquires ModuleStore, VirtualPool { + inline fun borrow_all_mut( + metadata: Object + ): (&mut ModuleStore, &mut VirtualPool, signer, signer) acquires ModuleStore, VirtualPool { let module_store = borrow_global_mut(@initia_std); let module_signer = object::generate_signer_for_extending(&module_store.extend_ref); @@ -1975,20 +1979,22 @@ module initia_std::minitswap { object::object_address( &*option::borrow( &table::borrow(&module_store.pools, metadata).virtual_pool - ), + ) ); let pool = borrow_global_mut(pool_addr); let pool_signer = object::generate_signer_for_extending(&pool.extend_ref); (module_store, pool, module_signer, pool_signer) } - inline fun borrow_all(metadata: Object): (&ModuleStore, &VirtualPool) acquires ModuleStore, VirtualPool { + inline fun borrow_all( + metadata: Object + ): (&ModuleStore, &VirtualPool) acquires ModuleStore, VirtualPool { let module_store = borrow_global(@initia_std); let pool_addr = object::object_address( &*option::borrow( &table::borrow(&module_store.pools, metadata).virtual_pool - ), + ) ); let pool = borrow_global(pool_addr); (module_store, pool) @@ -2006,29 +2012,28 @@ module initia_std::minitswap { let (_, timestamp) = block::get_block_info(); let imbalance = - decimal128::from_ratio_u64( - pool.peg_keeper_owned_ibc_op_init_balance + pool.ibc_op_init_pool_amount - - pool.pool_size, // same with real ibc op init balance - pool.pool_size, + bigdecimal::from_ratio_u64( + pool.peg_keeper_owned_ibc_op_init_balance + + pool.ibc_op_init_pool_amount - pool.pool_size, // same with real ibc op init balance + pool.pool_size ); // Peg keeper swap - let r_fr = - get_fully_recovered_ratio( - &imbalance, - &pool.max_ratio, - &pool.recover_param, - ); + let r_fr = get_fully_recovered_ratio( + imbalance, + pool.max_ratio, + pool.recover_param + ); let current_ratio = - decimal128::from_ratio_u64( + bigdecimal::from_ratio_u64( pool.ibc_op_init_pool_amount, - pool.init_pool_amount + pool.ibc_op_init_pool_amount, + pool.init_pool_amount + pool.ibc_op_init_pool_amount ); let time_diff = timestamp - pool.last_recovered_timestamp; - if (decimal128::val(¤t_ratio) > decimal128::val(&r_fr) && time_diff != 0) { + if (bigdecimal::gt(current_ratio, r_fr) && time_diff != 0) { let (x_fr, _) = - get_fully_recovered_pool_amounts(pool.pool_size, &r_fr, pool.ann); + get_fully_recovered_pool_amounts(pool.pool_size, r_fr, pool.ann); let max_recover_amount = - decimal128::mul_u64(&pool.recover_velocity, time_diff); + bigdecimal::mul_by_u64_truncate(pool.recover_velocity, time_diff); let swap_amount_to_reach_fr = if (x_fr > pool.init_pool_amount) { x_fr - pool.init_pool_amount @@ -2046,7 +2051,7 @@ module initia_std::minitswap { pool.init_pool_amount, pool.ibc_op_init_pool_amount, pool.pool_size, - pool.ann, + pool.ann ); (swap_amount, return_amount) @@ -2060,7 +2065,7 @@ module initia_std::minitswap { pool: &mut VirtualPool, module_signer: signer, pool_signer: signer, - is_init_offered: bool, + is_init_offered: bool ): (FungibleAsset, u64, u64, u64) { let module_addr = signer::address_of(&module_signer); let pool_addr = signer::address_of(&pool_signer); @@ -2078,22 +2083,23 @@ module initia_std::minitswap { pool.init_pool_amount, pool.ibc_op_init_pool_amount, pool.pool_size, - pool.ann, + pool.ann ); pool.init_pool_amount = pool.init_pool_amount + offer_amount; - pool.ibc_op_init_pool_amount = pool.ibc_op_init_pool_amount - return_amount; + pool.ibc_op_init_pool_amount = pool.ibc_op_init_pool_amount + - return_amount; assert!( pool.ibc_op_init_pool_amount >= pool.pool_size && pool.init_pool_amount <= pool.pool_size, - error::invalid_state(EIBC_OP_INIT_PRICE_TOO_LOW), + error::invalid_state(EIBC_OP_INIT_PRICE_TOO_LOW) ); // take swap fee let swap_fee_amount = - decimal128::mul_u64( - &module_store.swap_fee_rate, - return_amount, + bigdecimal::mul_by_u64_ceil( + module_store.swap_fee_rate, + return_amount ); return_amount = return_amount - swap_fee_amount; @@ -2102,9 +2108,9 @@ module initia_std::minitswap { if (return_amount > offer_amount) { return_amount - offer_amount } else { 0 }; - arb_fee_amount = decimal128::mul_u64( - &module_store.arb_fee_rate, - arb_profit, + arb_fee_amount = bigdecimal::mul_by_u64_ceil( + module_store.arb_fee_rate, + arb_profit ); return_amount = return_amount - arb_fee_amount; let total_fee_amount = swap_fee_amount + arb_fee_amount; @@ -2116,7 +2122,7 @@ module initia_std::minitswap { pool.ibc_op_init_pool_amount, pool.init_pool_amount, pool.pool_size, - pool.ann, + pool.ann ); pool.init_pool_amount = pool.init_pool_amount - depositor_return_amount; pool.ibc_op_init_pool_amount = pool.ibc_op_init_pool_amount @@ -2130,7 +2136,7 @@ module initia_std::minitswap { primary_fungible_store::withdraw( &pool_signer, return_metadata, - return_amount, + return_amount ), swap_fee_amount, depositor_return_amount @@ -2145,16 +2151,17 @@ module initia_std::minitswap { pool.ibc_op_init_pool_amount, pool.init_pool_amount, pool.pool_size, - pool.ann, + pool.ann ); pool.init_pool_amount = pool.init_pool_amount - return_amount; - pool.ibc_op_init_pool_amount = pool.ibc_op_init_pool_amount + offer_amount; + pool.ibc_op_init_pool_amount = pool.ibc_op_init_pool_amount + + offer_amount; // take swap fee let swap_fee_amount = - decimal128::mul_u64( - &module_store.swap_fee_rate, - return_amount, + bigdecimal::mul_by_u64_ceil( + module_store.swap_fee_rate, + return_amount ); let return_amount = return_amount - swap_fee_amount; @@ -2166,7 +2173,7 @@ module initia_std::minitswap { primary_fungible_store::withdraw( &module_signer, return_metadata, - return_amount, + return_amount ), swap_fee_amount, swap_fee_amount @@ -2213,7 +2220,7 @@ module initia_std::minitswap { &pool.arb_batch_map, option::none(), option::none(), - 2, + 2 ); let last_arb_timestamp = @@ -2235,7 +2242,7 @@ module initia_std::minitswap { executed_time: timestamp, init_used: pool.virtual_init_balance, ibc_op_init_sent: pool.virtual_ibc_op_init_balance, - triggering_fee: module_store.trigger_fee, + triggering_fee: module_store.trigger_fee }; // reset peg keeper balance @@ -2248,7 +2255,7 @@ module initia_std::minitswap { pool, arb_index, ibc_op_init_metadata, - arb_info.ibc_op_init_sent, + arb_info.ibc_op_init_sent ); // emit event @@ -2261,20 +2268,20 @@ module initia_std::minitswap { executed_time: arb_info.executed_time, init_used: arb_info.init_used, ibc_op_init_sent: arb_info.ibc_op_init_sent, - triggering_fee: arb_info.triggering_fee, - }, + triggering_fee: arb_info.triggering_fee + } ); // store arb info table::add( &mut module_store.global_arb_batch_map, table_key::encode_u64(arb_index), - pool_obj, + pool_obj ); table::add( &mut pool.arb_batch_map, table_key::encode_u64(arb_index), - arb_info, + arb_info ); } @@ -2284,13 +2291,10 @@ module initia_std::minitswap { op_bridge_id: u64, ibc_channel: String ): &mut Pools { - if (table::contains( - &module_store.pools, - ibc_op_init_metadata, - )) { + if (table::contains(&module_store.pools, ibc_op_init_metadata)) { table::borrow_mut( &mut module_store.pools, - ibc_op_init_metadata, + ibc_op_init_metadata ) } else { table::add( @@ -2300,13 +2304,13 @@ module initia_std::minitswap { op_bridge_id, ibc_channel, virtual_pool: option::none(), - stableswap_pool: option::none(), - }, + stableswap_pool: option::none() + } ); table::borrow_mut( &mut module_store.pools, - ibc_op_init_metadata, + ibc_op_init_metadata ) } } @@ -2316,7 +2320,7 @@ module initia_std::minitswap { pool: &mut VirtualPool, batch_index: u64, ibc_op_init_metadata: Object, - amount: u64, + amount: u64 ) { // create memo (ibc hook) let receiver = to_sdk(object::address_from_extend_ref(&pool.extend_ref)); @@ -2330,7 +2334,7 @@ module initia_std::minitswap { batch_index, receiver, op_denom, - amount, + amount ); // execute ibc transfer @@ -2347,24 +2351,24 @@ module initia_std::minitswap { 0, 0, (timestamp + module_store.ibc_timeout) * 1000000000, - memo, + memo ) } struct IBCMemo has copy, drop { _move_: MemoMove, - wasm: Option, + wasm: Option } struct MemoMove has copy, drop { message: Option, - async_callback: MemoAsyncCallback, + async_callback: MemoAsyncCallback } struct MemoAsyncCallback has copy, drop { id: u64, module_address: address, - module_name: String, + module_name: String } struct MemoMoveMessage has copy, drop { @@ -2372,30 +2376,30 @@ module initia_std::minitswap { module_name: String, function_name: String, type_args: vector, - args: vector, + args: vector } struct MemoWasm has copy, drop { - message: MemoWasmMessage, + message: MemoWasmMessage } struct MemoWasmMessage has copy, drop { contracts: String, funds: vector, - msg: MemoWasmMinitswapHook, + msg: MemoWasmMinitswapHook } struct MemoWasmFunds has copy, drop { denom: String, - amount: String, + amount: String } struct MemoWasmMinitswapHook has copy, drop { - minitswap_hook: MemoWasmMinitswapHookMsg, + minitswap_hook: MemoWasmMinitswapHookMsg } struct MemoWasmMinitswapHookMsg has copy, drop { - receiver: String, + receiver: String } fun generate_ibc_message( @@ -2404,7 +2408,7 @@ module initia_std::minitswap { batch_index: u64, receiver: String, op_denom: String, - amount: u64, + amount: u64 ): (String, String) { let memo = IBCMemo { _move_: MemoMove { @@ -2412,10 +2416,10 @@ module initia_std::minitswap { async_callback: MemoAsyncCallback { id: batch_index, module_address: @initia_std, - module_name: string::utf8(b"minitswap"), - }, + module_name: string::utf8(b"minitswap") + } }, - wasm: option::none(), + wasm: option::none() }; // set hook message @@ -2430,14 +2434,15 @@ module initia_std::minitswap { args: vector[ base64::to_string(bcs::to_bytes(&op_denom)), base64::to_string(bcs::to_bytes(&amount)), - base64::to_string(bcs::to_bytes(&receiver)),], - }, + base64::to_string(bcs::to_bytes(&receiver)) + ] + } ); let ibc_receiver = hook_contract; string::append( &mut ibc_receiver, - string::utf8(b"::minitswap_hook::minitswap_hook"), + string::utf8(b"::minitswap_hook::minitswap_hook") ); ibc_receiver } else if (vm_type == COSMWASM) { @@ -2446,14 +2451,14 @@ module initia_std::minitswap { message: MemoWasmMessage { contracts: hook_contract, funds: vector[MemoWasmFunds { - denom: op_denom, - amount: to_string(&amount), - },], + denom: op_denom, + amount: to_string(&amount) + }], msg: MemoWasmMinitswapHook { - minitswap_hook: MemoWasmMinitswapHookMsg { receiver, }, - }, - }, - }, + minitswap_hook: MemoWasmMinitswapHookMsg { receiver } + } + } + } ); hook_contract @@ -2476,12 +2481,12 @@ module initia_std::minitswap { version: String, state_root: String, storage_root: String, - latest_block_hash: String, + latest_block_hash: String } struct CosmosCoin has copy, drop { denom: String, - amount: u64, + amount: u64 } fun generate_finalize_token_withdrawal_msg( @@ -2496,7 +2501,7 @@ module initia_std::minitswap { version: String, state_root: String, storage_root: String, - latest_block_hash: String, + latest_block_hash: String ): vector { json::marshal( &FinalizeTokenWithdrawalRequest { @@ -2507,12 +2512,12 @@ module initia_std::minitswap { sender: to_sdk(sender), receiver: to_sdk(receiver), sequence, - amount: CosmosCoin { denom, amount, }, + amount: CosmosCoin { denom, amount }, version, state_root, storage_root, - latest_block_hash, - }, + latest_block_hash + } ) } @@ -2535,9 +2540,8 @@ module initia_std::minitswap { let addr = signer::address_of(account); let module_store = borrow_global(@initia_std); assert!( - addr == @initia_std - || (allow_admin && module_store.admin == addr), - error::permission_denied(EUNAUTHORIZED), + addr == @initia_std || (allow_admin && module_store.admin == addr), + error::permission_denied(EUNAUTHORIZED) ); } @@ -2557,7 +2561,7 @@ module initia_std::minitswap { let denom = string::utf8(b"ibc/"); string::append( &mut denom, - hex::encode_to_string_with_option(&hash, true), + hex::encode_to_string_with_option(&hash, true) ); denom } @@ -2581,7 +2585,7 @@ module initia_std::minitswap { object::create_object_address(&@initia_std, *string::bytes(&ibc_denom)); assert!( object::object_address(&ibc_op_init_metadata) == ibc_token_address, - error::invalid_argument(EINVAILD_METADATA), + error::invalid_argument(EINVAILD_METADATA) ); (op_denom, ibc_denom) @@ -2714,48 +2718,44 @@ module initia_std::minitswap { // R_fr = 0.5 + (R_max - 0.5) * (f * I) ** 3 / (1 + (f * I) ** 3) fun get_fully_recovered_ratio( - imbalance: &Decimal128, max_ratio: &Decimal128, recover_param: &Decimal128 - ): Decimal128 { - let fi = decimal128_safe_mul(recover_param, imbalance); - let fi3 = decimal128_safe_mul(&fi, &decimal128_safe_mul(&fi, &fi)); - let half = decimal128::from_ratio(1, 2); // .5 + imbalance: BigDecimal, max_ratio: BigDecimal, recover_param: BigDecimal + ): BigDecimal { + let fi = bigdecimal::mul(recover_param, imbalance); + let fi3 = bigdecimal::mul(fi, bigdecimal::mul(fi, fi)); + let half = bigdecimal::from_ratio_u64(1, 2); // .5 let to_sum = - decimal128_safe_mul( - &decimal128::sub(max_ratio, &half), // R_max - 0.5 - &decimal128_safe_from_ratio( - decimal128::val(&fi3), - decimal128::val(&decimal128::add(&decimal128::one(), &fi3)), - ), + bigdecimal::mul( + bigdecimal::sub(max_ratio, half), // R_max - 0.5 + bigdecimal::div(fi3, bigdecimal::add(bigdecimal::one(), fi3)) // (f * I) ** 3 / (1 + (f * I) ** 3) ); - decimal128::add(&half, &to_sum) + bigdecimal::add(half, to_sum) } fun get_fully_recovered_pool_amounts( - pool_size: u64, fully_recovered_ratio: &Decimal128, ann: u64 + pool_size: u64, fully_recovered_ratio: BigDecimal, ann: u64 ): (u64, u64) { - let denominator = decimal128::val(&decimal128::one()); - let fully_recovered_ratio_val = decimal128::val(fully_recovered_ratio); - let grad = - decimal128::from_ratio( - fully_recovered_ratio_val, - denominator - fully_recovered_ratio_val, + let one = bigdecimal::one(); + let g = + bigdecimal::div( + fully_recovered_ratio, bigdecimal::sub(one, fully_recovered_ratio) ); - let grad_val = decimal128::val(&grad); - - let pool_size = (pool_size as u128); - let pool_size_val = pool_size * denominator; + let z = pool_size; // Get first point - let d0 = get_d0((pool_size as u64), ann); - let x = ( - 2 * (pool_size_val as u256) / ((grad_val as u256) + (denominator as u256)) as u128 - ); // x = 2z / (g + 1) - if (x == (pool_size as u128)) { // fully_recovered_ratio = 0.5 - return ((pool_size as u64), (pool_size as u64)) + let d0 = get_d0(pool_size, ann); + let x = + bigdecimal::truncate_u64( + bigdecimal::div( + bigdecimal::mul_by_u64(bigdecimal::from_u64(z), 2), + bigdecimal::add(g, one) + ) + ); // x = 2z / (g + 1) + if (x == z) { // fully_recovered_ratio = 0.5 + return (pool_size, pool_size) }; - let y = (get_y(d0, (x as u64), ann) as u128); + let y = get_y(d0, (x as u64), ann); let i = 0; let x_prev; @@ -2767,24 +2767,21 @@ module initia_std::minitswap { // x = z * (x' - y') / (g * (x'- z) - (y' - z)) // x = z * (y' - x') / (g * (z - x') + (y' - z)) let temp_x = - ( - (pool_size as u256) * (y - x as u256) * (denominator as u256) - / ( - (grad_val as u256) * (pool_size - x as u256) - + (y - pool_size as u256) * (denominator as u256) - ) as u128 + bigdecimal::div( + bigdecimal::mul_by_u64(bigdecimal::from_u64(z), y - x), + bigdecimal::add_by_u64(bigdecimal::mul_by_u64(g, z - x), y - z) ); // get y from temp x - y = decimal128::mul_u128(&grad, temp_x); + y = bigdecimal::truncate_u64(bigdecimal::mul(g, temp_x)); // get x from y - x = (get_y(d0, (y as u64), ann) as u128); + x = get_y(d0, y, ann); // when fully recovered rate is too close to 0.5 y can be same with pool_size - if (y == pool_size) break; + if (y == z) break; // when fully recovered rate is too close to 0.5 x can be slightly higher than pool_size - if (x > pool_size) { + if (x > z) { x = pool_size; break }; @@ -2800,28 +2797,12 @@ module initia_std::minitswap { ((x as u64), (y as u64)) } - fun decimal128_safe_mul(a: &Decimal128, b: &Decimal128): Decimal128 { - let a_val = (decimal128::val(a) as u256); - let b_val = (decimal128::val(b) as u256); - let one = (decimal128::val(&decimal128::one()) as u256); - let val = (a_val * b_val / one as u128); - decimal128::new(val) - } - - fun decimal128_safe_from_ratio(a: u128, b: u128): Decimal128 { - let a = (a as u256); - let b = (b as u256); - let one = (decimal128::val(&decimal128::one()) as u256); - let val = (a * one / b as u128); - decimal128::new(val) - } - fun assert_min_amount(fa: &FungibleAsset, min_return: Option) { if (option::is_some(&min_return)) { let amount = fungible_asset::amount(fa); assert!( amount >= option::extract(&mut min_return), - error::invalid_state(EMIN_RETURN), + error::invalid_state(EMIN_RETURN) ) } } @@ -2830,7 +2811,7 @@ module initia_std::minitswap { public fun safe_swap_simulation( offer_metadata: Object, return_metadata: Object, - offer_amount: u64, + offer_amount: u64 ): (u64, u64) acquires ModuleStore, VirtualPool { let is_init_offered = is_init_metadata(offer_metadata); let ibc_op_init_metadata = @@ -2844,7 +2825,7 @@ module initia_std::minitswap { assert!( virtual_pool_exists, - error::invalid_argument(EPOOL_NOT_FOUND), + error::invalid_argument(EPOOL_NOT_FOUND) ); let (init_pool_amount, ibc_op_init_pool_amount) = @@ -2859,7 +2840,7 @@ module initia_std::minitswap { init_pool_amount, ibc_op_init_pool_amount, pool_size, - ann, + ann ); if (ibc_op_init_pool_amount - return_amount < pool_size) { @@ -2868,9 +2849,9 @@ module initia_std::minitswap { // take swap fee let swap_fee_amount = - decimal128::mul_u64( - &module_store.swap_fee_rate, - return_amount, + bigdecimal::mul_by_u64_ceil( + module_store.swap_fee_rate, + return_amount ); // take arb fee @@ -2879,9 +2860,9 @@ module initia_std::minitswap { return_amount - swap_fee_amount - offer_amount } else { 0 }; let arb_fee_amount = - decimal128::mul_u64( - &module_store.arb_fee_rate, - arb_profit, + bigdecimal::mul_by_u64_ceil( + module_store.arb_fee_rate, + arb_profit ); let fee_amount = swap_fee_amount + arb_fee_amount; @@ -2893,12 +2874,12 @@ module initia_std::minitswap { ibc_op_init_pool_amount, init_pool_amount, pool_size, - ann, + ann ); let fee_amount = - decimal128::mul_u64( - &module_store.swap_fee_rate, - return_amount, + bigdecimal::mul_by_u64_ceil( + module_store.swap_fee_rate, + return_amount ); (return_amount, fee_amount) @@ -2912,7 +2893,7 @@ module initia_std::minitswap { public fun safe_swap_simulation_given_out( offer_metadata: Object, return_metadata: Object, - return_amount: u64, + return_amount: u64 ): (u64, u64) acquires ModuleStore, VirtualPool { let is_init_offered = is_init_metadata(offer_metadata); let ibc_op_init_metadata = @@ -2926,7 +2907,7 @@ module initia_std::minitswap { assert!( virtual_pool_exists, - error::invalid_argument(EPOOL_NOT_FOUND), + error::invalid_argument(EPOOL_NOT_FOUND) ); let (init_pool_amount, ibc_op_init_pool_amount) = @@ -2942,16 +2923,13 @@ module initia_std::minitswap { // and recalculate offer amount repeatly until return amount <= actual return amount // note that actual return is always small or equal with target return amount - let denominator = decimal128::val(&decimal128::one()); - // adjust fee. return amount before swap fee = return amount * 1 / (1 - f) let return_amount_before_swap_fee = - ( - mul_div_u128( - (return_amount as u128), - denominator, - (denominator - decimal128::val(&module_store.swap_fee_rate)), - ) as u64 + bigdecimal::truncate_u64( + bigdecimal::div( + bigdecimal::from_u64(return_amount), + bigdecimal::sub(bigdecimal::one(), module_store.swap_fee_rate) + ) ); if (ibc_op_init_pool_amount - return_amount_before_swap_fee < pool_size) { return ((U64_MAX as u64), (U64_MAX as u64)) @@ -2965,7 +2943,7 @@ module initia_std::minitswap { init_pool_amount, ibc_op_init_pool_amount, pool_size, - ann, + ann ); // calculate arb fee @@ -2974,9 +2952,9 @@ module initia_std::minitswap { return_amount - offer_amount } else { 0 }; let arb_fee_amount = - decimal128::mul_u64( - &module_store.arb_fee_rate, - arb_profit, + bigdecimal::mul_by_u64_ceil( + module_store.arb_fee_rate, + arb_profit ); // actual return amount is return amount - arb fee @@ -2989,13 +2967,14 @@ module initia_std::minitswap { return_amount_before_swap_fee = return_amount_before_swap_fee + return_diff; - if (ibc_op_init_pool_amount - return_amount_before_swap_fee < pool_size) { + if (ibc_op_init_pool_amount - return_amount_before_swap_fee + < pool_size) { return ((U64_MAX as u64), (U64_MAX as u64)) }; - swap_fee_amount = decimal128::mul_u64( - &module_store.swap_fee_rate, - return_amount_before_swap_fee, + swap_fee_amount = bigdecimal::mul_by_u64_ceil( + module_store.swap_fee_rate, + return_amount_before_swap_fee ); offer_amount = get_offer_amount( @@ -3003,19 +2982,19 @@ module initia_std::minitswap { init_pool_amount, ibc_op_init_pool_amount, pool_size, - ann, + ann ); // calculate arb fee arb_profit = if (return_amount > offer_amount) { return_amount_before_swap_fee - swap_fee_amount - offer_amount } else { 0 }; - arb_fee_amount = decimal128::mul_u64( - &module_store.arb_fee_rate, - arb_profit, + arb_fee_amount = bigdecimal::mul_by_u64_ceil( + module_store.arb_fee_rate, + arb_profit ); - actual_return_amount = return_amount_before_swap_fee - swap_fee_amount - - arb_fee_amount; + actual_return_amount = return_amount_before_swap_fee + - swap_fee_amount - arb_fee_amount; if (actual_return_amount >= return_amount) break; return_diff = return_amount - actual_return_amount; @@ -3024,16 +3003,13 @@ module initia_std::minitswap { (offer_amount, swap_fee_amount + arb_fee_amount) } else { - let denominator = decimal128::val(&decimal128::one()); - // adjust fee. amount = amount * 1 / (1 - f) let return_amount_ = - ( - mul_div_u128( - (return_amount as u128), - denominator, - (denominator - decimal128::val(&module_store.swap_fee_rate)), - ) as u64 + bigdecimal::truncate_u64( + bigdecimal::div( + bigdecimal::from_u64(return_amount), + bigdecimal::sub(bigdecimal::one(), module_store.swap_fee_rate) + ) ); let fee_amount = return_amount_ - return_amount; @@ -3043,7 +3019,7 @@ module initia_std::minitswap { ibc_op_init_pool_amount, init_pool_amount, pool_size, - ann, + ann ); (offer_amount, fee_amount) @@ -3052,20 +3028,15 @@ module initia_std::minitswap { (offer_amount, fee_amount) } - fun mul_div_u128(a: u128, b: u128, c: u128): u128 { - return ((a as u256) * (b as u256) / (c as u256) as u128) - } - #[test_only] public fun init_module_for_test() { init_module(&initia_std::account::create_signer_for_test(@initia_std)); } #[test_only] - fun initialized_coin(account: &signer, symbol: String,) - : ( - coin::BurnCapability, coin::FreezeCapability, coin::MintCapability - ) { + fun initialized_coin( + account: &signer, symbol: String + ): (coin::BurnCapability, coin::FreezeCapability, coin::MintCapability) { let (mint_cap, burn_cap, freeze_cap, _) = coin::initialize_and_generate_extend_ref( account, @@ -3074,7 +3045,7 @@ module initia_std::minitswap { symbol, 6, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); return (burn_cap, freeze_cap, mint_cap) @@ -3094,32 +3065,32 @@ module initia_std::minitswap { _state_root: String, _storage_root: String, _latest_block_hash: String, - init_mint_cap: &coin::MintCapability, + init_mint_cap: &coin::MintCapability ) acquires ModuleStore, VirtualPool { // check arb info let module_store = borrow_global(@initia_std); let pool_obj = table::borrow( &module_store.global_arb_batch_map, - table_key::encode_u64(arb_index), + table_key::encode_u64(arb_index) ); let pool = borrow_global(object::object_address(&*pool_obj)); let arb_info = table::borrow( &pool.arb_batch_map, - table_key::encode_u64(arb_index), + table_key::encode_u64(arb_index) ); assert!( amount == arb_info.ibc_op_init_sent, - error::invalid_argument(EAMOUNT_MISMATCH), + error::invalid_argument(EAMOUNT_MISMATCH) ); // mock finalize withdraw coin::mint_to( init_mint_cap, object::address_from_extend_ref(&pool.extend_ref), - amount, + amount ); let module_signer = @@ -3129,7 +3100,7 @@ module initia_std::minitswap { finalize_arb_hook( &module_signer, arb_index, - signer::address_of(account), + signer::address_of(account) ); } @@ -3139,7 +3110,7 @@ module initia_std::minitswap { generate_finalize_token_withdrawal_msg( 1, 2, - vector[string::utf8(b"abc"), string::utf8(b"123"),], + vector[string::utf8(b"abc"), string::utf8(b"123")], @0x1, @0x2, 3, @@ -3148,7 +3119,7 @@ module initia_std::minitswap { string::utf8(b"version"), string::utf8(b"state_root"), string::utf8(b"storage_root"), - string::utf8(b"latest_block_hash"), + string::utf8(b"latest_block_hash") ); let json_str = b"{\"@type\":\"/opinit.ophost.v1.MsgFinalizeTokenWithdrawal\",\"amount\":{\"amount\":\"100\",\"denom\":\"uinit\"},\"bridge_id\":\"1\",\"latest_block_hash\":\"latest_block_hash\",\"output_index\":\"2\",\"receiver\":\"init1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzwsp0lj\",\"sender\":\"init1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpqr5e3d\",\"sequence\":\"3\",\"state_root\":\"state_root\",\"storage_root\":\"storage_root\",\"version\":\"version\",\"withdrawal_proofs\":[\"abc\",\"123\"]}"; @@ -3161,14 +3132,14 @@ module initia_std::minitswap { get_ibc_denom( string::utf8(b"channel-0"), string::utf8( - b"l2/771d639f30fbe45e3fbca954ffbe2fcc26f915f5513c67a4a2d0bc1d635bdefd", - ), + b"l2/771d639f30fbe45e3fbca954ffbe2fcc26f915f5513c67a4a2d0bc1d635bdefd" + ) ); assert!( string::utf8( b"ibc/82EB1C694C571F954E68BFD68CFCFCD6123B0EBB69AAA8BAB7A082939B45E802" ) == ibc_denom, - 0, + 0 ); } @@ -3179,7 +3150,7 @@ module initia_std::minitswap { string::utf8( b"l2/771d639f30fbe45e3fbca954ffbe2fcc26f915f5513c67a4a2d0bc1d635bdefd" ) == op_denom, - 0, + 0 ); } @@ -3195,41 +3166,41 @@ module initia_std::minitswap { initialized_coin( &chain, string::utf8( - b"ibc/82EB1C694C571F954E68BFD68CFCFCD6123B0EBB69AAA8BAB7A082939B45E802", - ), + b"ibc/82EB1C694C571F954E68BFD68CFCFCD6123B0EBB69AAA8BAB7A082939B45E802" + ) ); let init_metadata = coin::metadata(chain_addr, string::utf8(b"uinit")); let ibc_op_init_metadata = coin::metadata( chain_addr, string::utf8( - b"ibc/82EB1C694C571F954E68BFD68CFCFCD6123B0EBB69AAA8BAB7A082939B45E802", - ), + b"ibc/82EB1C694C571F954E68BFD68CFCFCD6123B0EBB69AAA8BAB7A082939B45E802" + ) ); coin::mint_to( &initia_mint_cap, chain_addr, - 1000000000, + 1000000000 ); coin::mint_to( &ibc_op_init_mint_cap, chain_addr, - 1000000000, + 1000000000 ); provide(&chain, 15000000, option::none()); create_pool( &chain, ibc_op_init_metadata, - decimal128::from_ratio(100000, 1), + bigdecimal::from_ratio_u64(100000, 1), 10000000, 3000, - decimal128::from_ratio(7, 10), - decimal128::from_ratio(2, 1), + bigdecimal::from_ratio_u64(7, 10), + bigdecimal::from_ratio_u64(2, 1), MOVE, string::utf8(b"0x1"), 1, - string::utf8(b"channel-0"), + string::utf8(b"channel-0") ); swap( @@ -3237,7 +3208,7 @@ module initia_std::minitswap { ibc_op_init_metadata, init_metadata, 10000000, - option::none(), + option::none() ); block::set_block_info(0, 100000); @@ -3248,7 +3219,7 @@ module initia_std::minitswap { ibc_op_init_metadata, init_metadata, 10000000, - option::none(), + option::none() ); let arb_info = get_arb_info(0); @@ -3270,7 +3241,7 @@ module initia_std::minitswap { str, str, str, - &initia_mint_cap, + &initia_mint_cap ); let excutor_balance_after = coin::balance(@0x1, init_metadata); @@ -3278,12 +3249,12 @@ module initia_std::minitswap { // check triggering fee assert!( excutor_balance_after - excutor_balance_before == arb_info.triggering_fee, - 0, + 0 ); } #[test(chain = @0x1)] - fun end_to_end(chain: signer,) acquires ModuleStore, VirtualPool { + fun end_to_end(chain: signer) acquires ModuleStore, VirtualPool { initia_std::primary_fungible_store::init_module_for_test(); init_module(&chain); stableswap::init_module_for_test(); @@ -3297,75 +3268,75 @@ module initia_std::minitswap { initialized_coin( &chain, string::utf8( - b"ibc/82EB1C694C571F954E68BFD68CFCFCD6123B0EBB69AAA8BAB7A082939B45E802", - ), + b"ibc/82EB1C694C571F954E68BFD68CFCFCD6123B0EBB69AAA8BAB7A082939B45E802" + ) ); let (_, _, ibc_op_init_2_mint_cap) = initialized_coin( &chain, string::utf8( - b"ibc/AD8D520BF2D981113B652A3BCD55368EF146FCB9E016F8B1DAECAA5D570BC8A1", - ), + b"ibc/AD8D520BF2D981113B652A3BCD55368EF146FCB9E016F8B1DAECAA5D570BC8A1" + ) ); let init_metadata = coin::metadata(chain_addr, string::utf8(b"uinit")); let ibc_op_init_1_metadata = coin::metadata( chain_addr, string::utf8( - b"ibc/82EB1C694C571F954E68BFD68CFCFCD6123B0EBB69AAA8BAB7A082939B45E802", - ), + b"ibc/82EB1C694C571F954E68BFD68CFCFCD6123B0EBB69AAA8BAB7A082939B45E802" + ) ); let ibc_op_init_2_metadata = coin::metadata( chain_addr, string::utf8( - b"ibc/AD8D520BF2D981113B652A3BCD55368EF146FCB9E016F8B1DAECAA5D570BC8A1", - ), + b"ibc/AD8D520BF2D981113B652A3BCD55368EF146FCB9E016F8B1DAECAA5D570BC8A1" + ) ); coin::mint_to( &initia_mint_cap, chain_addr, - 100000000, + 100000000 ); coin::mint_to( &ibc_op_init_1_mint_cap, chain_addr, - 1000000000, + 1000000000 ); coin::mint_to( &ibc_op_init_2_mint_cap, chain_addr, - 1000000000, + 1000000000 ); provide(&chain, 15000000, option::none()); create_pool( &chain, ibc_op_init_1_metadata, - decimal128::from_ratio(100000, 1), + bigdecimal::from_ratio_u64(100000, 1), 10000000, 3000, - decimal128::from_ratio(7, 10), - decimal128::from_ratio(2, 1), + bigdecimal::from_ratio_u64(7, 10), + bigdecimal::from_ratio_u64(2, 1), MOVE, string::utf8(b"0x1"), 1, - string::utf8(b"channel-0"), + string::utf8(b"channel-0") ); create_pool( &chain, ibc_op_init_2_metadata, - decimal128::from_ratio(100000, 1), + bigdecimal::from_ratio_u64(100000, 1), 10000000, 3000, - decimal128::from_ratio(7, 10), - decimal128::from_ratio(2, 1), + bigdecimal::from_ratio_u64(7, 10), + bigdecimal::from_ratio_u64(2, 1), MOVE, string::utf8(b"0x1"), 2, - string::utf8(b"channel-2"), + string::utf8(b"channel-2") ); create_stableswap_pool( @@ -3374,7 +3345,7 @@ module initia_std::minitswap { string::utf8(b"channel-0"), ibc_op_init_1_metadata, 10000000, - 10000000, + 10000000 ); // swap ibc op init to init @@ -3382,9 +3353,9 @@ module initia_std::minitswap { swap_simulation( ibc_op_init_1_metadata, init_metadata, - 1000000, + 1000000 ); - assert!(return_amount == 992741, 0); + assert!(return_amount == 992740, 0); let balance_before = coin::balance(chain_addr, init_metadata); swap( @@ -3392,12 +3363,12 @@ module initia_std::minitswap { ibc_op_init_1_metadata, init_metadata, 1000000, - option::none(), + option::none() ); let balance_after = coin::balance(chain_addr, init_metadata); assert!( balance_after - balance_before == return_amount, - 0, + 0 ); // swap init to ibc op init @@ -3405,9 +3376,9 @@ module initia_std::minitswap { swap_simulation( init_metadata, ibc_op_init_1_metadata, - 500000, + 500000 ); - assert!(return_amount == 504226, 0); + assert!(return_amount == 504224, 0); let balance_before = coin::balance(chain_addr, ibc_op_init_1_metadata); swap( @@ -3415,18 +3386,18 @@ module initia_std::minitswap { init_metadata, ibc_op_init_1_metadata, 500000, - option::none(), + option::none() ); let balance_after = coin::balance(chain_addr, ibc_op_init_1_metadata); assert!( balance_after - balance_before == return_amount, - 0, + 0 ); change_pool_size( &chain, ibc_op_init_1_metadata, - 9000000, + 9000000 ); } @@ -3439,16 +3410,16 @@ module initia_std::minitswap { 1, string::utf8(b"receiver"), string::utf8(b"op_denom"), - 1000000, + 1000000 ); assert!(ibc_receiver == string::utf8(b"0x1::minitswap_hook::minitswap_hook"), 0); assert!( memo == string::utf8( - b"{\"move\":{\"async_callback\":{\"id\":\"1\",\"module_address\":\"0x1\",\"module_name\":\"minitswap\"},\"message\":{\"args\":[\"CG9wX2Rlbm9t\",\"QEIPAAAAAAA=\",\"CHJlY2VpdmVy\"],\"function_name\":\"minitswap_hook\",\"module_address\":\"0x1\",\"module_name\":\"minitswap_hook\",\"type_args\":[]}},\"wasm\":null}", + b"{\"move\":{\"async_callback\":{\"id\":\"1\",\"module_address\":\"0x1\",\"module_name\":\"minitswap\"},\"message\":{\"args\":[\"CG9wX2Rlbm9t\",\"QEIPAAAAAAA=\",\"CHJlY2VpdmVy\"],\"function_name\":\"minitswap_hook\",\"module_address\":\"0x1\",\"module_name\":\"minitswap_hook\",\"type_args\":[]}},\"wasm\":null}" ), - 1, + 1 ); let (ibc_receiver, memo) = @@ -3458,16 +3429,16 @@ module initia_std::minitswap { 1, string::utf8(b"receiver"), string::utf8(b"op_denom"), - 1000000, + 1000000 ); assert!(ibc_receiver == string::utf8(b"cosmwasm_contract_addr"), 2); assert!( memo == string::utf8( - b"{\"move\":{\"async_callback\":{\"id\":\"1\",\"module_address\":\"0x1\",\"module_name\":\"minitswap\"},\"message\":null},\"wasm\":{\"message\":{\"contracts\":\"cosmwasm_contract_addr\",\"funds\":[{\"amount\":\"1000000\",\"denom\":\"op_denom\"}],\"msg\":{\"minitswap_hook\":{\"receiver\":\"receiver\"}}}}}", + b"{\"move\":{\"async_callback\":{\"id\":\"1\",\"module_address\":\"0x1\",\"module_name\":\"minitswap\"},\"message\":null},\"wasm\":{\"message\":{\"contracts\":\"cosmwasm_contract_addr\",\"funds\":[{\"amount\":\"1000000\",\"denom\":\"op_denom\"}],\"msg\":{\"minitswap_hook\":{\"receiver\":\"receiver\"}}}}}" ), - 3, + 3 ); } } diff --git a/initia_stdlib/sources/multisig.move b/initia_stdlib/sources/multisig.move index 9cbea4e..81b5f81 100644 --- a/initia_stdlib/sources/multisig.move +++ b/initia_stdlib/sources/multisig.move @@ -34,7 +34,7 @@ module initia_std::multisig { // constants - const STATUS: vector> = vector[b"in voting preiod", b"executed", b"expired",]; + const STATUS: vector> = vector[b"in voting preiod", b"executed", b"expired"]; const MAX_LIMIT: u8 = 30; @@ -45,7 +45,7 @@ module initia_std::multisig { /// If both `height` and `timestamp` are set, and only one of them has expired, the period is considered expired. struct Period has copy, drop, store { height: Option, - timestamp: Option, + timestamp: Option } struct MultisigWallet has key { @@ -54,7 +54,7 @@ module initia_std::multisig { members: vector
, // members of multisig account threshold: u64, // require votes to pass max_voting_period: Period, // max voting period - proposals: Table, + proposals: Table } struct Proposal has store { @@ -69,7 +69,7 @@ module initia_std::multisig { votes: SimpleMap, status: u8, is_json: bool, - json_args: vector, + json_args: vector } // events @@ -91,7 +91,7 @@ module initia_std::multisig { function_name: String, type_args: vector, args: vector>, - config_version: u64, + config_version: u64 } #[event] @@ -99,14 +99,14 @@ module initia_std::multisig { multisig_addr: address, proposal_id: u64, voter: address, - vote_yes: bool, + vote_yes: bool } #[event] struct ExecuteProposalEvent has drop, store { multisig_addr: address, proposal_id: u64, - executor: address, + executor: address } #[event] @@ -133,7 +133,7 @@ module initia_std::multisig { yes_vote_count: u64, status: String, is_json: bool, - json_args: vector, + json_args: vector } struct ConfigResponse has drop { @@ -141,19 +141,21 @@ module initia_std::multisig { config_version: u64, members: vector
, threshold: u64, - max_voting_period: Period, + max_voting_period: Period } // view functions #[view] - public fun get_proposal(multisig_addr: address, proposal_id: u64): ProposalResponse acquires MultisigWallet { + public fun get_proposal( + multisig_addr: address, proposal_id: u64 + ): ProposalResponse acquires MultisigWallet { let multisig_wallet = borrow_global(multisig_addr); let proposal = table::borrow(&multisig_wallet.proposals, proposal_id); proposal_to_proposal_response( multisig_wallet, multisig_addr, proposal_id, - proposal, + proposal ) } @@ -170,12 +172,11 @@ module initia_std::multisig { &multisig_wallet.proposals, option::none(), start_after, - 2, + 2 ); - while (vector::length(&res) < (limit as u64) && table::prepare( - iter - )) { + while (vector::length(&res) < (limit as u64) + && table::prepare(iter)) { let (proposal_id, proposal) = table::next(iter); vector::push_back( &mut res, @@ -183,8 +184,8 @@ module initia_std::multisig { multisig_wallet, multisig_addr, proposal_id, - proposal, - ), + proposal + ) ); }; @@ -200,7 +201,7 @@ module initia_std::multisig { config_version: multisig_wallet.config_version, members: multisig_wallet.members, threshold: multisig_wallet.threshold, - max_voting_period: multisig_wallet.max_voting_period, + max_voting_period: multisig_wallet.max_voting_period } } @@ -213,12 +214,12 @@ module initia_std::multisig { members: vector
, threshold: u64, max_voting_period_height: Option, - max_voting_period_timestamp: Option, + max_voting_period_timestamp: Option ) { assert_member(&members, &signer::address_of(account)); assert!( vector::length(&members) >= threshold, - error::invalid_argument(EINVALID_THRESHOLD), + error::invalid_argument(EINVALID_THRESHOLD) ); let constructor_ref = object::create_named_object( account, *string::bytes(&name) @@ -228,12 +229,12 @@ module initia_std::multisig { let multisig_addr = signer::address_of(&multisig_signer); let max_voting_period = Period { height: max_voting_period_height, - timestamp: max_voting_period_timestamp, + timestamp: max_voting_period_timestamp }; let members_map = simple_map::create(); vector::for_each( members, - |member| simple_map::add(&mut members_map, member, true), + |member| simple_map::add(&mut members_map, member, true) ); // just for check uniqueness move_to( @@ -244,8 +245,8 @@ module initia_std::multisig { members, threshold, max_voting_period, - proposals: table::new(), - }, + proposals: table::new() + } ); event::emit( @@ -253,8 +254,8 @@ module initia_std::multisig { multisig_addr, members, threshold, - max_voting_period, - }, + max_voting_period + } ) } @@ -266,7 +267,7 @@ module initia_std::multisig { module_name: String, function_name: String, type_args: vector, - args: vector>, + args: vector> ) acquires MultisigWallet { create_proposal_internal( account, @@ -277,7 +278,7 @@ module initia_std::multisig { type_args, args, false, - vector[], + vector[] ) } @@ -289,7 +290,7 @@ module initia_std::multisig { module_name: String, function_name: String, type_args: vector, - args: vector, + args: vector ) acquires MultisigWallet { create_proposal_internal( account, @@ -300,7 +301,7 @@ module initia_std::multisig { type_args, vector[], true, - args, + args ) } @@ -309,7 +310,7 @@ module initia_std::multisig { account: &signer, multisig_addr: address, proposal_id: u64, - vote_yes: bool, + vote_yes: bool ) acquires MultisigWallet { let voter = signer::address_of(account); let multisig_wallet = borrow_global_mut(multisig_addr); @@ -318,9 +319,9 @@ module initia_std::multisig { assert!( table::contains( &multisig_wallet.proposals, - proposal_id, + proposal_id ), - error::invalid_argument(EPROPOSAL_NOT_FOUND), + error::invalid_argument(EPROPOSAL_NOT_FOUND) ); let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id); @@ -330,15 +331,13 @@ module initia_std::multisig { vote(&mut proposal.votes, voter, vote_yes); event::emit( - VoteProposalEvent { multisig_addr, proposal_id, voter, vote_yes, }, + VoteProposalEvent { multisig_addr, proposal_id, voter, vote_yes } ) } /// Execute proposal public entry fun execute_proposal( - account: &signer, - multisig_addr: address, - proposal_id: u64, + account: &signer, multisig_addr: address, proposal_id: u64 ) acquires MultisigWallet { let executor = signer::address_of(account); let multisig_wallet = borrow_global_mut(multisig_addr); @@ -347,9 +346,9 @@ module initia_std::multisig { assert!( table::contains( &multisig_wallet.proposals, - proposal_id, + proposal_id ), - error::invalid_argument(EPROPOSAL_NOT_FOUND), + error::invalid_argument(EPROPOSAL_NOT_FOUND) ); let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id); @@ -360,9 +359,9 @@ module initia_std::multisig { assert!( yes_vote_count( &proposal.votes, - &multisig_wallet.members, + &multisig_wallet.members ) >= multisig_wallet.threshold, - error::invalid_state(ENOT_PASS), + error::invalid_state(ENOT_PASS) ); let multisig_signer = @@ -375,7 +374,7 @@ module initia_std::multisig { proposal.module_name, proposal.function_name, proposal.type_args, - proposal.args, + proposal.args ) } else { move_execute_with_json( @@ -384,14 +383,14 @@ module initia_std::multisig { proposal.module_name, proposal.function_name, proposal.type_args, - proposal.json_args, + proposal.json_args ) }; proposal.status = 1; // executed event::emit( - ExecuteProposalEvent { multisig_addr, proposal_id, executor, }, + ExecuteProposalEvent { multisig_addr, proposal_id, executor } ) } @@ -401,23 +400,23 @@ module initia_std::multisig { new_members: vector
, new_threshold: u64, new_max_voting_period_height: Option, - new_max_voting_period_timestamp: Option, + new_max_voting_period_timestamp: Option ) acquires MultisigWallet { let multisig_addr = signer::address_of(account); let multisig_wallet = borrow_global_mut(multisig_addr); assert!( vector::length(&new_members) >= new_threshold, - error::invalid_argument(EINVALID_THRESHOLD), + error::invalid_argument(EINVALID_THRESHOLD) ); let new_members_map = simple_map::create(); vector::for_each( new_members, - |member| simple_map::add(&mut new_members_map, member, true), + |member| simple_map::add(&mut new_members_map, member, true) ); // just for check uniqueness let new_max_voting_period = Period { height: new_max_voting_period_height, - timestamp: new_max_voting_period_timestamp, + timestamp: new_max_voting_period_timestamp }; multisig_wallet.config_version = multisig_wallet.config_version + 1; @@ -430,8 +429,8 @@ module initia_std::multisig { multisig_addr, members: new_members, threshold: new_threshold, - max_voting_period: new_max_voting_period, - }, + max_voting_period: new_max_voting_period + } ) } @@ -444,7 +443,7 @@ module initia_std::multisig { type_args: vector, args: vector>, is_json: bool, - json_args: vector, + json_args: vector ) acquires MultisigWallet { let addr = signer::address_of(account); let multisig_wallet = borrow_global_mut(multisig_addr); @@ -465,14 +464,14 @@ module initia_std::multisig { votes: simple_map::create(), status: 0, // in voting period is_json, - json_args, + json_args }; let proposal_id = table::length(&multisig_wallet.proposals) + 1; table::add( &mut multisig_wallet.proposals, proposal_id, - proposal, + proposal ); event::emit( @@ -484,8 +483,8 @@ module initia_std::multisig { function_name, type_args, args, - config_version, - }, + config_version + } ) } @@ -529,10 +528,10 @@ module initia_std::multisig { members, |member| { if (simple_map::contains_key(votes, member) - && *simple_map::borrow(votes, member)) { + && *simple_map::borrow(votes, member)) { yes_count = yes_count + 1; } - }, + } ); yes_count @@ -542,14 +541,14 @@ module initia_std::multisig { multisig_wallet: &MultisigWallet, multisig_addr: address, proposal_id: u64, - proposal: &Proposal, + proposal: &Proposal ): ProposalResponse { let status_index = proposal.status; let is_expired = is_proposal_expired( &multisig_wallet.max_voting_period, proposal.proposal_height, - proposal.proposal_timestamp, + proposal.proposal_timestamp ); let yes_vote_count = yes_vote_count(&proposal.votes, &multisig_wallet.members); if (status_index == 0 && is_expired) { @@ -570,14 +569,14 @@ module initia_std::multisig { yes_vote_count, status: string::utf8(*vector::borrow(&STATUS, (status_index as u64))), is_json: proposal.is_json, - json_args: proposal.json_args, + json_args: proposal.json_args } } inline fun assert_member(members: &vector
, member: &address) { assert!( vector::contains(members, member), - error::permission_denied(ENOT_MEMBER), + error::permission_denied(ENOT_MEMBER) ) } @@ -586,7 +585,7 @@ module initia_std::multisig { ) { assert!( multisig_wallet_config_version == execute_proposal.config_version, - error::invalid_state(EOLD_CONFIG_VERSION), + error::invalid_state(EOLD_CONFIG_VERSION) ) } @@ -595,28 +594,30 @@ module initia_std::multisig { ) { assert!( proposal.status == 0, - error::invalid_state(EINVALID_PROPOSAL_STATUS), + error::invalid_state(EINVALID_PROPOSAL_STATUS) ); assert!( !is_proposal_expired( max_voting_period, proposal.proposal_height, - proposal.proposal_timestamp, + proposal.proposal_timestamp ), - error::invalid_state(EPROPOSAL_EXPIRED), + error::invalid_state(EPROPOSAL_EXPIRED) ); } #[test_only] use initia_std::block::set_block_info; - #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104)] + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] #[expected_failure(abort_code = 0x50002, location = Self)] fun create_wallet_by_other( account1: signer, account2: signer, account3: signer, - account4: signer, + account4: signer ) { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -629,16 +630,14 @@ module initia_std::multisig { vector[addr1, addr2, addr3], 2, option::none(), - option::none(), + option::none() ); } #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] #[expected_failure(abort_code = 0x10001, location = Self)] fun invalid_threshold( - account1: signer, - account2: signer, - account3: signer, + account1: signer, account2: signer, account3: signer ) { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -651,16 +650,14 @@ module initia_std::multisig { vector[addr1, addr2, addr3], 4, option::none(), - option::none(), + option::none() ); } #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] - #[expected_failure(abort_code = 0x10000, location = simple_map)] + #[expected_failure(abort_code = 0x10001, location = simple_map)] fun duplicated_member( - account1: signer, - account2: signer, - account3: signer, + account1: signer, account2: signer, account3: signer ) { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -673,17 +670,19 @@ module initia_std::multisig { vector[addr1, addr1, addr2, addr3], 3, option::none(), - option::none(), + option::none() ); } - #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104)] + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] #[expected_failure(abort_code = 0x50002, location = Self)] fun create_proposal_by_other( account1: signer, account2: signer, account3: signer, - account4: signer, + account4: signer ) acquires MultisigWallet { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -697,7 +696,7 @@ module initia_std::multisig { vector[addr1, addr2, addr3], 2, option::none(), - option::none(), + option::none() ); let multisig_addr = object::create_object_address(&addr1, b"multisig wallet"); @@ -712,17 +711,20 @@ module initia_std::multisig { std::bcs::to_bytes(&vector[addr1, addr2, addr4]), std::bcs::to_bytes(&3u64), std::bcs::to_bytes(&option::none()), - std::bcs::to_bytes(&option::none()),], + std::bcs::to_bytes(&option::none()) + ] ); } - #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104)] + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] #[expected_failure(abort_code = 0x50002, location = Self)] fun vote_by_other( account1: signer, account2: signer, account3: signer, - account4: signer, + account4: signer ) acquires MultisigWallet { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -736,7 +738,7 @@ module initia_std::multisig { vector[addr1, addr2, addr3], 2, option::none(), - option::none(), + option::none() ); let multisig_addr = object::create_object_address(&addr1, b"multisig wallet"); @@ -751,19 +753,22 @@ module initia_std::multisig { std::bcs::to_bytes(&vector[addr1, addr2, addr4]), std::bcs::to_bytes(&3u64), std::bcs::to_bytes(&option::none()), - std::bcs::to_bytes(&option::none()),], + std::bcs::to_bytes(&option::none()) + ] ); vote_proposal(&account4, multisig_addr, 1, true); } - #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104)] + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] #[expected_failure(abort_code = 0x30005, location = Self)] fun vote_after_height_expired( account1: signer, account2: signer, account3: signer, - account4: signer, + account4: signer ) acquires MultisigWallet { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -777,7 +782,7 @@ module initia_std::multisig { vector[addr1, addr2, addr3], 2, option::some(10), - option::some(10), + option::some(10) ); let multisig_addr = object::create_object_address(&addr1, b"multisig wallet"); @@ -793,20 +798,23 @@ module initia_std::multisig { std::bcs::to_bytes(&vector[addr1, addr2, addr4]), std::bcs::to_bytes(&3u64), std::bcs::to_bytes(&option::none()), - std::bcs::to_bytes(&option::none()),], + std::bcs::to_bytes(&option::none()) + ] ); set_block_info(111, 100); vote_proposal(&account1, multisig_addr, 1, true); } - #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104)] + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] #[expected_failure(abort_code = 0x30005, location = Self)] fun vote_after_timestamp_expired( account1: signer, account2: signer, account3: signer, - account4: signer, + account4: signer ) acquires MultisigWallet { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -820,7 +828,7 @@ module initia_std::multisig { vector[addr1, addr2, addr3], 2, option::some(10), - option::some(10), + option::some(10) ); let multisig_addr = object::create_object_address(&addr1, b"multisig wallet"); @@ -836,20 +844,23 @@ module initia_std::multisig { std::bcs::to_bytes(&vector[addr1, addr2, addr4]), std::bcs::to_bytes(&3u64), std::bcs::to_bytes(&option::none()), - std::bcs::to_bytes(&option::none()),], + std::bcs::to_bytes(&option::none()) + ] ); set_block_info(100, 111); vote_proposal(&account1, multisig_addr, 1, true); } - #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104)] + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] #[expected_failure(abort_code = 0x30008, location = Self)] fun execute_not_pass( account1: signer, account2: signer, account3: signer, - account4: signer, + account4: signer ) acquires MultisigWallet { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -863,7 +874,7 @@ module initia_std::multisig { vector[addr1, addr2, addr3], 2, option::none(), - option::none(), + option::none() ); let multisig_addr = object::create_object_address(&addr1, b"multisig wallet"); @@ -878,7 +889,8 @@ module initia_std::multisig { std::bcs::to_bytes(&vector[addr1, addr2, addr4]), std::bcs::to_bytes(&3u64), std::bcs::to_bytes(&option::none()), - std::bcs::to_bytes(&option::none()),], + std::bcs::to_bytes(&option::none()) + ] ); vote_proposal(&account1, multisig_addr, 1, true); @@ -888,13 +900,15 @@ module initia_std::multisig { execute_proposal(&account1, multisig_addr, 1); } - #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104)] + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] #[expected_failure(abort_code = 0x30003, location = Self)] fun execute_after_config_update( account1: signer, account2: signer, account3: signer, - account4: signer, + account4: signer ) acquires MultisigWallet { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -908,7 +922,7 @@ module initia_std::multisig { vector[addr1, addr2, addr3], 2, option::none(), - option::none(), + option::none() ); let multisig_addr = object::create_object_address(&addr1, b"multisig wallet"); @@ -923,7 +937,8 @@ module initia_std::multisig { std::bcs::to_bytes(&vector[addr1, addr2, addr4]), std::bcs::to_bytes(&3u64), std::bcs::to_bytes(&option::none()), - std::bcs::to_bytes(&option::none()),], + std::bcs::to_bytes(&option::none()) + ] ); vote_proposal(&account1, multisig_addr, 1, true); @@ -938,7 +953,7 @@ module initia_std::multisig { vector[addr1, addr2, addr4], 2, option::none(), - option::none(), + option::none() ); execute_proposal(&account1, multisig_addr, 1); @@ -946,9 +961,7 @@ module initia_std::multisig { #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] fun proposal_with_json( - account1: signer, - account2: signer, - account3: signer, + account1: signer, account2: signer, account3: signer ) acquires MultisigWallet { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -961,7 +974,7 @@ module initia_std::multisig { vector[addr1, addr2, addr3], 2, option::none(), - option::none(), + option::none() ); let multisig_addr = object::create_object_address(&addr1, b"multisig wallet"); @@ -976,18 +989,19 @@ module initia_std::multisig { string::utf8(b"[\"0x101\", \"0x102\", \"0x104\"]"), string::utf8(b"\"3\""), string::utf8(b""), - string::utf8(b""),], + string::utf8(b"") + ] ); let proposal = get_proposal(multisig_addr, 1); assert!(proposal.module_address == @initia_std, 0); assert!( proposal.module_name == string::utf8(b"multisig"), - 1, + 1 ); assert!( proposal.function_name == string::utf8(b"update_config"), - 2, + 2 ); assert!(proposal.type_args == vector[], 3); assert!( @@ -996,8 +1010,9 @@ module initia_std::multisig { string::utf8(b"[\"0x101\", \"0x102\", \"0x104\"]"), string::utf8(b"\"3\""), string::utf8(b""), - string::utf8(b""),], - 4, + string::utf8(b"") + ], + 4 ); assert!(proposal.args == vector[], 5); } diff --git a/initia_stdlib/sources/object.move b/initia_stdlib/sources/object.move index 373d642..779e242 100644 --- a/initia_stdlib/sources/object.move +++ b/initia_stdlib/sources/object.move @@ -28,6 +28,7 @@ module initia_std::object { use initia_std::event; friend initia_std::primary_fungible_store; + friend initia_std::nft; /// An object already exists at this address const EOBJECT_EXISTS: u64 = 1; @@ -82,7 +83,7 @@ module initia_std::object { /// Tombstone is version store for deleted objects with version struct Tombstone has key { - version: u64, + version: u64 } /// The core of the object model that defines ownership, transferability, and events. @@ -93,7 +94,7 @@ module initia_std::object { /// transfers bypassing the use of a TransferRef. allow_ungated_transfer: bool, /// The version is to invalidate the refs, which are generated for previously burnt object. - version: u64, + version: u64 } /// A pointer to an object -- these can only provide guarantees based upon the underlying data @@ -101,7 +102,7 @@ module initia_std::object { /// by any other module than the module that defined T. Similarly, the module that defines T /// can remove it from storage at any point in time. struct Object has copy, drop, store { - inner: address, + inner: address } /// This is a one time ability given to the creator to configure the object as necessary @@ -109,25 +110,25 @@ module initia_std::object { self: address, /// True if the object can be deleted. can_delete: bool, - version: u64, + version: u64 } /// Used to remove an object from storage. struct DeleteRef has drop, store { self: address, - version: u64, + version: u64 } /// Used to create events or move additional resources into object storage. struct ExtendRef has drop, store { self: address, - version: u64, + version: u64 } /// Used to create LinearTransferRef, hence ownership transfer. struct TransferRef has drop, store { self: address, - version: u64, + version: u64 } /// Used to perform transfers. This locks transferring ability to a single time use bound to @@ -135,13 +136,13 @@ module initia_std::object { struct LinearTransferRef has drop { self: address, owner: address, - version: u64, + version: u64 } /// Used to create derived objects from a given objects. struct DeriveRef has drop, store { self: address, - version: u64, + version: u64 } #[event] @@ -149,7 +150,7 @@ module initia_std::object { struct CreateEvent has drop, store { object: address, owner: address, - version: u64, + version: u64 } #[event] @@ -157,18 +158,18 @@ module initia_std::object { struct TransferEvent has drop, store { object: address, from: address, - to: address, + to: address } /// Produces an ObjectId from the given address. This is not verified. public fun address_to_object(object: address): Object { assert!( exists(object), - error::not_found(EOBJECT_DOES_NOT_EXIST), + error::not_found(EOBJECT_DOES_NOT_EXIST) ); assert!( exists_at(object), - error::not_found(ERESOURCE_DOES_NOT_EXIST), + error::not_found(ERESOURCE_DOES_NOT_EXIST) ); Object { inner: object } } @@ -178,6 +179,11 @@ module initia_std::object { exists(object) } + /// Returns true if there exists an object with resource T. + public fun object_exists(object: address): bool { + exists(object) && exists_at(object) + } + /// Derives an object address from source material: sha3_256([creator address | seed | 0xFE]). public fun create_object_address(source: &address, seed: vector): address { let bytes = bcs::to_bytes(source); @@ -220,7 +226,9 @@ module initia_std::object { /// Create a new named object and return the ConstructorRef. /// Named objects can be queried globally by knowing the user generated seed used to create them. - public fun create_named_object(creator: &signer, seed: vector): ConstructorRef acquires Tombstone { + public fun create_named_object( + creator: &signer, seed: vector + ): ConstructorRef acquires Tombstone { let creator_address = signer::address_of(creator); let obj_addr = create_object_address(&creator_address, seed); create_object_internal(creator_address, obj_addr, false) @@ -236,6 +244,16 @@ module initia_std::object { create_object_internal(creator_address, obj_addr, true) } + /// Create a new object to represent an NFT and return the ConstructorRef. + /// Nft objects can be queried globally by knowing the user generated seed used to create them + /// and the creator's address. NFT objects can be deleted. + public(friend) fun create_nft_object( + owner: address, creator: address, seed: vector + ): ConstructorRef acquires Tombstone { + let obj_addr = create_object_address(&creator, seed); + create_object_internal(owner, obj_addr, true) + } + /// Create a new object whose address is derived based on the creator account address and another object. /// Derivde objects, similar to named objects, cannot be deleted. public(friend) fun create_user_derived_object( @@ -246,32 +264,32 @@ module initia_std::object { create_object_internal( creator_address, obj_addr, - can_delete, + can_delete ) } /// Create a new object by generating a random unique address based on transaction hash. /// The unique address is computed sha3_256([transaction hash | auid counter | 0xFB]). - public fun create_object(owner_address: address, can_delete: bool): ConstructorRef acquires Tombstone { + public fun create_object( + owner_address: address, can_delete: bool + ): ConstructorRef acquires Tombstone { let unique_address = transaction_context::generate_unique_address(); create_object_internal( owner_address, unique_address, - can_delete, + can_delete ) } fun create_object_internal( - creator_address: address, - object: address, - can_delete: bool, + creator_address: address, object: address, can_delete: bool ): ConstructorRef acquires Tombstone { // create resource account to prevent address overapping. account::create_object_account(object); assert!( !exists(object), - error::already_exists(EOBJECT_EXISTS), + error::already_exists(EOBJECT_EXISTS) ); let object_signer = account::create_signer(object); let version = @@ -282,12 +300,10 @@ module initia_std::object { move_to( &object_signer, - ObjectCore { owner: creator_address, allow_ungated_transfer: true, version, }, + ObjectCore { owner: creator_address, allow_ungated_transfer: true, version } ); - event::emit( - CreateEvent { owner: creator_address, object, version, } - ); + event::emit(CreateEvent { owner: creator_address, object, version }); ConstructorRef { self: object, version, can_delete } } @@ -298,7 +314,7 @@ module initia_std::object { public fun generate_delete_ref(ref: &ConstructorRef): DeleteRef { assert!( ref.can_delete, - error::permission_denied(ECANNOT_DELETE), + error::permission_denied(ECANNOT_DELETE) ); DeleteRef { self: ref.self, version: ref.version } } @@ -355,15 +371,15 @@ module initia_std::object { let object_core = move_from(ref.self); assert!( ref.version == object_core.version, - error::permission_denied(EVERSION_MISMATCH), + error::permission_denied(EVERSION_MISMATCH) ); - let ObjectCore { owner: _, allow_ungated_transfer: _, version, } = object_core; + let ObjectCore { owner: _, allow_ungated_transfer: _, version } = object_core; // set tombstone move_to( &account::create_signer(ref.self), - Tombstone { version, }, + Tombstone { version } ); } @@ -374,7 +390,7 @@ module initia_std::object { let object_core = borrow_global(ref.self); assert!( ref.version == object_core.version, - error::permission_denied(EVERSION_MISMATCH), + error::permission_denied(EVERSION_MISMATCH) ); account::create_signer(ref.self) @@ -392,7 +408,7 @@ module initia_std::object { let object_core = borrow_global_mut(ref.self); assert!( ref.version == object_core.version, - error::permission_denied(EVERSION_MISMATCH), + error::permission_denied(EVERSION_MISMATCH) ); object_core.allow_ungated_transfer = false; @@ -403,7 +419,7 @@ module initia_std::object { let object_core = borrow_global_mut(ref.self); assert!( ref.version == object_core.version, - error::permission_denied(EVERSION_MISMATCH), + error::permission_denied(EVERSION_MISMATCH) ); object_core.allow_ungated_transfer = true; @@ -411,17 +427,19 @@ module initia_std::object { /// Create a LinearTransferRef for a one-time transfer. This requires that the owner at the /// time of generation is the owner at the time of transferring. - public fun generate_linear_transfer_ref(ref: &TransferRef): LinearTransferRef acquires ObjectCore { + public fun generate_linear_transfer_ref( + ref: &TransferRef + ): LinearTransferRef acquires ObjectCore { let object_core = borrow_global(ref.self); assert!( ref.version == object_core.version, - error::permission_denied(EVERSION_MISMATCH), + error::permission_denied(EVERSION_MISMATCH) ); LinearTransferRef { self: ref.self, owner: object_core.owner, - version: object_core.version, + version: object_core.version } } @@ -430,25 +448,21 @@ module initia_std::object { let object_core = borrow_global_mut(ref.self); assert!( ref.version == object_core.version, - error::permission_denied(EVERSION_MISMATCH), + error::permission_denied(EVERSION_MISMATCH) ); assert!( object_core.owner == ref.owner, - error::permission_denied(ENOT_OBJECT_OWNER), + error::permission_denied(ENOT_OBJECT_OWNER) ); - event::emit( - TransferEvent { object: ref.self, from: object_core.owner, to, }, - ); + event::emit(TransferEvent { object: ref.self, from: object_core.owner, to }); object_core.owner = to; } /// Entry function that can be used to transfer, if allow_ungated_transfer is set true. public entry fun transfer_call( - owner: &signer, - object: address, - to: address, + owner: &signer, object: address, to: address ) acquires ObjectCore { transfer_raw(owner, object, to) } @@ -456,9 +470,7 @@ module initia_std::object { /// Transfers ownership of the object (and all associated resources) at the specified address /// for Object to the "to" address. public entry fun transfer( - owner: &signer, - object: Object, - to: address, + owner: &signer, object: Object, to: address ) acquires ObjectCore { transfer_raw(owner, object.inner, to) } @@ -467,28 +479,20 @@ module initia_std::object { /// allow_ungated_transfer is set true. Note, that this allows the owner of a nested object to /// transfer that object, so long as allow_ungated_transfer is enabled at each stage in the /// hierarchy. - public fun transfer_raw( - owner: &signer, - object: address, - to: address, - ) acquires ObjectCore { + public fun transfer_raw(owner: &signer, object: address, to: address) acquires ObjectCore { let owner_address = signer::address_of(owner); verify_ungated_and_descendant(owner_address, object); let object_core = borrow_global_mut(object); if (object_core.owner == to) { return }; - event::emit( - TransferEvent { object: object, from: object_core.owner, to, }, - ); + event::emit(TransferEvent { object: object, from: object_core.owner, to }); object_core.owner = to; } /// Transfer the given object to another object. See `transfer` for more information. public entry fun transfer_to_object( - owner: &signer, - object: Object, - to: Object, + owner: &signer, object: Object, to: Object ) acquires ObjectCore { transfer(owner, object, to.inner) } @@ -502,13 +506,13 @@ module initia_std::object { let current_address = destination; assert!( exists(current_address), - error::not_found(EOBJECT_DOES_NOT_EXIST), + error::not_found(EOBJECT_DOES_NOT_EXIST) ); let object = borrow_global(current_address); assert!( object.allow_ungated_transfer, - error::permission_denied(ENO_UNGATED_TRANSFERS), + error::permission_denied(ENO_UNGATED_TRANSFERS) ); let current_address = object.owner; @@ -518,19 +522,19 @@ module initia_std::object { count = count + 1; assert!( count < MAXIMUM_OBJECT_NESTING, - error::out_of_range(EMAXIMUM_NESTING), + error::out_of_range(EMAXIMUM_NESTING) ); // At this point, the first object exists and so the more likely case is that the // object's owner is not an object. So we return a more sensible error. assert!( exists(current_address), - error::permission_denied(ENOT_OBJECT_OWNER), + error::permission_denied(ENOT_OBJECT_OWNER) ); let object = borrow_global(current_address); assert!( object.allow_ungated_transfer, - error::permission_denied(ENO_UNGATED_TRANSFERS), + error::permission_denied(ENO_UNGATED_TRANSFERS) ); current_address = object.owner; @@ -544,7 +548,7 @@ module initia_std::object { public fun ungated_transfer_allowed(object: Object): bool acquires ObjectCore { assert!( exists(object.inner), - error::not_found(EOBJECT_DOES_NOT_EXIST), + error::not_found(EOBJECT_DOES_NOT_EXIST) ); borrow_global(object.inner).allow_ungated_transfer } @@ -554,7 +558,7 @@ module initia_std::object { public fun owner(object: Object): address acquires ObjectCore { assert!( exists(object.inner), - error::not_found(EOBJECT_DOES_NOT_EXIST), + error::not_found(EOBJECT_DOES_NOT_EXIST) ); borrow_global(object.inner).owner } @@ -575,7 +579,7 @@ module initia_std::object { assert!( exists(current_address), - error::not_found(EOBJECT_DOES_NOT_EXIST), + error::not_found(EOBJECT_DOES_NOT_EXIST) ); let object = borrow_global(current_address); @@ -586,7 +590,7 @@ module initia_std::object { count = count + 1; assert!( count < MAXIMUM_OBJECT_NESTING, - error::out_of_range(EMAXIMUM_NESTING), + error::out_of_range(EMAXIMUM_NESTING) ); if (!exists(current_address)) { return false @@ -609,12 +613,12 @@ module initia_std::object { #[event] #[test_only] struct HeroEquipEvent has drop, store { - weapon_id: Option>, + weapon_id: Option> } #[test_only] struct Hero has key { - weapon: Option>, + weapon: Option> } #[test_only] @@ -624,7 +628,7 @@ module initia_std::object { public fun create_hero(creator: &signer): (ConstructorRef, Object) acquires Tombstone { let hero_constructor_ref = create_deletable_named_object(creator, b"hero"); let hero_signer = generate_signer(&hero_constructor_ref); - move_to(&hero_signer, Hero { weapon: option::none(), }); + move_to(&hero_signer, Hero { weapon: option::none() }); let hero = object_from_constructor_ref(&hero_constructor_ref); (hero_constructor_ref, hero) @@ -647,9 +651,7 @@ module initia_std::object { #[test_only] public fun hero_equip( - owner: &signer, - hero: Object, - weapon: Object, + owner: &signer, hero: Object, weapon: Object ) acquires Hero, ObjectCore { transfer_to_object(owner, weapon, hero); let hero_obj = borrow_global_mut(object_address(&hero)); @@ -659,14 +661,12 @@ module initia_std::object { #[test_only] public fun hero_unequip( - owner: &signer, - hero: Object, - weapon: Object, + owner: &signer, hero: Object, weapon: Object ) acquires Hero, ObjectCore { transfer( owner, weapon, - signer::address_of(owner), + signer::address_of(owner) ); let hero = borrow_global_mut(object_address(&hero)); option::extract(&mut hero.weapon); @@ -734,7 +734,9 @@ module initia_std::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 0x50009, location = Self)] - fun test_cannot_use_transfer_ref_with_old_version(creator: &signer) acquires Tombstone, ObjectCore, Hero { + fun test_cannot_use_transfer_ref_with_old_version( + creator: &signer + ) acquires Tombstone, ObjectCore, Hero { let (hero_constructor, _) = create_hero(creator); let delete_ref = generate_delete_ref(&hero_constructor); let transfer_ref = generate_transfer_ref(&hero_constructor); @@ -747,7 +749,9 @@ module initia_std::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 0x50009, location = Self)] - fun test_cannot_use_transfer_ref_with_old_version2(creator: &signer) acquires Tombstone, ObjectCore, Hero { + fun test_cannot_use_transfer_ref_with_old_version2( + creator: &signer + ) acquires Tombstone, ObjectCore, Hero { let (hero_constructor, _) = create_hero(creator); let delete_ref = generate_delete_ref(&hero_constructor); let transfer_ref = generate_transfer_ref(&hero_constructor); @@ -760,7 +764,9 @@ module initia_std::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 0x50009, location = Self)] - fun test_cannot_use_transfer_ref_with_old_version3(creator: &signer) acquires Tombstone, ObjectCore, Hero { + fun test_cannot_use_transfer_ref_with_old_version3( + creator: &signer + ) acquires Tombstone, ObjectCore, Hero { let (hero_constructor, _) = create_hero(creator); let delete_ref = generate_delete_ref(&hero_constructor); let transfer_ref = generate_transfer_ref(&hero_constructor); @@ -773,7 +779,9 @@ module initia_std::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 0x50009, location = Self)] - fun test_cannot_use_delete_ref_with_old_version(creator: &signer) acquires Tombstone, ObjectCore, Hero { + fun test_cannot_use_delete_ref_with_old_version( + creator: &signer + ) acquires Tombstone, ObjectCore, Hero { let (hero_constructor, _) = create_hero(creator); let delete_ref = generate_delete_ref(&hero_constructor); let delete_ref2 = generate_delete_ref(&hero_constructor); @@ -786,7 +794,9 @@ module initia_std::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 0x50009, location = Self)] - fun test_cannot_use_extend_ref_with_old_version(creator: &signer) acquires Tombstone, ObjectCore, Hero { + fun test_cannot_use_extend_ref_with_old_version( + creator: &signer + ) acquires Tombstone, ObjectCore, Hero { let (hero_constructor, _) = create_hero(creator); let delete_ref = generate_delete_ref(&hero_constructor); let extend_ref = generate_extend_ref(&hero_constructor); diff --git a/initia_stdlib/sources/object_code_deployment.move b/initia_stdlib/sources/object_code_deployment.move new file mode 100644 index 0000000..bf11f59 --- /dev/null +++ b/initia_stdlib/sources/object_code_deployment.move @@ -0,0 +1,146 @@ +/// This module allows users to deploy, upgrade and freeze modules deployed to objects on-chain. +/// This enables users to deploy modules to an object with a unique address each time they are published. +/// This modules provides an alternative method to publish code on-chain, where code is deployed to objects rather than accounts. +/// This is encouraged as it abstracts the necessary resources needed for deploying modules, +/// along with the required authorization to upgrade and freeze modules. +/// +/// The functionalities of this module are as follows. +/// +/// Publishing modules flow: +/// 1. Create a new object with the address derived from the publisher address and the object seed. +/// 2. Publish the module passed in the function via `metadata_serialized` and `code` to the newly created object. +/// 3. Emits 'Publish' event with the address of the newly created object. +/// 4. Create a `ManagingRefs` which stores the extend ref of the newly created object. +/// Note: This is needed to upgrade the code as the signer must be generated to upgrade the existing code in an object. +/// +/// Upgrading modules flow: +/// 1. Assert the `code_object` passed in the function is owned by the `publisher`. +/// 2. Assert the `code_object` passed in the function exists in global storage. +/// 2. Retrieve the `ExtendRef` from the `code_object` and generate the signer from this. +/// 3. Upgrade the module with the `metadata_serialized` and `code` passed in the function. +/// 4. Emits 'Upgrade' event with the address of the object with the upgraded code. +/// Note: If the modules were deployed as immutable when calling `publish`, the upgrade will fail. +/// +/// Freezing modules flow: +/// 1. Assert the `code_object` passed in the function exists in global storage. +/// 2. Assert the `code_object` passed in the function is owned by the `publisher`. +/// 3. Mark all the modules in the `code_object` as immutable. +/// 4. Emits 'Freeze' event with the address of the object with the frozen code. +/// Note: There is no unfreeze function as this gives no benefit if the user can freeze/unfreeze modules at will. +/// Once modules are marked as immutable, they cannot be made mutable again. +module initia_std::object_code_deployment { + use std::bcs; + use std::error; + use std::signer; + use std::vector; + use initia_std::account; + use initia_std::code::{Self, MetadataStore}; + use initia_std::event; + use initia_std::object; + use initia_std::object::{ExtendRef, Object}; + use initia_std::string::String; + + /// Object code deployment feature not supported. + const EOBJECT_CODE_DEPLOYMENT_NOT_SUPPORTED: u64 = 1; + /// Not the owner of the `code_object` + const ENOT_CODE_OBJECT_OWNER: u64 = 2; + /// `code_object` does not exist. + const ECODE_OBJECT_DOES_NOT_EXIST: u64 = 3; + + const OBJECT_CODE_DEPLOYMENT_DOMAIN_SEPARATOR: vector = b"initia_std::object_code_deployment"; + + /// Internal struct, attached to the object, that holds Refs we need to manage the code deployment (i.e. upgrades). + struct ManagingRefs has key { + /// We need to keep the extend ref to be able to generate the signer to upgrade existing code. + extend_ref: ExtendRef + } + + #[event] + /// Event emitted when code is published to an object. + struct Publish has drop, store { + object_address: address + } + + #[event] + /// Event emitted when code in an existing object is upgraded. + struct Upgrade has drop, store { + object_address: address + } + + #[event] + /// Event emitted when code in an existing object is made immutable. + struct Freeze has drop, store { + object_address: address + } + + /// Creates a new object with a unique address derived from the publisher address and the object seed. + /// Publishes the code passed in the function to the newly created object. + /// The caller must provide package metadata describing the package via `metadata_serialized` and + /// the code to be published via `code`. This contains a vector of modules to be deployed on-chain. + public entry fun publish( + publisher: &signer, module_ids: vector, code: vector> + ) { + let publisher_address = signer::address_of(publisher); + let object_seed = object_seed(publisher_address); + let constructor_ref = &object::create_named_object(publisher, object_seed); + let code_signer = &object::generate_signer(constructor_ref); + code::publish(code_signer, module_ids, code, 1); + + event::emit(Publish { object_address: signer::address_of(code_signer) }); + + move_to( + code_signer, + ManagingRefs { extend_ref: object::generate_extend_ref(constructor_ref) } + ); + } + + inline fun object_seed(publisher: address): vector { + let sequence_number = account::get_sequence_number(publisher) + 1; + let seeds = vector[]; + vector::append( + &mut seeds, bcs::to_bytes(&OBJECT_CODE_DEPLOYMENT_DOMAIN_SEPARATOR) + ); + vector::append(&mut seeds, bcs::to_bytes(&sequence_number)); + seeds + } + + /// Upgrades the existing modules at the `code_object` address with the new modules passed in `code`, + /// along with the metadata `metadata_serialized`. + /// Note: If the modules were deployed as immutable when calling `publish`, the upgrade will fail. + /// Requires the publisher to be the owner of the `code_object`. + public entry fun upgrade( + publisher: &signer, + module_ids: vector, + code: vector>, + code_object: Object + ) acquires ManagingRefs { + let publisher_address = signer::address_of(publisher); + assert!( + object::is_owner(code_object, publisher_address), + error::permission_denied(ENOT_CODE_OBJECT_OWNER) + ); + + let code_object_address = object::object_address(&code_object); + assert!( + exists(code_object_address), + error::not_found(ECODE_OBJECT_DOES_NOT_EXIST) + ); + + let extend_ref = &borrow_global(code_object_address).extend_ref; + let code_signer = &object::generate_signer_for_extending(extend_ref); + code::publish(code_signer, module_ids, code, 1); + + event::emit(Upgrade { object_address: signer::address_of(code_signer) }); + } + + /// Make an existing upgradable package immutable. Once this is called, the package cannot be made upgradable again. + /// Each `code_object` should only have one package, as one package is deployed per object in this module. + /// Requires the `publisher` to be the owner of the `code_object`. + public entry fun freeze_code_object( + publisher: &signer, code_object: Object + ) { + code::freeze_code_object(publisher, code_object); + + event::emit(Freeze { object_address: object::object_address(&code_object) }); + } +} diff --git a/initia_stdlib/sources/oracle.move b/initia_stdlib/sources/oracle.move index 458b519..7b66413 100644 --- a/initia_stdlib/sources/oracle.move +++ b/initia_stdlib/sources/oracle.move @@ -19,13 +19,16 @@ module initia_std::oracle { *string::bytes(pair_id), price, updated_at, - decimals, + decimals ) } #[test_only] native fun set_price_internal( - pair_id: vector, price: u256, updated_at: u64, decimals: u64 + pair_id: vector, + price: u256, + updated_at: u64, + decimals: u64 ); #[test] @@ -46,13 +49,13 @@ module initia_std::oracle { &btc_usd_pair_id, btc_price, btc_updated_at, - btc_decimals, + btc_decimals ); set_price( ð_usd_pair_id, eth_price, eth_updated_at, - eth_decimals, + eth_decimals ); let (price, updated_at, decimals) = get_price(btc_usd_pair_id); diff --git a/initia_stdlib/sources/query.move b/initia_stdlib/sources/query.move index d94beae..fb92c7f 100644 --- a/initia_stdlib/sources/query.move +++ b/initia_stdlib/sources/query.move @@ -36,7 +36,7 @@ module initia_std::query { */ struct ProposalRequest has copy, drop { - proposal_id: u64, + proposal_id: u64 } struct ProposalResponse has copy, drop { @@ -45,7 +45,7 @@ module initia_std::query { summary: String, status: String, submit_time: String, - emergency: bool, + emergency: bool } #[view] @@ -53,7 +53,7 @@ module initia_std::query { let response = query_stargate( b"/initia.gov.v1.Query/Proposal", - json::marshal(&ProposalRequest { proposal_id, }), + json::marshal(&ProposalRequest { proposal_id }) ); let res = json::unmarshal(response); (res.id, res.title, res.summary, string::utf8(response)) @@ -64,7 +64,7 @@ module initia_std::query { let response = query_stargate( b"/initia.gov.v1.Query/Proposal", - json::marshal(&ProposalRequest { proposal_id, }), + json::marshal(&ProposalRequest { proposal_id }) ); let res = json::unmarshal(response); (res.id, res.status, res.submit_time, res.emergency) @@ -79,6 +79,11 @@ module initia_std::query { path_or_name: vector, data: vector, response: vector ); + #[test_only] + native public fun unset_query_response( + path_or_name: vector, data: vector + ); + #[test] fun test_query_custom() { set_query_response(b"path", b"data123", b"output"); @@ -94,4 +99,14 @@ module initia_std::query { let res = query_stargate(b"path", b"data123"); assert!(res == b"output", 0); } + + #[test] + #[expected_failure(abort_code = 0x1006E, location = Self)] + fun test_query_unsset() { + set_query_response(b"path", b"data123", b"output"); + unset_query_response(b"path", b"data123"); + + let res = query_custom(b"path", b"data123"); + assert!(res == b"", 0); + } } diff --git a/initia_stdlib/sources/simple_map.move b/initia_stdlib/sources/simple_map.move index afe08c4..6cf6275 100644 --- a/initia_stdlib/sources/simple_map.move +++ b/initia_stdlib/sources/simple_map.move @@ -1,151 +1,216 @@ -/// This module provides a solution for sorted maps, that is it has the properties that +/// This module provides a solution for unsorted maps, that is it has the properties that /// 1) Keys point to Values /// 2) Each Key must be unique -/// 3) A Key can be found within O(Log N) time -/// 4) The data is stored as a sorted by Key +/// 3) A Key can be found within O(N) time +/// 4) The keys are unsorted. /// 5) Adds and removals take O(N) time module initia_std::simple_map { use std::error; use std::option; use std::vector; - use initia_std::comparator; - const EKEY_ALREADY_EXISTS: u64 = 0; - const EKEY_NOT_FOUND: u64 = 1; + /// Map key already exists + const EKEY_ALREADY_EXISTS: u64 = 1; + /// Map key is not found + const EKEY_NOT_FOUND: u64 = 2; struct SimpleMap has copy, drop, store { - data: vector>, + data: vector> } struct Element has copy, drop, store { key: Key, - value: Value, + value: Value } - public fun length(map: &SimpleMap): u64 { - vector::length(&map.data) + public fun length(self: &SimpleMap): u64 { + vector::length(&self.data) } + /// Create an empty SimpleMap. + public fun new(): SimpleMap { + SimpleMap { data: vector::empty() } + } + + /// Create a SimpleMap from a vector of keys and values. The keys must be unique. + public fun new_from( + keys: vector, values: vector + ): SimpleMap { + let map = new(); + add_all(&mut map, keys, values); + map + } + + #[deprecated] + /// Create an empty SimpleMap. + /// This function is deprecated, use `new` instead. public fun create(): SimpleMap { - SimpleMap { data: vector::empty(), } + new() } public fun borrow( - map: &SimpleMap, key: &Key, + self: &SimpleMap, key: &Key ): &Value { - let (maybe_idx, _) = find(map, key); - assert!( - option::is_some(&maybe_idx), - error::invalid_argument(EKEY_NOT_FOUND), - ); + let maybe_idx = find(self, key); + assert!(option::is_some(&maybe_idx), error::invalid_argument(EKEY_NOT_FOUND)); let idx = option::extract(&mut maybe_idx); - &vector::borrow(&map.data, idx).value + &vector::borrow(&self.data, idx).value } public fun borrow_mut( - map: &mut SimpleMap, key: &Key, + self: &mut SimpleMap, key: &Key ): &mut Value { - let (maybe_idx, _) = find(map, key); - assert!( - option::is_some(&maybe_idx), - error::invalid_argument(EKEY_NOT_FOUND), - ); + let maybe_idx = find(self, key); + assert!(option::is_some(&maybe_idx), error::invalid_argument(EKEY_NOT_FOUND)); let idx = option::extract(&mut maybe_idx); - &mut vector::borrow_mut(&mut map.data, idx).value + &mut vector::borrow_mut(&mut self.data, idx).value } public fun contains_key( - map: &SimpleMap, key: &Key, + self: &SimpleMap, key: &Key ): bool { - let (maybe_idx, _) = find(map, key); + let maybe_idx = find(self, key); option::is_some(&maybe_idx) } public fun destroy_empty( - map: SimpleMap + self: SimpleMap ) { - let SimpleMap { data } = map; + let SimpleMap { data } = self; vector::destroy_empty(data); } + /// Add a key/value pair to the map. The key must not already exist. public fun add( - map: &mut SimpleMap, + self: &mut SimpleMap, key: Key, - value: Value, + value: Value ) { - let (maybe_idx, maybe_placement) = find(map, &key); - assert!( - option::is_none(&maybe_idx), - error::invalid_argument(EKEY_ALREADY_EXISTS), - ); + let maybe_idx = find(self, &key); + assert!(option::is_none(&maybe_idx), error::invalid_argument(EKEY_ALREADY_EXISTS)); - // Append to the end and then swap elements until the list is ordered again - vector::push_back(&mut map.data, Element { key, value }); - - let placement = option::extract(&mut maybe_placement); - let end = vector::length(&map.data) - 1; - while (placement < end) { - vector::swap(&mut map.data, placement, end); - placement = placement + 1; - }; + vector::push_back(&mut self.data, Element { key, value }); } - public fun remove( - map: &mut SimpleMap, key: &Key, - ): (Key, Value) { - let (maybe_idx, _) = find(map, key); - assert!( - option::is_some(&maybe_idx), - error::invalid_argument(EKEY_NOT_FOUND), + /// Add multiple key/value pairs to the map. The keys must not already exist. + public fun add_all( + self: &mut SimpleMap, + keys: vector, + values: vector + ) { + vector::zip( + keys, + values, + |key, value| { + add(self, key, value); + } ); + } - let placement = option::extract(&mut maybe_idx); - let end = vector::length(&map.data) - 1; - - while (placement < end) { - vector::swap( - &mut map.data, - placement, - placement + 1, - ); - placement = placement + 1; + /// Insert key/value pair or update an existing key to a new value + public fun upsert( + self: &mut SimpleMap, + key: Key, + value: Value + ): (std::option::Option, std::option::Option) { + let data = &mut self.data; + let len = vector::length(data); + let i = 0; + while (i < len) { + let element = vector::borrow(data, i); + if (&element.key == &key) { + vector::push_back(data, Element { key, value }); + vector::swap(data, i, len); + let Element { key, value } = vector::pop_back(data); + return (std::option::some(key), std::option::some(value)) + }; + i = i + 1; }; + vector::push_back(&mut self.data, Element { key, value }); + (std::option::none(), std::option::none()) + } - let Element { key, value } = vector::pop_back(&mut map.data); - (key, value) + /// Return all keys in the map. This requires keys to be copyable. + public fun keys(self: &SimpleMap): vector { + vector::map_ref( + &self.data, + |e| { + let e: &Element = e; + e.key + } + ) } - fun find( - map: &SimpleMap, key: &Key, - ): (option::Option, option::Option) { - let length = vector::length(&map.data); + /// Return all values in the map. This requires values to be copyable. + public fun values(self: &SimpleMap): vector { + vector::map_ref( + &self.data, + |e| { + let e: &Element = e; + e.value + } + ) + } - if (length == 0) { - return (option::none(), option::some(0)) - }; + /// Transform the map into two vectors with the keys and values respectively + /// Primarily used to destroy a map + public fun to_vec_pair( + self: SimpleMap + ): (vector, vector) { + let keys: vector = vector::empty(); + let values: vector = vector::empty(); + let SimpleMap { data } = self; + vector::for_each( + data, + |e| { + let Element { key, value } = e; + vector::push_back(&mut keys, key); + vector::push_back(&mut values, value); + } + ); + (keys, values) + } - let left = 0; - let right = length; + /// For maps that cannot be dropped this is a utility to destroy them + /// using lambdas to destroy the individual keys and values. + public inline fun destroy( + self: SimpleMap, + dk: |Key|, + dv: |Value| + ) { + let (keys, values) = to_vec_pair(self); + vector::destroy(keys, |_k| dk(_k)); + vector::destroy(values, |_v| dv(_v)); + } - while (left != right) { - let mid = (left + right) / 2; - let potential_key = &vector::borrow(&map.data, mid).key; - if (comparator::is_smaller_than(&comparator::compare(potential_key, key))) { - left = mid + 1; - } else { - right = mid; + /// Remove a key/value pair from the map. The key must exist. + public fun remove( + self: &mut SimpleMap, key: &Key + ): (Key, Value) { + let maybe_idx = find(self, key); + assert!(option::is_some(&maybe_idx), error::invalid_argument(EKEY_NOT_FOUND)); + let placement = option::extract(&mut maybe_idx); + let Element { key, value } = vector::swap_remove(&mut self.data, placement); + (key, value) + } + + fun find( + self: &SimpleMap, key: &Key + ): option::Option { + let leng = vector::length(&self.data); + let i = 0; + while (i < leng) { + let element = vector::borrow(&self.data, i); + if (&element.key == key) { + return option::some(i) }; + i = i + 1; }; - - if (left != length && key == &vector::borrow(&map.data, left).key) { - (option::some(left), option::none()) - } else { - (option::none(), option::some(left)) - } + option::none() } #[test] - public fun add_remove_many() { + public fun test_add_remove_many() { let map = create(); assert!(length(&map) == 0, 0); @@ -178,41 +243,45 @@ module initia_std::simple_map { } #[test] - public fun test_several() { + public fun test_add_all() { let map = create(); - add(&mut map, 6, 6); - add(&mut map, 1, 1); - add(&mut map, 5, 5); - add(&mut map, 2, 2); - add(&mut map, 3, 3); - add(&mut map, 0, 0); - add(&mut map, 7, 7); - add(&mut map, 4, 4); - - let idx = 0; - while (idx < vector::length(&map.data)) { - assert!( - idx == vector::borrow(&map.data, idx).key, - idx, - ); - idx = idx + 1; - }; - remove(&mut map, &0); + assert!(length(&map) == 0, 0); + add_all(&mut map, vector[1, 2, 3], vector[10, 20, 30]); + assert!(length(&map) == 3, 1); + assert!(borrow(&map, &1) == &10, 2); + assert!(borrow(&map, &2) == &20, 3); + assert!(borrow(&map, &3) == &30, 4); + remove(&mut map, &1); remove(&mut map, &2); remove(&mut map, &3); - remove(&mut map, &4); - remove(&mut map, &5); - remove(&mut map, &6); - remove(&mut map, &7); - destroy_empty(map); } + #[test] + public fun test_keys() { + let map = create(); + assert!(keys(&map) == vector[], 0); + add(&mut map, 2, 1); + add(&mut map, 3, 1); + + assert!(keys(&map) == vector[2, 3], 0); + } + + #[test] + public fun test_values() { + let map = create(); + assert!(values(&map) == vector[], 0); + add(&mut map, 2, 1); + add(&mut map, 3, 2); + + assert!(values(&map) == vector[1, 2], 0); + } + #[test] #[expected_failure] - public fun add_twice() { + public fun test_add_twice() { let map = create(); add(&mut map, 3, 1); add(&mut map, 3, 1); @@ -223,7 +292,7 @@ module initia_std::simple_map { #[test] #[expected_failure] - public fun remove_twice() { + public fun test_remove_twice() { let map = create(); add(&mut map, 3, 1); remove(&mut map, &3); @@ -231,4 +300,28 @@ module initia_std::simple_map { destroy_empty(map); } + + #[test] + public fun test_upsert_test() { + let map = create(); + // test adding 3 elements using upsert + upsert(&mut map, 1, 1); + upsert(&mut map, 2, 2); + upsert(&mut map, 3, 3); + + assert!(length(&map) == 3, 0); + assert!(contains_key(&map, &1), 1); + assert!(contains_key(&map, &2), 2); + assert!(contains_key(&map, &3), 3); + assert!(borrow(&map, &1) == &1, 4); + assert!(borrow(&map, &2) == &2, 5); + assert!(borrow(&map, &3) == &3, 6); + + // change mapping 1->1 to 1->4 + upsert(&mut map, 1, 4); + + assert!(length(&map) == 3, 7); + assert!(contains_key(&map, &1), 8); + assert!(borrow(&map, &1) == &4, 9); + } } diff --git a/initia_stdlib/sources/stableswap.move b/initia_stdlib/sources/stableswap.move index c9098bd..b0d07a0 100644 --- a/initia_stdlib/sources/stableswap.move +++ b/initia_stdlib/sources/stableswap.move @@ -9,7 +9,7 @@ module initia_std::stableswap { use initia_std::block; use initia_std::primary_fungible_store; use initia_std::object::{Self, ExtendRef, Object}; - use initia_std::decimal128::{Self, Decimal128}; + use initia_std::bigdecimal::{Self, BigDecimal}; use initia_std::string::{Self, String}; use initia_std::coin; use initia_std::table::{Self, Table}; @@ -18,7 +18,7 @@ module initia_std::stableswap { struct ModuleStore has key { pools: Table, - pool_count: u64, + pool_count: u64 } struct Pool has key { @@ -27,7 +27,7 @@ module initia_std::stableswap { /// ANN ann: Ann, /// swap fee - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal, /// Coin metadata coin_metadata: vector>, /// Liqudiity token's burn capability @@ -35,7 +35,7 @@ module initia_std::stableswap { /// Liqudiity token's freeze capability freeze_cap: coin::FreezeCapability, /// Liqudiity token's mint capability - mint_cap: coin::MintCapability, + mint_cap: coin::MintCapability } #[event] @@ -43,7 +43,7 @@ module initia_std::stableswap { coins: vector
, liquidity_token: address, ann: u64, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal } #[event] @@ -52,7 +52,7 @@ module initia_std::stableswap { coin_amounts: vector, fee_amounts: vector, liquidity_token: address, - liquidity: u64, + liquidity: u64 } #[event] @@ -61,7 +61,7 @@ module initia_std::stableswap { coin_amounts: vector, fee_amounts: vector, liquidity_token: address, - liquidity: u64, + liquidity: u64 } #[event] @@ -71,26 +71,26 @@ module initia_std::stableswap { liquidity_token: address, offer_amount: u64, return_amount: u64, - fee_amount: u64, + fee_amount: u64 } #[event] struct UpdateSwapFeeEvent has drop, store { liquidity_token: address, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal } #[event] struct UpdateAnnEvent has drop, store { liquidity_token: address, - ann: Ann, + ann: Ann } struct Ann has copy, drop, store { ann_before: u64, ann_after: u64, timestamp_before: u64, - timestamp_after: u64, + timestamp_after: u64 } struct PoolResponse has copy, drop, store { @@ -98,7 +98,7 @@ module initia_std::stableswap { coin_denoms: vector, coin_balances: vector, current_ann: u64, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal } // Errors @@ -154,15 +154,13 @@ module initia_std::stableswap { // Constants const MAX_LIMIT: u8 = 30; - const MAX_FEE_RATE: u128 = 10_000_000_000_000_000; // 1% - #[view] /// Return swap simulation result public fun get_swap_simulation( pool_obj: Object, offer_metadata: Object, return_metadata: Object, - offer_amount: u64, + offer_amount: u64 ): u64 acquires Pool { let (return_amount, fee_amount) = swap_simulation( @@ -170,7 +168,7 @@ module initia_std::stableswap { offer_metadata, return_metadata, offer_amount, - true, + true ); return_amount - fee_amount @@ -182,7 +180,7 @@ module initia_std::stableswap { pool_obj: Object, offer_metadata: Object, return_metadata: Object, - return_amount: u64, + return_amount: u64 ): u64 acquires Pool { let (offer_amount, _) = swap_simulation( @@ -190,7 +188,7 @@ module initia_std::stableswap { offer_metadata, return_metadata, return_amount, - false, + false ); offer_amount @@ -201,7 +199,7 @@ module initia_std::stableswap { pool_obj: Object, offer_denom: String, return_denom: String, - offer_amount: u64, + offer_amount: u64 ): u64 acquires Pool { let offer_metadata = coin::denom_to_metadata(offer_denom); let return_metadata = coin::denom_to_metadata(return_denom); @@ -209,13 +207,13 @@ module initia_std::stableswap { pool_obj, offer_metadata, return_metadata, - offer_amount, + offer_amount ) } #[view] public fun get_provide_simulation( - pool_obj: Object, coin_amounts: vector, + pool_obj: Object, coin_amounts: vector ): u64 acquires Pool { let (liquidity_amount, _) = provide_simulation(pool_obj, coin_amounts); liquidity_amount @@ -223,13 +221,13 @@ module initia_std::stableswap { #[view] public fun get_imbalance_withdraw_simulation( - pool_obj: Object, coin_amounts: vector, + pool_obj: Object, coin_amounts: vector ): u64 acquires Pool { let (liquidity_amount, _) = imbalance_withdraw_simulation( pool_obj, coin_amounts, - option::none(), + option::none() ); liquidity_amount } @@ -238,7 +236,7 @@ module initia_std::stableswap { public fun get_single_asset_withdraw_simulation( pool_obj: Object, return_coin_metadata: Object, - liquidity_amount: u64, + liquidity_amount: u64 ): u64 acquires Pool { let pool = borrow_pool(pool_obj); @@ -252,7 +250,7 @@ module initia_std::stableswap { single_asset_withdraw_simulation( pool_obj, liquidity_amount, - return_index, + return_index ); liquidity_amount } @@ -262,7 +260,7 @@ module initia_std::stableswap { let (coin_metadata, coin_balances, current_ann, swap_fee_rate) = pool_info(pool); let coin_denoms = vector::map( coin_metadata, - |metadata| coin::metadata_to_denom(metadata), + |metadata| coin::metadata_to_denom(metadata) ); PoolResponse { @@ -277,7 +275,9 @@ module initia_std::stableswap { #[view] // get all kinds of pool // return vector of PoolResponse - public fun get_all_pools(start_after: Option
, limit: u8,): vector acquires ModuleStore, Pool { + public fun get_all_pools( + start_after: Option
, limit: u8 + ): vector acquires ModuleStore, Pool { if (limit > MAX_LIMIT) { limit = MAX_LIMIT; }; @@ -289,11 +289,11 @@ module initia_std::stableswap { &module_store.pools, option::none(), start_after, - 2, + 2 ); while (vector::length(&res) < (limit as u64) - && table::prepare(pools_iter)) { + && table::prepare(pools_iter)) { let (key, _) = table::next(pools_iter); let pool_response = get_pool(object::address_to_object(key)); vector::push_back(&mut res, pool_response) @@ -306,8 +306,8 @@ module initia_std::stableswap { public fun spot_price( pool_obj: Object, base_metadata: Object, - quote_metadata: Object, - ): Decimal128 acquires Pool { + quote_metadata: Object + ): BigDecimal acquires Pool { let pool = borrow_pool(pool_obj); let ann = get_current_ann(&pool.ann); let pool_addr = object::object_address(&pool_obj); @@ -334,7 +334,7 @@ module initia_std::stableswap { quote_metadata, base_metadata, swap_amount, - true, + true ); let (quote_return_amount, _) = swap_simulation_with_given_amounts( @@ -343,32 +343,31 @@ module initia_std::stableswap { base_metadata, quote_metadata, swap_amount, - true, + true ); - decimal128::from_ratio_u64( + bigdecimal::from_ratio_u64( quote_return_amount + swap_amount, - base_return_amount + swap_amount, + base_return_amount + swap_amount ) } fun init_module(chain: &signer) { move_to( chain, - ModuleStore { pools: table::new(), pool_count: 0 }, + ModuleStore { pools: table::new(), pool_count: 0 } ) } - public fun unpack_pool_response(pool_response: &PoolResponse) - : ( - vector>, vector, vector, u64, Decimal128 - ) { + public fun unpack_pool_response( + pool_response: &PoolResponse + ): (vector>, vector, vector, u64, BigDecimal) { ( pool_response.coin_metadata, pool_response.coin_denoms, pool_response.coin_balances, pool_response.current_ann, - pool_response.swap_fee_rate, + pool_response.swap_fee_rate ) } @@ -376,10 +375,10 @@ module initia_std::stableswap { creator: &signer, name: String, symbol: String, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal, coin_metadata: vector>, coin_amounts: vector, - ann: u64, + ann: u64 ) acquires Pool, ModuleStore { let coins: vector = vector[]; let i = 0; @@ -389,7 +388,7 @@ module initia_std::stableswap { let amount = *vector::borrow(&coin_amounts, i); vector::push_back( &mut coins, - primary_fungible_store::withdraw(creator, metadata, amount), + primary_fungible_store::withdraw(creator, metadata, amount) ); i = i + 1; }; @@ -400,13 +399,13 @@ module initia_std::stableswap { symbol, swap_fee_rate, coins, - ann, + ann ); primary_fungible_store::deposit(signer::address_of(creator), liquidity_token); } public entry fun update_swap_fee_rate( - account: &signer, pool_obj: Object, new_swap_fee_rate: Decimal128 + account: &signer, pool_obj: Object, new_swap_fee_rate: BigDecimal ) acquires Pool { check_chain_permission(account); let pool = borrow_pool_mut(pool_obj); @@ -415,8 +414,8 @@ module initia_std::stableswap { event::emit( UpdateSwapFeeEvent { liquidity_token: object::object_address(&pool_obj), - swap_fee_rate: new_swap_fee_rate, - }, + swap_fee_rate: new_swap_fee_rate + } ) } @@ -437,8 +436,8 @@ module initia_std::stableswap { event::emit( UpdateAnnEvent { liquidity_token: object::object_address(&pool_obj), - ann: pool.ann, - }, + ann: pool.ann + } ) } @@ -446,7 +445,7 @@ module initia_std::stableswap { account: &signer, pool_obj: Object, coin_amounts: vector, - min_liquidity: Option, + min_liquidity: Option ) acquires Pool { let coins: vector = vector[]; let pool = borrow_pool(pool_obj); @@ -458,7 +457,7 @@ module initia_std::stableswap { let amount = *vector::borrow(&coin_amounts, i); vector::push_back( &mut coins, - primary_fungible_store::withdraw(account, metadata, amount), + primary_fungible_store::withdraw(account, metadata, amount) ); i = i + 1; }; @@ -492,13 +491,13 @@ module initia_std::stableswap { account: &signer, pool_obj: Object, coin_amounts: vector, - max_liquidity: Option, + max_liquidity: Option ) acquires Pool { let (liquidity_amount, fee_amounts) = imbalance_withdraw_simulation( pool_obj, coin_amounts, - max_liquidity, + max_liquidity ); let liquidity_token = primary_fungible_store::withdraw(account, pool_obj, liquidity_amount); @@ -524,8 +523,8 @@ module initia_std::stableswap { coin_amounts, fee_amounts, liquidity_token: object::object_address(&pool_obj), - liquidity: liquidity_amount, - }, + liquidity: liquidity_amount + } ); } @@ -534,7 +533,7 @@ module initia_std::stableswap { pool_obj: Object, return_coin_metadata: Object, liquidity_amount: u64, - min_return_amount: Option, + min_return_amount: Option ) acquires Pool { let liquidity_token = primary_fungible_store::withdraw(account, pool_obj, liquidity_amount); @@ -542,7 +541,7 @@ module initia_std::stableswap { single_asset_withdraw_liquidity( liquidity_token, return_coin_metadata, - min_return_amount, + min_return_amount ); primary_fungible_store::deposit(signer::address_of(account), return_coin); } @@ -553,35 +552,39 @@ module initia_std::stableswap { offer_coin_metadata: Object, return_coin_metadata: Object, offer_amount: u64, - min_return_amount: Option, + min_return_amount: Option ) acquires Pool { let offer_coin = primary_fungible_store::withdraw( account, offer_coin_metadata, - offer_amount, + offer_amount ); let return_coin = swap( pool_obj, offer_coin, return_coin_metadata, - min_return_amount, + min_return_amount ); primary_fungible_store::deposit(signer::address_of(account), return_coin); } + fun max_fee_rate(): BigDecimal { + bigdecimal::from_ratio_u64(1, 100) + } + public fun create_pool( creator: &signer, name: String, symbol: String, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal, coins: vector, - ann: u64, + ann: u64 ): FungibleAsset acquires Pool, ModuleStore { assert!( vector::length(&coins) >= 2, - error::invalid_argument(EN_COINS), + error::invalid_argument(EN_COINS) ); let (_, timestamp) = block::get_block_info(); let (mint_cap, burn_cap, freeze_cap, extend_ref) = @@ -592,7 +595,7 @@ module initia_std::stableswap { symbol, 6, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); let coin_metadata: vector> = vector[]; @@ -607,7 +610,7 @@ module initia_std::stableswap { fungible_asset::metadata_from_asset(vector::borrow(&coins, j)); assert!( coin_metadata_i != coin_metadata_j, - error::invalid_argument(ESAME_COIN_TYPE), + error::invalid_argument(ESAME_COIN_TYPE) ); j = j + 1; }; @@ -616,8 +619,8 @@ module initia_std::stableswap { }; assert!( - decimal128::val(&swap_fee_rate) < MAX_FEE_RATE, - error::invalid_argument(EOUT_OF_SWAP_FEE_RATE_RANGE), + bigdecimal::le(swap_fee_rate, max_fee_rate()), + error::invalid_argument(EOUT_OF_SWAP_FEE_RATE_RANGE) ); let pool_signer = &object::generate_signer_for_extending(&extend_ref); @@ -633,21 +636,21 @@ module initia_std::stableswap { ann_before: ann, ann_after: ann, timestamp_before: timestamp, - timestamp_after: timestamp, + timestamp_after: timestamp }, swap_fee_rate, coin_metadata, burn_cap, freeze_cap, - mint_cap, - }, + mint_cap + } ); let liquidity_token = provide_liquidity( object::address_to_object(pool_address), coins, - option::none(), + option::none() ); // update module store @@ -657,7 +660,7 @@ module initia_std::stableswap { table::add( &mut module_store.pools, pool_address, - true, + true ); // emit create pool event @@ -666,8 +669,8 @@ module initia_std::stableswap { coins: get_coin_addresses(coin_metadata), liquidity_token: pool_address, ann, - swap_fee_rate, - }, + swap_fee_rate + } ); return liquidity_token @@ -685,7 +688,7 @@ module initia_std::stableswap { assert!( option::is_none(&min_liquidity) || *option::borrow(&min_liquidity) <= liquidity_amount, - error::invalid_state(EMIN_LIQUIDITY), + error::invalid_state(EMIN_LIQUIDITY) ); let pool_addr = object::object_address(&pool_obj); @@ -706,8 +709,8 @@ module initia_std::stableswap { coin_amounts: amounts, fee_amounts, liquidity_token: pool_addr, - liquidity: liquidity_amount, - }, + liquidity: liquidity_amount + } ); return liquidity_token @@ -724,7 +727,7 @@ module initia_std::stableswap { let liquidity_amount = fungible_asset::amount(&liquidity_token); assert!( liquidity_amount != 0, - error::invalid_argument(EZERO_LIQUIDITY), + error::invalid_argument(EZERO_LIQUIDITY) ); let pool = borrow_pool(pool_obj); let pool_signer = object::generate_signer_for_extending(&pool.extend_ref); @@ -745,15 +748,16 @@ module initia_std::stableswap { mul_div_u128( (pool_amount as u128), (liquidity_amount as u128), - total_supply, + total_supply ) as u64 ); let min_return = vector::borrow(&min_return_amounts, i); let coin_metadata = *vector::borrow(&pool.coin_metadata, i); assert!( - option::is_none(min_return) || *option::borrow(min_return) <= return_amount, - error::invalid_state(EMIN_WITHDRAW), + option::is_none(min_return) + || *option::borrow(min_return) <= return_amount, + error::invalid_state(EMIN_WITHDRAW) ); vector::push_back(&mut coin_amounts, return_amount); @@ -762,8 +766,8 @@ module initia_std::stableswap { primary_fungible_store::withdraw( &pool_signer, coin_metadata, - return_amount, - ), + return_amount + ) ); i = i + 1; }; @@ -776,8 +780,8 @@ module initia_std::stableswap { coin_amounts, fee_amounts, liquidity_token: pool_addr, - liquidity: liquidity_amount, - }, + liquidity: liquidity_amount + } ); return return_coins @@ -786,7 +790,7 @@ module initia_std::stableswap { public fun single_asset_withdraw_liquidity( liquidity_token: FungibleAsset, return_coin_metadata: Object, - min_return_amount: Option, + min_return_amount: Option ): FungibleAsset acquires Pool { // get pool infos let pool_addr = @@ -797,7 +801,7 @@ module initia_std::stableswap { let liquidity_amount = fungible_asset::amount(&liquidity_token); assert!( liquidity_amount != 0, - error::invalid_argument(EZERO_LIQUIDITY), + error::invalid_argument(EZERO_LIQUIDITY) ); let pool = borrow_pool(pool_obj); @@ -815,12 +819,12 @@ module initia_std::stableswap { single_asset_withdraw_simulation( pool_obj, liquidity_amount, - return_index, + return_index ); assert!( option::is_none(&min_return_amount) || *option::borrow(&min_return_amount) <= return_amount, - error::invalid_state(EMIN_RETURN), + error::invalid_state(EMIN_RETURN) ); // withdraw return coin @@ -828,7 +832,7 @@ module initia_std::stableswap { primary_fungible_store::withdraw( &pool_signer, return_coin_metadata, - return_amount, + return_amount ); // burn liquidity token @@ -855,8 +859,8 @@ module initia_std::stableswap { coin_amounts, fee_amounts, liquidity_token: pool_addr, - liquidity: liquidity_amount, - }, + liquidity: liquidity_amount + } ); return_coin @@ -876,14 +880,14 @@ module initia_std::stableswap { offer_coin_metadata, return_coin_metadata, offer_amount, - true, + true ); return_amount = return_amount - fee_amount; assert!( option::is_none(&min_return_amount) || *option::borrow(&min_return_amount) <= return_amount, - error::invalid_state(EMIN_RETURN), + error::invalid_state(EMIN_RETURN) ); let pool = borrow_pool(pool_obj); @@ -894,7 +898,7 @@ module initia_std::stableswap { primary_fungible_store::withdraw( &pool_signer, return_coin_metadata, - return_amount, + return_amount ); event::emit( @@ -904,24 +908,23 @@ module initia_std::stableswap { liquidity_token: pool_addr, fee_amount, offer_amount, - return_amount, - }, + return_amount + } ); return return_coin } - public fun pool_info(pool_obj: Object) - : ( - vector>, vector, u64, Decimal128 - ) acquires Pool { + public fun pool_info( + pool_obj: Object + ): (vector>, vector, u64, BigDecimal) acquires Pool { let pool_addr = object::object_address(&pool_obj); let pool = borrow_global(pool_addr); let ann = get_current_ann(&pool.ann); let pool_amounts = get_pool_amounts(pool_addr, pool.coin_metadata); - (pool.coin_metadata, pool_amounts, ann, pool.swap_fee_rate,) + (pool.coin_metadata, pool_amounts, ann, pool.swap_fee_rate) } inline fun borrow_pool(pool_obj: Object): &Pool { @@ -956,7 +959,7 @@ module initia_std::stableswap { let len = vector::length(coin_metadata); assert!( len == vector::length(coins), - error::invalid_argument(EN_COINS), + error::invalid_argument(EN_COINS) ); let i = 0; @@ -965,7 +968,7 @@ module initia_std::stableswap { let metadata_ = fungible_asset::metadata_from_asset(vector::borrow(coins, i)); assert!( *metadata == metadata_, - error::invalid_argument(ECOIN_TYPE), + error::invalid_argument(ECOIN_TYPE) ); i = i + 1; }; @@ -983,7 +986,7 @@ module initia_std::stableswap { let metadata = *vector::borrow(&coin_metadata, i); vector::push_back( &mut amounts, - primary_fungible_store::balance(pool_addr, metadata), + primary_fungible_store::balance(pool_addr, metadata) ); i = i + 1; }; @@ -1040,7 +1043,8 @@ module initia_std::stableswap { let d_prod = d; let j = 0; while (j < (n as u64)) { - d_prod = d_prod * d / (n as u256) / (*vector::borrow(&amounts, j) as u256); + d_prod = d_prod * d / (n as u256) + / (*vector::borrow(&amounts, j) as u256); j = j + 1; }; @@ -1086,7 +1090,7 @@ module initia_std::stableswap { pool_amounts: vector, y_index: u64, ann: u64, - d: u64, + d: u64 ): u64 { let d = (d as u256); let ann = (ann as u256); @@ -1136,17 +1140,16 @@ module initia_std::stableswap { } public fun single_asset_withdraw_simulation( - pool_obj: Object, - liquidity_amount: u64, - return_index: u64, + pool_obj: Object, liquidity_amount: u64, return_index: u64 ): (u64, u64) acquires Pool { let pool_addr = object::object_address(&pool_obj); let pool = borrow_global(pool_addr); let n = vector::length(&pool.coin_metadata); let ann = get_current_ann(&pool.ann); let withdraw_fee_rate = - decimal128::new( - decimal128::val(&pool.swap_fee_rate) * (n as u128) / (4 * (n - 1) as u128), + bigdecimal::div_by_u64( + bigdecimal::mul_by_u64(pool.swap_fee_rate, n), + 4 * (n - 1) ); let total_supply = option::extract(&mut fungible_asset::supply(pool_obj)); let pool_amounts = get_pool_amounts(pool_addr, pool.coin_metadata); @@ -1157,7 +1160,7 @@ module initia_std::stableswap { mul_div_u128( (liquidity_amount as u128), (d_before as u128), - total_supply, + total_supply ) as u64 ); @@ -1165,7 +1168,7 @@ module initia_std::stableswap { pool_amounts, return_index, ann, - d_after, + d_after ); let return_amount_without_fee = *vector::borrow(&pool_amounts, return_index) - y_without_fee; @@ -1182,20 +1185,20 @@ module initia_std::stableswap { mul_div_u64( *vector::borrow(&pool_amounts, i), d_after, - d_before, + d_before ) - y_without_fee } else { *vector::borrow(&pool_amounts, i) - mul_div_u64( *vector::borrow(&pool_amounts, i), d_after, - d_before, + d_before ) }; let pool_amount = vector::borrow_mut(&mut pool_amounts_reduced, i); *pool_amount = *pool_amount - - decimal128::mul_u64(&withdraw_fee_rate, amount_diff); + - bigdecimal::mul_by_u64_truncate(withdraw_fee_rate, amount_diff); i = i + 1; }; @@ -1205,7 +1208,7 @@ module initia_std::stableswap { pool_amounts_reduced, return_index, ann, - d_after, + d_after ) - 1; // sub 1 in case of rounding errors (return_amount, return_amount_without_fee - return_amount) @@ -1214,21 +1217,22 @@ module initia_std::stableswap { public fun imbalance_withdraw_simulation( pool_obj: Object, coin_amounts: vector, - max_liquidity_amount: Option, + max_liquidity_amount: Option ): (u64, vector) acquires Pool { let pool_addr = object::object_address(&pool_obj); let pool = borrow_global(pool_addr); let n = vector::length(&pool.coin_metadata); let ann = get_current_ann(&pool.ann); let withdraw_fee_rate = - decimal128::new( - decimal128::val(&pool.swap_fee_rate) * (n as u128) / (4 * (n - 1) as u128), + bigdecimal::div_by_u64( + bigdecimal::mul_by_u64(pool.swap_fee_rate, n), + 4 * (n - 1) ); let total_supply = option::extract(&mut fungible_asset::supply(pool_obj)); assert!( n == vector::length(&coin_amounts), - error::invalid_argument(EN_COINS), + error::invalid_argument(EN_COINS) ); let pool_amounts_before = get_pool_amounts(pool_addr, pool.coin_metadata); @@ -1255,7 +1259,7 @@ module initia_std::stableswap { mul_div_u64( *vector::borrow(&pool_amounts_before, i), d_after_without_fee, - d_before, + d_before ); let balance_after = vector::borrow_mut(&mut pool_amounts_after, i); let amount_diff = @@ -1264,7 +1268,7 @@ module initia_std::stableswap { } else { ideal_balance - *balance_after }; - let fee = decimal128::mul_u64(&withdraw_fee_rate, amount_diff); + let fee = bigdecimal::mul_by_u64_ceil(withdraw_fee_rate, amount_diff); vector::push_back(&mut fees, fee); *balance_after = *balance_after - fee; // to get d_after remove fee i = i + 1; @@ -1276,19 +1280,19 @@ module initia_std::stableswap { mul_div_u128( total_supply, (d_before - d_after as u128), - (d_before as u128), + (d_before as u128) ) as u64 ); assert!( liquidity_amount != 0, - error::invalid_state(EZERO_LIQUIDITY), + error::invalid_state(EZERO_LIQUIDITY) ); liquidity_amount = liquidity_amount + 1; // add 1 just in case of rounding errors assert!( option::is_none(&max_liquidity_amount) || *option::borrow(&max_liquidity_amount) >= liquidity_amount, - error::invalid_state(EMAX_LIQUIDITY), + error::invalid_state(EMAX_LIQUIDITY) ); (liquidity_amount, fees) @@ -1299,7 +1303,7 @@ module initia_std::stableswap { offer_coin_metadata: Object, return_coin_metadata: Object, amount: u64, - is_offer_amount: bool, + is_offer_amount: bool ): (u64, u64) acquires Pool { let pool = borrow_pool(pool_obj); let pool_addr = object::object_address(&pool_obj); @@ -1310,12 +1314,12 @@ module initia_std::stableswap { offer_coin_metadata, return_coin_metadata, amount, - is_offer_amount, + is_offer_amount ) } public fun provide_simulation( - pool_obj: Object, amounts: vector, + pool_obj: Object, amounts: vector ): (u64, vector) acquires Pool { let pool = borrow_pool(pool_obj); let pool_addr = object::object_address(&pool_obj); @@ -1335,12 +1339,12 @@ module initia_std::stableswap { if (total_supply == 0) { assert!( offer_amount > 0, - error::invalid_argument(EZERO_LIQUIDITY), + error::invalid_argument(EZERO_LIQUIDITY) ); }; vector::push_back( &mut pool_amounts_after, - pool_amount + offer_amount, + pool_amount + offer_amount ); i = i + 1; }; @@ -1352,9 +1356,9 @@ module initia_std::stableswap { let liquidity_amount = if (total_supply > 0) { let provide_fee_rate = - decimal128::new( - decimal128::val(&pool.swap_fee_rate) * (n as u128) - / (4 * (n - 1) as u128), + bigdecimal::div_by_u64( + bigdecimal::mul_by_u64(pool.swap_fee_rate, n), + 4 * (n - 1) ); i = 0; while (i < n) { @@ -1363,7 +1367,7 @@ module initia_std::stableswap { let ideal_balance = mul_div_u64( d_ideal, pool_amount_before, - d_before, + d_before ); let diff = if (ideal_balance > *pool_amount_after) { @@ -1371,7 +1375,7 @@ module initia_std::stableswap { } else { *pool_amount_after - ideal_balance }; - let fee = decimal128::mul_u64(&provide_fee_rate, diff); + let fee = bigdecimal::mul_by_u64_ceil(provide_fee_rate, diff); vector::push_back(&mut fee_amounts, fee); *pool_amount_after = *pool_amount_after - fee; i = i + 1; @@ -1382,7 +1386,7 @@ module initia_std::stableswap { mul_div_u128( total_supply, (d_real - d_before as u128), - (d_before as u128), + (d_before as u128) ) as u64 ) } else { @@ -1398,11 +1402,11 @@ module initia_std::stableswap { offer_coin_metadata: Object, return_coin_metadata: Object, amount: u64, - is_offer_amount: bool, + is_offer_amount: bool ): (u64, u64) acquires Pool { assert!( offer_coin_metadata != return_coin_metadata, - error::invalid_argument(ESAME_COIN_TYPE), + error::invalid_argument(ESAME_COIN_TYPE) ); let pool = borrow_pool(pool_obj); let n = vector::length(&pool.coin_metadata); @@ -1425,23 +1429,20 @@ module initia_std::stableswap { assert!( offer_index != n && return_index != n, - error::invalid_argument(ECOIN_TYPE), + error::invalid_argument(ECOIN_TYPE) ); if (!is_offer_amount) { - let denominator = decimal128::val(&decimal128::one()); amount = amount + 1; // for revert sub 1 when get return amount // adjust fee. amount = amount * 1 / (1 - f) let return_amount = - ( - mul_div_u128( - (amount as u128), - denominator, - (denominator - decimal128::val(&pool.swap_fee_rate)), - ) as u64 + bigdecimal::truncate_u64( + bigdecimal::div( + bigdecimal::from_u64(amount), + bigdecimal::sub(bigdecimal::one(), pool.swap_fee_rate) + ) ); - let fee_amount = return_amount - amount; let y = @@ -1451,7 +1452,7 @@ module initia_std::stableswap { return_amount, pool_amounts, ann, - is_offer_amount, + is_offer_amount ); let offer_amount = y - *vector::borrow(&pool_amounts, offer_index); @@ -1464,11 +1465,12 @@ module initia_std::stableswap { amount, pool_amounts, ann, - is_offer_amount, + is_offer_amount ); let return_amount = *vector::borrow(&pool_amounts, return_index) - y - 1; // sub 1 in case of rounding errors - let fee_amount = decimal128::mul_u64(&pool.swap_fee_rate, return_amount); + let fee_amount = + bigdecimal::mul_by_u64_ceil(pool.swap_fee_rate, return_amount); (return_amount, fee_amount) } @@ -1486,7 +1488,7 @@ module initia_std::stableswap { fun check_chain_permission(chain: &signer) { assert!( signer::address_of(chain) == @initia_std, - error::permission_denied(EUNAUTHORIZED), + error::permission_denied(EUNAUTHORIZED) ); } @@ -1496,10 +1498,9 @@ module initia_std::stableswap { } #[test_only] - fun initialized_coin(account: &signer, symbol: String,) - : ( - coin::BurnCapability, coin::FreezeCapability, coin::MintCapability - ) { + fun initialized_coin( + account: &signer, symbol: String + ): (coin::BurnCapability, coin::FreezeCapability, coin::MintCapability) { let (mint_cap, burn_cap, freeze_cap, _) = coin::initialize_and_generate_extend_ref( account, @@ -1508,7 +1509,7 @@ module initia_std::stableswap { symbol, 6, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); return (burn_cap, freeze_cap, mint_cap) @@ -1530,61 +1531,61 @@ module initia_std::stableswap { &chain, string::utf8(b"lp"), string::utf8(b"lp"), - decimal128::from_ratio(5, 10000), + bigdecimal::from_ratio_u64(5, 10000), vector[metadata_a, metadata_b], vector[100000000, 100000000], - 6000, + 6000 ); let metadata_lp = coin::metadata(chain_addr, string::utf8(b"lp")); let pool = object::convert(metadata_lp); assert!( coin::balance(chain_addr, metadata_lp) == 200000000, - 0, + 0 ); assert!( coin::balance(chain_addr, metadata_a) == 900000000, - 0, + 0 ); assert!( coin::balance(chain_addr, metadata_b) == 900000000, - 0, + 0 ); provide_liquidity_script( &chain, pool, vector[100000000, 100000000], - option::none(), + option::none() ); assert!( coin::balance(chain_addr, metadata_lp) == 400000000, - 1, + 1 ); assert!( coin::balance(chain_addr, metadata_a) == 800000000, - 1, + 1 ); assert!( coin::balance(chain_addr, metadata_b) == 800000000, - 1, + 1 ); withdraw_liquidity_script( &chain, pool, 200000000, - vector[option::none(), option::none()], + vector[option::none(), option::none()] ); assert!( coin::balance(chain_addr, metadata_lp) == 200000000, - 2, + 2 ); assert!( coin::balance(chain_addr, metadata_a) == 900000000, - 2, + 2 ); assert!( coin::balance(chain_addr, metadata_b) == 900000000, - 2, + 2 ); let offer_coin = coin::withdraw(&chain, metadata_a, 1000000); @@ -1592,10 +1593,10 @@ module initia_std::stableswap { pool, offer_coin, metadata_b, - option::none(), + option::none() ); let return_amount = fungible_asset::amount(&return_coin); - assert!(return_amount == 999178, 3); + assert!(return_amount == 999177, 3); coin::deposit(chain_addr, return_coin); } @@ -1616,10 +1617,10 @@ module initia_std::stableswap { &chain, string::utf8(b"lp"), string::utf8(b"lp"), - decimal128::new(0), + bigdecimal::zero(), vector[metadata_a, metadata_b], vector[100000000, 100000000], - 6000, + 6000 ); let metadata_lp = coin::metadata(chain_addr, string::utf8(b"lp")); @@ -1630,7 +1631,7 @@ module initia_std::stableswap { &chain, pool, vector[100000000, 0], - option::none(), + option::none() ); let liquidity_after = coin::balance(chain_addr, metadata_lp); @@ -1639,13 +1640,13 @@ module initia_std::stableswap { pool, metadata_a, liquidity_after - liquidity_before, - option::none(), + option::none() ); // theorically it should be 100000000, 100000000 but reduce 1 from return amount because of rounding error assert!( get_pool(pool).coin_balances == vector[100000001, 100000000], - 0, + 0 ); } @@ -1665,10 +1666,10 @@ module initia_std::stableswap { &chain, string::utf8(b"lp"), string::utf8(b"lp"), - decimal128::new(0), + bigdecimal::zero(), vector[metadata_a, metadata_b], vector[100000000, 100000000], - 6000, + 6000 ); let metadata_lp = coin::metadata(chain_addr, string::utf8(b"lp")); @@ -1679,14 +1680,14 @@ module initia_std::stableswap { &chain, pool, vector[100000000, 50000000], - option::none(), + option::none() ); imbalance_withdraw_liquidity_script( &chain, pool, vector[100000000, 50000000], - option::none(), + option::none() ); let liquidity_after = coin::balance(chain_addr, metadata_lp); diff --git a/initia_stdlib/sources/staking.move b/initia_stdlib/sources/staking.move index e739119..36d8a96 100644 --- a/initia_stdlib/sources/staking.move +++ b/initia_stdlib/sources/staking.move @@ -13,40 +13,40 @@ module initia_std::staking { use initia_std::object::{Self, Object, ExtendRef}; use initia_std::fungible_asset::{Self, Metadata, FungibleStore, FungibleAsset}; use initia_std::table::{Self, Table}; - use initia_std::decimal128::{Self, Decimal128}; + use initia_std::bigdecimal::{Self, BigDecimal}; use initia_std::coin; use initia_std::string; struct ModuleStore has key { - staking_states: Table, Table>, + staking_states: Table, Table> } struct StakingState has store { metadata: Object, validator: String, - total_share: u128, - unbonding_share: u128, - reward_index: Decimal128, + total_share: BigDecimal, + unbonding_share: BigDecimal, + reward_index: BigDecimal, reward_coin_store_ref: ExtendRef, unbonding_coin_store_ref: ExtendRef, reward_coin_store: Object, - unbonding_coin_store: Object, + unbonding_coin_store: Object } /// Define a delegation entry which can be transferred. struct Delegation has store { metadata: Object, validator: String, - share: u64, - reward_index: Decimal128, + share: BigDecimal, + reward_index: BigDecimal } /// Define a unbonding entry which can be transferred. struct Unbonding has store { metadata: Object, validator: String, - unbonding_share: u64, - release_time: u64, + unbonding_share: BigDecimal, + release_time: u64 } /// A holder of delegations and unbonding delegations. @@ -55,7 +55,7 @@ module initia_std::staking { // key: metadata + validator delegations: Table, Table>, // key: metadata + validator + release_times - unbondings: Table, Table>, + unbondings: Table, Table> } // Keys @@ -63,7 +63,7 @@ module initia_std::staking { /// Key for `Unbonding` struct UnbondingKey has copy, drop { validator: String, - release_time: u64, + release_time: u64 } // Events @@ -73,7 +73,7 @@ module initia_std::staking { struct RewardEvent has drop, store { account: address, metadata: Object, - amount: u64, + amount: u64 } #[event] @@ -82,7 +82,7 @@ module initia_std::staking { account: address, metadata: Object, validator: String, - share: u64, + share: BigDecimal } #[event] @@ -91,7 +91,7 @@ module initia_std::staking { account: address, metadata: Object, validator: String, - share: u64, + share: BigDecimal } #[event] @@ -100,8 +100,8 @@ module initia_std::staking { account: address, metadata: Object, validator: String, - share: u64, - release_time: u64, + share: BigDecimal, + release_time: u64 } #[event] @@ -110,8 +110,8 @@ module initia_std::staking { account: address, metadata: Object, validator: String, - share: u64, - release_time: u64, + share: BigDecimal, + release_time: u64 } // Query responses @@ -119,15 +119,15 @@ module initia_std::staking { struct DelegationResponse has drop { metadata: Object, validator: String, - share: u64, - unclaimed_reward: u64, + share: BigDecimal, + unclaimed_reward: u64 } struct UnbondingResponse has drop { metadata: Object, validator: String, unbonding_amount: u64, - release_time: u64, + release_time: u64 } // Errors @@ -197,7 +197,7 @@ module initia_std::staking { fun init_module(chain: &signer) { move_to( chain, - ModuleStore { staking_states: table::new(), }, + ModuleStore { staking_states: table::new() } ); } @@ -210,13 +210,13 @@ module initia_std::staking { ): &StakingState { assert!( table::contains(staking_states, metadata), - error::not_found(ESTAKING_STATE_NOT_EXISTS), + error::not_found(ESTAKING_STATE_NOT_EXISTS) ); let states = table::borrow(staking_states, metadata); assert!( table::contains(states, validator), - error::not_found(ESTAKING_STATE_NOT_EXISTS), + error::not_found(ESTAKING_STATE_NOT_EXISTS) ); table::borrow(states, validator) } @@ -228,13 +228,13 @@ module initia_std::staking { ): &mut StakingState { assert!( table::contains(staking_states, metadata), - error::not_found(ESTAKING_STATE_NOT_EXISTS), + error::not_found(ESTAKING_STATE_NOT_EXISTS) ); let states = table::borrow_mut(staking_states, metadata); assert!( table::contains(states, validator), - error::not_found(ESTAKING_STATE_NOT_EXISTS), + error::not_found(ESTAKING_STATE_NOT_EXISTS) ); table::borrow_mut(states, validator) } @@ -246,13 +246,13 @@ module initia_std::staking { ): &Delegation { assert!( table::contains(delegations, metadata), - error::not_found(EDELEGATION_NOT_FOUND), + error::not_found(EDELEGATION_NOT_FOUND) ); let delegations = table::borrow(delegations, metadata); assert!( table::contains(delegations, validator), - error::not_found(EDELEGATION_NOT_FOUND), + error::not_found(EDELEGATION_NOT_FOUND) ); table::borrow(delegations, validator) } @@ -264,13 +264,13 @@ module initia_std::staking { ): &mut Delegation { assert!( table::contains(delegations, metadata), - error::not_found(EDELEGATION_NOT_FOUND), + error::not_found(EDELEGATION_NOT_FOUND) ); let delegations = table::borrow_mut(delegations, metadata); assert!( table::contains(delegations, validator), - error::not_found(EDELEGATION_NOT_FOUND), + error::not_found(EDELEGATION_NOT_FOUND) ); table::borrow_mut(delegations, validator) } @@ -283,14 +283,14 @@ module initia_std::staking { ): &Unbonding { assert!( table::contains(unbondings, metadata), - error::not_found(EUNBONDING_NOT_FOUND), + error::not_found(EUNBONDING_NOT_FOUND) ); let unbondings = table::borrow(unbondings, metadata); let key = UnbondingKey { validator, release_time }; assert!( table::contains(unbondings, key), - error::not_found(EUNBONDING_NOT_FOUND), + error::not_found(EUNBONDING_NOT_FOUND) ); table::borrow(unbondings, key) } @@ -303,14 +303,14 @@ module initia_std::staking { ): &mut Unbonding { assert!( table::contains(unbondings, metadata), - error::not_found(EUNBONDING_NOT_FOUND), + error::not_found(EUNBONDING_NOT_FOUND) ); let unbondings = table::borrow_mut(unbondings, metadata); let key = UnbondingKey { validator, release_time }; assert!( table::contains(unbondings, key), - error::not_found(EUNBONDING_NOT_FOUND), + error::not_found(EUNBONDING_NOT_FOUND) ); table::borrow_mut(unbondings, key) } @@ -328,7 +328,7 @@ module initia_std::staking { let state = load_staking_state( &module_store.staking_states, metadata, - validator, + validator ); let reward = calculate_reward(delegation, state); @@ -337,7 +337,7 @@ module initia_std::staking { metadata: delegation.metadata, validator: delegation.validator, share: delegation.share, - unclaimed_reward: reward, + unclaimed_reward: reward } } @@ -351,20 +351,18 @@ module initia_std::staking { metadata: unbonding.metadata, validator: unbonding.validator, unbonding_amount, - release_time: unbonding.release_time, + release_time: unbonding.release_time } } #[view] /// Get delegation info of specifed addr and validator public fun get_delegation( - addr: address, - metadata: Object, - validator: String, + addr: address, metadata: Object, validator: String ): DelegationResponse acquires DelegationStore, ModuleStore { assert!( is_account_registered(addr), - error::not_found(EDELEGATION_STORE_NOT_EXISTS), + error::not_found(EDELEGATION_STORE_NOT_EXISTS) ); let delegation_store = borrow_global(addr); @@ -372,14 +370,14 @@ module initia_std::staking { load_delegation( &delegation_store.delegations, metadata, - validator, + validator ); let module_store = borrow_global(@initia_std); let state = load_staking_state( &module_store.staking_states, metadata, - validator, + validator ); let reward = calculate_reward(delegation, state); @@ -388,7 +386,7 @@ module initia_std::staking { metadata, validator, share: delegation.share, - unclaimed_reward: reward, + unclaimed_reward: reward } } @@ -398,7 +396,7 @@ module initia_std::staking { addr: address, metadata: Object, start_after: Option, - limit: u8, + limit: u8 ): vector acquires DelegationStore, ModuleStore { if (limit > MAX_LIMIT) { limit = MAX_LIMIT; @@ -406,7 +404,7 @@ module initia_std::staking { assert!( is_account_registered(addr), - error::not_found(EDELEGATION_STORE_NOT_EXISTS), + error::not_found(EDELEGATION_STORE_NOT_EXISTS) ); let module_store = borrow_global(@initia_std); @@ -418,7 +416,7 @@ module initia_std::staking { delegations, option::none(), start_after, - 2, + 2 ); let prepare = table::prepare(delegations_iter); @@ -433,8 +431,8 @@ module initia_std::staking { metadata: delegation.metadata, validator: delegation.validator, share: delegation.share, - unclaimed_reward: reward, - }, + unclaimed_reward: reward + } ); prepare = table::prepare(delegations_iter); }; @@ -448,11 +446,11 @@ module initia_std::staking { addr: address, metadata: Object, validator: String, - release_time: u64, + release_time: u64 ): UnbondingResponse acquires DelegationStore, ModuleStore { assert!( is_account_registered(addr), - error::not_found(EDELEGATION_STORE_NOT_EXISTS), + error::not_found(EDELEGATION_STORE_NOT_EXISTS) ); let delegation_store = borrow_global(addr); @@ -462,7 +460,7 @@ module initia_std::staking { &delegation_store.unbondings, metadata, validator, - release_time, + release_time ); let unbonding_amount = get_unbonding_amount_from_unbonding(unbonding); @@ -470,7 +468,7 @@ module initia_std::staking { metadata: unbonding.metadata, validator: unbonding.validator, unbonding_amount, - release_time, + release_time } } @@ -481,7 +479,7 @@ module initia_std::staking { metadata: Object, start_after_validator: Option, start_after_release_time: Option, - limit: u8, + limit: u8 ): vector acquires DelegationStore, ModuleStore { if (limit > MAX_LIMIT) { limit = MAX_LIMIT; @@ -489,13 +487,13 @@ module initia_std::staking { assert!( is_account_registered(addr), - error::not_found(EDELEGATION_STORE_NOT_EXISTS), + error::not_found(EDELEGATION_STORE_NOT_EXISTS) ); assert!( option::is_some(&start_after_validator) == option::is_some(&start_after_release_time), - error::invalid_argument(EINVALID_START_AFTER), + error::invalid_argument(EINVALID_START_AFTER) ); let delegation_store = borrow_global(addr); @@ -506,8 +504,8 @@ module initia_std::staking { option::some( UnbondingKey { validator: *option::borrow(&start_after_validator), - release_time: *option::borrow(&start_after_release_time), - }, + release_time: *option::borrow(&start_after_release_time) + } ) } else { option::none() @@ -517,12 +515,12 @@ module initia_std::staking { unbondings, option::none(), start_after, - 2, + 2 ); let res: vector = vector[]; while (vector::length(&res) < (limit as u64) - && table::prepare(unbondings_iter)) { + && table::prepare(unbondings_iter)) { let (_, unbonding) = table::next(unbondings_iter); let unbonding_amount = get_unbonding_amount_from_unbonding(unbonding); vector::push_back( @@ -531,8 +529,8 @@ module initia_std::staking { metadata: unbonding.metadata, validator: unbonding.validator, unbonding_amount, - release_time: unbonding.release_time, - }, + release_time: unbonding.release_time + } ); }; @@ -558,7 +556,7 @@ module initia_std::staking { /// get `share` from `DelegationResponse` public fun get_share_from_delegation_response( delegation_res: &DelegationResponse - ): u64 { + ): BigDecimal { delegation_res.share } @@ -603,7 +601,7 @@ module initia_std::staking { fun check_chain_permission(chain: &signer) { assert!( signer::address_of(chain) == @initia_std, - error::permission_denied(EUNAUTHORIZED_CHAIN_OPERATION), + error::permission_denied(EUNAUTHORIZED_CHAIN_OPERATION) ); } @@ -618,14 +616,14 @@ module initia_std::staking { assert!( !table::contains( &module_store.staking_states, - metadata, + metadata ), - error::already_exists(ESTAKING_STATE_ALREADY_EXISTS), + error::already_exists(ESTAKING_STATE_ALREADY_EXISTS) ); table::add( &mut module_store.staking_states, metadata, - table::new(), + table::new() ); } @@ -634,7 +632,7 @@ module initia_std::staking { chain: &signer, metadata: Object, validator: String, - fraction: String + fraction: BigDecimal ) acquires ModuleStore { check_chain_permission(chain); @@ -643,13 +641,11 @@ module initia_std::staking { load_staking_state_mut( &mut module_store.staking_states, metadata, - validator, + validator ); - let fraction = decimal128::from_string(&fraction); - let unbonding_amount = fungible_asset::balance(state.unbonding_coin_store); - let slash_amount = decimal128::mul_u64(&fraction, unbonding_amount); + let slash_amount = bigdecimal::mul_by_u64_truncate(fraction, unbonding_amount); if (slash_amount > 0) { let unbonding_coin_store_signer = @@ -660,7 +656,7 @@ module initia_std::staking { fungible_asset::withdraw( unbonding_coin_store_signer, state.unbonding_coin_store, - slash_amount, + slash_amount ); // deposit to relayer for fund community pool @@ -672,7 +668,7 @@ module initia_std::staking { cosmos::fund_community_pool( &staking_module, metadata, - slash_amount, + slash_amount ); } } @@ -688,7 +684,7 @@ module initia_std::staking { assert!( vector::length(&validators) == vector::length(&amounts), - error::invalid_argument(ELENGTH_MISMATCH), + error::invalid_argument(ELENGTH_MISMATCH) ); let module_store = borrow_global_mut(@initia_std); let staking_module = create_signer(@relayer); @@ -701,7 +697,7 @@ module initia_std::staking { load_staking_state_mut( &mut module_store.staking_states, metadata, - validator, + validator ); // calculate share @@ -709,21 +705,21 @@ module initia_std::staking { fungible_asset::balance(state.unbonding_coin_store); let share_amount_ratio = if (total_unbonding_amount == 0) { - decimal128::one() + bigdecimal::one() } else { - decimal128::from_ratio( - state.unbonding_share, - (total_unbonding_amount as u128), - ) + bigdecimal::div_by_u64(state.unbonding_share, total_unbonding_amount) }; - let share_diff = decimal128::mul_u64(&share_amount_ratio, amount); - state.unbonding_share = state.unbonding_share + (share_diff as u128); + let share_diff = + bigdecimal::mul( + share_amount_ratio, bigdecimal::from_ratio_u64(amount, 1) + ); + state.unbonding_share = bigdecimal::add(state.unbonding_share, share_diff); let unbonding_coin = coin::withdraw(&staking_module, metadata, amount); fungible_asset::deposit( state.unbonding_coin_store, - unbonding_coin, + unbonding_coin ); index = index + 1; @@ -735,13 +731,13 @@ module initia_std::staking { chain: &signer, metadata: Object, validators: vector, - reward_amounts: vector, + reward_amounts: vector ) acquires ModuleStore { check_chain_permission(chain); assert!( vector::length(&validators) == vector::length(&reward_amounts), - error::invalid_argument(ELENGTH_MISMATCH), + error::invalid_argument(ELENGTH_MISMATCH) ); let module_store = borrow_global_mut(@initia_std); let staking_module = create_signer(@relayer); @@ -754,21 +750,18 @@ module initia_std::staking { let reward = coin::withdraw( &staking_module, reward_metadata, - reward_amount, + reward_amount ); let state = load_staking_state_mut( &mut module_store.staking_states, metadata, - validator, + validator ); - state.reward_index = decimal128::add( - &state.reward_index, - &decimal128::from_ratio( - (reward_amount as u128), - state.total_share, - ), + state.reward_index = bigdecimal::add( + state.reward_index, + bigdecimal::rev(bigdecimal::div_by_u64(state.total_share, reward_amount)) ); fungible_asset::deposit(state.reward_coin_store, reward); @@ -789,12 +782,12 @@ module initia_std::staking { let account_addr = signer::address_of(account); assert!( !is_account_registered(account_addr), - error::already_exists(EDELEGATION_STORE_ALREADY_EXISTS), + error::already_exists(EDELEGATION_STORE_ALREADY_EXISTS) ); let delegation_store = DelegationStore { delegations: table::new, Table>(), - unbondings: table::new, Table>(), + unbondings: table::new, Table>() }; move_to(account, delegation_store); @@ -805,7 +798,7 @@ module initia_std::staking { account: &signer, metadata: Object, validator: String, - amount: u64, + amount: u64 ) acquires DelegationStore, ModuleStore { let account_addr = signer::address_of(account); if (!is_account_registered(account_addr)) { @@ -821,8 +814,8 @@ module initia_std::staking { RewardEvent { account: account_addr, metadata, - amount: fungible_asset::amount(&reward), - }, + amount: fungible_asset::amount(&reward) + } ); coin::deposit(account_addr, reward); @@ -836,9 +829,9 @@ module initia_std::staking { assert!( table::contains( &module_store.staking_states, - metadata, + metadata ), - error::not_found(ESTAKING_STATE_NOT_EXISTS), + error::not_found(ESTAKING_STATE_NOT_EXISTS) ); let states = table::borrow_mut(&mut module_store.staking_states, metadata); @@ -851,7 +844,7 @@ module initia_std::staking { let reward_coin_store = primary_fungible_store::create_primary_store( reward_coin_store_address, - reward_metadata(), + reward_metadata() ); let unbonding_coin_store_address = @@ -859,7 +852,7 @@ module initia_std::staking { let unbonding_coin_store = primary_fungible_store::create_primary_store( unbonding_coin_store_address, - metadata, + metadata ); table::add( @@ -868,9 +861,9 @@ module initia_std::staking { StakingState { metadata, validator, - total_share: 0, - unbonding_share: 0, - reward_index: decimal128::zero(), + total_share: bigdecimal::zero(), + unbonding_share: bigdecimal::zero(), + reward_index: bigdecimal::zero(), reward_coin_store_ref: object::generate_extend_ref( reward_coin_store_ref ), @@ -878,8 +871,8 @@ module initia_std::staking { unbonding_coin_store_ref ), reward_coin_store, - unbonding_coin_store, - }, + unbonding_coin_store + } ) }; @@ -887,15 +880,15 @@ module initia_std::staking { delegate_internal( *string::bytes(&validator), &metadata, - fungible_asset::amount(&fa), + fungible_asset::amount(&fa) ); let state = load_staking_state_mut( &mut module_store.staking_states, metadata, - validator, + validator ); - state.total_share = state.total_share + (share_diff as u128); + state.total_share = bigdecimal::add(state.total_share, share_diff); // deposit to relayer // relayer is module address, so we need to use sudo_deposit @@ -905,7 +898,7 @@ module initia_std::staking { metadata, validator, share: share_diff, - reward_index: state.reward_index, + reward_index: state.reward_index } } @@ -915,20 +908,22 @@ module initia_std::staking { account: &signer, metadata: Object, validator: String, - amount: u64, + amount: u64 ) acquires DelegationStore, ModuleStore { + let account_addr = signer::address_of(account); assert!( is_account_registered(account_addr), - error::not_found(EDELEGATION_STORE_NOT_EXISTS), + error::not_found(EDELEGATION_STORE_NOT_EXISTS) ); let share = amount_to_share( *string::bytes(&validator), &metadata, - amount, + amount ); + let delegation = withdraw_delegation(account, metadata, validator, share); let (reward, unbonding) = undelegate(delegation); @@ -936,15 +931,15 @@ module initia_std::staking { RewardEvent { account: account_addr, metadata, - amount: fungible_asset::amount(&reward), - }, + amount: fungible_asset::amount(&reward) + } ); coin::deposit(account_addr, reward); deposit_unbonding(account_addr, unbonding); } - public fun undelegate(delegation: Delegation,): (FungibleAsset, Unbonding) acquires ModuleStore { + public fun undelegate(delegation: Delegation): (FungibleAsset, Unbonding) acquires ModuleStore { let share = delegation.share; let validator = delegation.validator; let metadata = delegation.metadata; @@ -953,7 +948,7 @@ module initia_std::staking { undelegate_internal( *string::bytes(&validator), &metadata, - share, + &share ); let reward = destroy_delegation_and_extract_reward(delegation); @@ -962,20 +957,20 @@ module initia_std::staking { load_staking_state_mut( &mut module_store.staking_states, metadata, - validator, + validator ); assert!( - state.total_share >= (share as u128), - error::invalid_state(EINSUFFICIENT_UNBONDING_DELEGATION_TOTAL_SHARE), + bigdecimal::ge(state.total_share, share), + error::invalid_state(EINSUFFICIENT_UNBONDING_DELEGATION_TOTAL_SHARE) ); - state.total_share = state.total_share - (share as u128); + state.total_share = bigdecimal::sub(state.total_share, share); let unbonding_share = unbonding_share_from_amount( metadata, validator, - unbonding_amount, + unbonding_amount ); let unbonding = Unbonding { metadata, validator, unbonding_share, release_time }; @@ -993,7 +988,7 @@ module initia_std::staking { assert!( is_account_registered(account_addr), - error::not_found(EDELEGATION_STORE_NOT_EXISTS), + error::not_found(EDELEGATION_STORE_NOT_EXISTS) ); // withdraw unbonding all @@ -1001,7 +996,7 @@ module initia_std::staking { account_addr, metadata, validator, - release_time, + release_time ); let unbonding = withdraw_unbonding( @@ -1009,7 +1004,7 @@ module initia_std::staking { metadata, validator, release_time, - unbonding_info.unbonding_amount, + unbonding_info.unbonding_amount ); let unbonding_coin = claim_unbonding(unbonding); coin::deposit(account_addr, unbonding_coin) @@ -1022,7 +1017,7 @@ module initia_std::staking { assert!( is_account_registered(account_addr), - error::not_found(EDELEGATION_STORE_NOT_EXISTS), + error::not_found(EDELEGATION_STORE_NOT_EXISTS) ); let delegation_store = borrow_global_mut(account_addr); @@ -1030,7 +1025,7 @@ module initia_std::staking { load_delegation_mut( &mut delegation_store.delegations, metadata, - validator, + validator ); let reward = claim_reward(delegation); @@ -1038,8 +1033,8 @@ module initia_std::staking { RewardEvent { account: account_addr, metadata, - amount: fungible_asset::amount(&reward), - }, + amount: fungible_asset::amount(&reward) + } ); coin::deposit(account_addr, reward); @@ -1054,7 +1049,7 @@ module initia_std::staking { let state = load_staking_state( &module_store.staking_states, metadata, - validator, + validator ); let reward_amount = calculate_reward(delegation, state); @@ -1069,7 +1064,7 @@ module initia_std::staking { fungible_asset::withdraw( reward_coin_store_signer, state.reward_coin_store, - reward_amount, + reward_amount ) }; @@ -1082,11 +1077,11 @@ module initia_std::staking { fun calculate_reward(delegation: &Delegation, state: &StakingState): u64 { assert!( delegation.metadata == state.metadata, - error::invalid_argument(EMETADATA_MISMATCH), + error::invalid_argument(EMETADATA_MISMATCH) ); - let index_diff = decimal128::sub(&state.reward_index, &delegation.reward_index); - decimal128::mul_u64(&index_diff, delegation.share) + let index_diff = bigdecimal::sub(state.reward_index, delegation.reward_index); + bigdecimal::truncate_u64(bigdecimal::mul(index_diff, delegation.share)) } /// For delegation object @@ -1095,7 +1090,12 @@ module initia_std::staking { public fun empty_delegation( metadata: Object, validator: String ): Delegation { - Delegation { metadata, validator, share: 0, reward_index: decimal128::zero(), } + Delegation { + metadata, + validator, + share: bigdecimal::zero(), + reward_index: bigdecimal::zero() + } } /// Get `metadata` from `Delegation` @@ -1109,15 +1109,15 @@ module initia_std::staking { } /// Get `share` from `Delegation` - public fun get_share_from_delegation(delegation: &Delegation): u64 { + public fun get_share_from_delegation(delegation: &Delegation): BigDecimal { delegation.share } /// Destory empty delegation public fun destroy_empty_delegation(delegation: Delegation) { assert!( - delegation.share == 0, - error::invalid_argument(ENOT_EMPTY), + bigdecimal::is_zero(delegation.share), + error::invalid_argument(ENOT_EMPTY) ); let Delegation { metadata: _, validator: _, share: _, reward_index: _ } = delegation; @@ -1125,25 +1125,22 @@ module initia_std::staking { /// Deposit the delegation into recipient's account. public fun deposit_delegation( - account_addr: address, delegation: Delegation, + account_addr: address, delegation: Delegation ): FungibleAsset acquires DelegationStore, ModuleStore { assert!( is_account_registered(account_addr), - error::not_found(EDELEGATION_STORE_NOT_EXISTS), + error::not_found(EDELEGATION_STORE_NOT_EXISTS) ); let metadata = delegation.metadata; let validator = delegation.validator; let delegation_store = borrow_global_mut(account_addr); - if (!table::contains( - &delegation_store.delegations, - metadata, - )) { + if (!table::contains(&delegation_store.delegations, metadata)) { table::add( &mut delegation_store.delegations, metadata, - table::new(), + table::new() ); }; @@ -1154,8 +1151,8 @@ module initia_std::staking { validator, empty_delegation( delegation.metadata, - delegation.validator, - ), + delegation.validator + ) ); }; @@ -1164,15 +1161,15 @@ module initia_std::staking { account: account_addr, metadata: delegation.metadata, share: delegation.share, - validator: delegation.validator, - }, + validator: delegation.validator + } ); let dst_delegation = load_delegation_mut( &mut delegation_store.delegations, metadata, - validator, + validator ); merge_delegation(dst_delegation, delegation) @@ -1183,13 +1180,13 @@ module initia_std::staking { account: &signer, metadata: Object, validator: String, - share: u64, + share: BigDecimal ): Delegation acquires DelegationStore { let account_addr = signer::address_of(account); assert!( is_account_registered(account_addr), - error::not_found(EDELEGATION_STORE_NOT_EXISTS), + error::not_found(EDELEGATION_STORE_NOT_EXISTS) ); let delegation_store = borrow_global_mut(account_addr); @@ -1197,11 +1194,11 @@ module initia_std::staking { load_delegation_mut( &mut delegation_store.delegations, metadata, - validator, + validator ); event::emit( - DelegationWithdrawEvent { account: account_addr, metadata, share, validator, }, + DelegationWithdrawEvent { account: account_addr, metadata, share, validator } ); // If withdraw all, remove delegation @@ -1209,7 +1206,7 @@ module initia_std::staking { let delegations = table::borrow_mut( &mut delegation_store.delegations, - metadata, + metadata ); table::remove(delegations, validator) // Else extract @@ -1220,20 +1217,20 @@ module initia_std::staking { /// Extracts specified share of delegatiion from the passed-in `delegation`. public fun extract_delegation( - delegation: &mut Delegation, share: u64 + delegation: &mut Delegation, share: BigDecimal ): Delegation { assert!( - delegation.share >= share, - error::invalid_argument(EINSUFFICIENT_AMOUNT), + bigdecimal::ge(delegation.share, share), + error::invalid_argument(EINSUFFICIENT_AMOUNT) ); // Total share is invariant and reward_indexes are same btw given and new one so no need to update `reward_index`. - delegation.share = delegation.share - share; + delegation.share = bigdecimal::sub(delegation.share, share); Delegation { metadata: delegation.metadata, validator: delegation.validator, reward_index: delegation.reward_index, - share, + share } } @@ -1244,20 +1241,18 @@ module initia_std::staking { ): FungibleAsset acquires ModuleStore { assert!( dst_delegation.metadata == source_delegation.metadata, - error::invalid_argument(EMETADATA_MISMATCH), + error::invalid_argument(EMETADATA_MISMATCH) ); assert!( dst_delegation.validator == source_delegation.validator, - error::invalid_argument(EVALIDATOR_MISMATCH), + error::invalid_argument(EVALIDATOR_MISMATCH) ); - spec { - assume dst_delegation.share + source_delegation.share <= MAX_U64; - }; - let reward = claim_reward(dst_delegation); - dst_delegation.share = dst_delegation.share + source_delegation.share; + dst_delegation.share = bigdecimal::add( + dst_delegation.share, source_delegation.share + ); let source_reward = destroy_delegation_and_extract_reward(source_delegation); fungible_asset::merge(&mut reward, source_reward); @@ -1266,7 +1261,9 @@ module initia_std::staking { } /// Destroy delegation and extract reward from delegation - fun destroy_delegation_and_extract_reward(delegation: Delegation): FungibleAsset acquires ModuleStore { + fun destroy_delegation_and_extract_reward( + delegation: Delegation + ): FungibleAsset acquires ModuleStore { let metadata = delegation.metadata; let validator = delegation.validator; @@ -1274,7 +1271,7 @@ module initia_std::staking { let state = load_staking_state( &module_store.staking_states, metadata, - validator, + validator ); let reward_amount = calculate_reward(&delegation, state); @@ -1289,7 +1286,7 @@ module initia_std::staking { fungible_asset::withdraw( reward_coin_store_signer, state.reward_coin_store, - reward_amount, + reward_amount ) }; @@ -1304,57 +1301,62 @@ module initia_std::staking { fun unbonding_share_from_amount( metadata: Object, validator: String, unbonding_amount: u64 - ): u64 acquires ModuleStore { + ): BigDecimal acquires ModuleStore { let module_store = borrow_global_mut(@initia_std); let state = load_staking_state( &module_store.staking_states, metadata, - validator, + validator ); - let total_unbonding_amount = fungible_asset::balance(state.unbonding_coin_store); - let share_amount_ratio = - if (total_unbonding_amount == 0) { - decimal128::one() - } else { - decimal128::from_ratio( - state.unbonding_share, - (total_unbonding_amount as u128), - ) - }; - - decimal128::mul_u64(&share_amount_ratio, unbonding_amount) + let share_amount_ratio = unbonding_share_amount_ratio(state); + bigdecimal::mul( + share_amount_ratio, bigdecimal::from_ratio_u64(unbonding_amount, 1) + ) } fun unbonding_amount_from_share( - metadata: Object, validator: String, unbonding_share: u64 + metadata: Object, validator: String, unbonding_share: BigDecimal ): u64 acquires ModuleStore { let module_store = borrow_global(@initia_std); let state = load_staking_state( &module_store.staking_states, metadata, - validator, + validator ); + let amount_share_ratio = bigdecimal::rev(unbonding_share_amount_ratio(state)); + bigdecimal::truncate_u64(bigdecimal::mul(amount_share_ratio, unbonding_share)) + } + + fun unbonding_share_amount_ratio(state: &StakingState): BigDecimal { let total_unbonding_amount = fungible_asset::balance(state.unbonding_coin_store); - let amount_share_ratio = - if (state.unbonding_share == 0) { - decimal128::one() + let share_amount_ratio = + if (total_unbonding_amount == 0) { + bigdecimal::one() } else { - decimal128::from_ratio( - (total_unbonding_amount as u128), - state.unbonding_share, - ) + bigdecimal::div_by_u64(state.unbonding_share, total_unbonding_amount) }; - decimal128::mul_u64(&amount_share_ratio, unbonding_share) + if (bigdecimal::lt(share_amount_ratio, bigdecimal::one())) { + // cap total unbonding amount to total share to prevent poissible attack like depositing huge amount of unbonding coin + // directly to the validator's unbonding_coin_store. + bigdecimal::one() + } else { + share_amount_ratio + } } /// return empty unbonding resource public fun empty_unbonding( metadata: Object, validator: String, release_time: u64 ): Unbonding { - Unbonding { metadata, validator, unbonding_share: 0, release_time, } + Unbonding { + metadata, + validator, + unbonding_share: bigdecimal::zero(), + release_time + } } /// Get `metadata` from `Unbonding` @@ -1373,7 +1375,7 @@ module initia_std::staking { } /// Get `unbonding_share` from `Unbonding` - public fun get_unbonding_share_from_unbonding(unbonding: &Unbonding): u64 { + public fun get_unbonding_share_from_unbonding(unbonding: &Unbonding): BigDecimal { unbonding.unbonding_share } @@ -1382,15 +1384,15 @@ module initia_std::staking { unbonding_amount_from_share( unbonding.metadata, unbonding.validator, - unbonding.unbonding_share, + unbonding.unbonding_share ) } /// Destory empty unbonding public fun destroy_empty_unbonding(unbonding: Unbonding) { assert!( - unbonding.unbonding_share == 0, - error::invalid_argument(ENOT_EMPTY), + bigdecimal::is_zero(unbonding.unbonding_share), + error::invalid_argument(ENOT_EMPTY) ); let Unbonding { metadata: _, validator: _, unbonding_share: _, release_time: _ } = unbonding; @@ -1402,24 +1404,21 @@ module initia_std::staking { ) acquires DelegationStore { assert!( is_account_registered(account_addr), - error::not_found(EDELEGATION_STORE_NOT_EXISTS), + error::not_found(EDELEGATION_STORE_NOT_EXISTS) ); let metadata = unbonding.metadata; let validator = unbonding.validator; let release_time = unbonding.release_time; - let key = UnbondingKey { validator, release_time, }; + let key = UnbondingKey { validator, release_time }; let delegation_store = borrow_global_mut(account_addr); - if (!table::contains( - &delegation_store.unbondings, - metadata, - )) { + if (!table::contains(&delegation_store.unbondings, metadata)) { table::add( &mut delegation_store.unbondings, metadata, - table::new(), + table::new() ); }; @@ -1428,7 +1427,7 @@ module initia_std::staking { table::add( unbondings, key, - empty_unbonding(metadata, validator, release_time), + empty_unbonding(metadata, validator, release_time) ); }; @@ -1438,8 +1437,8 @@ module initia_std::staking { metadata, validator, share: unbonding.unbonding_share, - release_time, - }, + release_time + } ); let dst_unbonding = table::borrow_mut(unbondings, key); @@ -1452,13 +1451,13 @@ module initia_std::staking { metadata: Object, validator: String, release_time: u64, - amount: u64, + amount: u64 ): Unbonding acquires DelegationStore, ModuleStore { let account_addr = signer::address_of(account); assert!( is_account_registered(account_addr), - error::not_found(EDELEGATION_STORE_NOT_EXISTS), + error::not_found(EDELEGATION_STORE_NOT_EXISTS) ); let delegation_store = borrow_global_mut(account_addr); @@ -1467,7 +1466,7 @@ module initia_std::staking { &mut delegation_store.unbondings, metadata, validator, - release_time, + release_time ); event::emit( @@ -1476,8 +1475,8 @@ module initia_std::staking { metadata, validator, share: unbonding.unbonding_share, - release_time: unbonding.release_time, - }, + release_time: unbonding.release_time + } ); let share = unbonding_share_from_amount(metadata, validator, amount); @@ -1485,12 +1484,12 @@ module initia_std::staking { // If withdraw all, remove unbonding let unbondings = table::borrow_mut( &mut delegation_store.unbondings, - metadata, + metadata ); table::remove( unbondings, - UnbondingKey { validator, release_time, }, + UnbondingKey { validator, release_time } ) } else { // Else extract @@ -1499,13 +1498,15 @@ module initia_std::staking { } /// Extracts specified amount of unbonding from the passed-in `unbonding`. - public fun extract_unbonding(unbonding: &mut Unbonding, share: u64): Unbonding { + public fun extract_unbonding( + unbonding: &mut Unbonding, share: BigDecimal + ): Unbonding { assert!( - unbonding.unbonding_share >= share, - error::invalid_argument(EINSUFFICIENT_AMOUNT), + bigdecimal::ge(unbonding.unbonding_share, share), + error::invalid_argument(EINSUFFICIENT_AMOUNT) ); - unbonding.unbonding_share = unbonding.unbonding_share - share; + unbonding.unbonding_share = bigdecimal::sub(unbonding.unbonding_share, share); Unbonding { metadata: unbonding.metadata, validator: unbonding.validator, @@ -1522,24 +1523,20 @@ module initia_std::staking { ) { assert!( dst_unbonding.metadata == source_unbonding.metadata, - error::invalid_argument(EMETADATA_MISMATCH), + error::invalid_argument(EMETADATA_MISMATCH) ); assert!( dst_unbonding.validator == source_unbonding.validator, - error::invalid_argument(EVALIDATOR_MISMATCH), + error::invalid_argument(EVALIDATOR_MISMATCH) ); assert!( dst_unbonding.release_time >= source_unbonding.release_time, - error::invalid_argument(ERELEASE_TIME), + error::invalid_argument(ERELEASE_TIME) ); - spec { - assume dst_unbonding.unbonding_share + source_unbonding.unbonding_share - <= MAX_U64; - }; - - dst_unbonding.unbonding_share = dst_unbonding.unbonding_share - + source_unbonding.unbonding_share; + dst_unbonding.unbonding_share = bigdecimal::add( + dst_unbonding.unbonding_share, source_unbonding.unbonding_share + ); let Unbonding { metadata: _, validator: _, unbonding_share: _, release_time: _ } = source_unbonding; } @@ -1549,7 +1546,7 @@ module initia_std::staking { let (_, timestamp) = block::get_block_info(); assert!( unbonding.release_time <= timestamp, - error::invalid_state(ENOT_RELEASED), + error::invalid_state(ENOT_RELEASED) ); let unbonding_amount = get_unbonding_amount_from_unbonding(&unbonding); @@ -1562,7 +1559,7 @@ module initia_std::staking { load_staking_state_mut( &mut module_store.staking_states, metadata, - validator, + validator ); let unbonding_coin = if (unbonding_amount == 0) { @@ -1575,12 +1572,14 @@ module initia_std::staking { fungible_asset::withdraw( unbonding_coin_store_signer, state.unbonding_coin_store, - unbonding_amount, + unbonding_amount ) }; // decrease share - state.unbonding_share = state.unbonding_share - (unbonding.unbonding_share as u128); + state.unbonding_share = bigdecimal::sub( + state.unbonding_share, unbonding.unbonding_share + ); // destroy empty let Unbonding { metadata: _, validator: _, unbonding_share: _, release_time: _ } = @@ -1592,24 +1591,27 @@ module initia_std::staking { // Native functions native fun delegate_internal( - validator: vector, metadata: &Object, amount: u64, /* share amount */ - ): u64; + validator: vector, metadata: &Object, amount: u64 + ): BigDecimal /* share amount */; native fun undelegate_internal( - validator: vector, metadata: &Object, share: u64 + validator: vector, metadata: &Object, share: &BigDecimal ): (u64 /* unbonding amount */, u64 /* unbond timestamp */); native public fun share_to_amount( - validator: vector, metadata: &Object, share: u64 + validator: vector, metadata: &Object, share: &BigDecimal ): u64 /* delegation amount */; native public fun amount_to_share( validator: vector, metadata: &Object, amount: u64 - ): u64 /* share amount */; + ): BigDecimal /* share amount */; #[test_only] native public fun set_staking_share_ratio( - validator: vector, metadata: &Object, share: u64, amount: u64 + validator: vector, + metadata: &Object, + share: &BigDecimal, + amount: u64 ); #[test_only] @@ -1655,13 +1657,13 @@ module initia_std::staking { string::utf8(STAKING_SYMBOL), 6, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); coin::mint_to( &mint_cap, chain_addr, - 100000000000000, + 100000000000000 ); // initialize reward coin @@ -1673,13 +1675,13 @@ module initia_std::staking { string::utf8(REWARD_SYMBOL), 6, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); coin::mint_to( &mint_cap, chain_addr, - 100000000000000, + 100000000000000 ); initialize_for_chain(chain, staking_metadata_for_test()); @@ -1694,8 +1696,8 @@ module initia_std::staking { coin::withdraw( chain, staking_metadata_for_test(), - amount, - ), + amount + ) ); } @@ -1705,15 +1707,13 @@ module initia_std::staking { ) { coin::deposit( receiver, - coin::withdraw(chain, reward_metadata(), amount), + coin::withdraw(chain, reward_metadata(), amount) ); } #[test(chain = @0x1, user1 = @0x1234, user2 = @0x4321)] fun end_to_end( - chain: &signer, - user1: &signer, - user2: &signer, + chain: &signer, user1: &signer, user2: &signer ) acquires DelegationStore, ModuleStore { test_setup(); @@ -1733,20 +1733,20 @@ module initia_std::staking { set_staking_share_ratio( *string::bytes(&validator), &metadata, - 1, - 1, + &bigdecimal::one(), + 1 ); delegate_script(user1, metadata, validator, 10000000); assert!( coin::balance(user1_addr, metadata) == 990000000, - 0, + 0 ); let delegation = get_delegation(user1_addr, metadata, validator); assert!(delegation.validator == validator, 1); - assert!(delegation.share == 10000000, 2); + assert!(bigdecimal::truncate_u64(delegation.share) == 10000000, 2); assert!(delegation.unclaimed_reward == 0, 3); fund_reward_coin(chain, @relayer, 1000000); @@ -1754,15 +1754,19 @@ module initia_std::staking { chain, metadata, vector[validator], - vector[1000000], + vector[1000000] ); let delegation = get_delegation(user1_addr, metadata, validator); assert!(delegation.unclaimed_reward == 1000000, 4); - let withdrawn_delegation = withdraw_delegation( - user1, metadata, validator, 5000000 - ); + let withdrawn_delegation = + withdraw_delegation( + user1, + metadata, + validator, + bigdecimal::from_ratio_u64(5000000, 1) + ); let reward = deposit_delegation(user2_addr, withdrawn_delegation); assert!(fungible_asset::amount(&reward) == 500000, 5); coin::deposit(user1_addr, reward); @@ -1773,7 +1777,7 @@ module initia_std::staking { claim_reward_script(user1, metadata, validator); assert!( coin::balance(user1_addr, reward_metadata) == 1000000, - 8, + 8 ); let delegation = get_delegation(user1_addr, metadata, validator); assert!(delegation.unclaimed_reward == 0, 8); @@ -1783,7 +1787,7 @@ module initia_std::staking { chain, metadata, vector[validator], - vector[1000000], + vector[1000000] ); let delegation = get_delegation(user1_addr, metadata, validator); assert!(delegation.unclaimed_reward == 500000, 9); @@ -1791,7 +1795,7 @@ module initia_std::staking { undelegate_script(user1, metadata, validator, 5000000); assert!( coin::balance(user1_addr, reward_metadata) == 1500000, - 10, + 10 ); // undelegate trigger `deposit_unbonding_coin_for_chain` @@ -1799,7 +1803,7 @@ module initia_std::staking { chain, metadata, vector[validator], - vector[5000000], + vector[5000000] ); let unbondings = @@ -1808,7 +1812,7 @@ module initia_std::staking { metadata, option::none(), option::none(), - 1, + 1 ); let unbonding = vector::borrow(&unbondings, 0); @@ -1818,7 +1822,7 @@ module initia_std::staking { metadata, validator, unbonding.release_time, - 2500000, + 2500000 ); deposit_unbonding(user2_addr, withdrawn_unbonding); @@ -1828,7 +1832,7 @@ module initia_std::staking { user1_addr, metadata, validator, - unbonding.release_time, + unbonding.release_time ); assert!(unbonding.unbonding_amount == 2500000, 11); let unbonding = @@ -1836,7 +1840,7 @@ module initia_std::staking { user2_addr, metadata, validator, - unbonding.release_time, + unbonding.release_time ); assert!(unbonding.unbonding_amount == 2500000, 12); @@ -1846,16 +1850,16 @@ module initia_std::staking { user1, metadata, validator, - unbonding.release_time, + unbonding.release_time ); assert!( coin::balance(user1_addr, metadata) == 992500000, - 13, + 13 ); } #[test(chain = @0x1, user = @0x1234)] - public fun test_delegate(chain: &signer, user: &signer,) acquires DelegationStore, ModuleStore { + public fun test_delegate2(chain: &signer, user: &signer) acquires DelegationStore, ModuleStore { test_setup(); let user_addr = signer::address_of(user); @@ -1872,69 +1876,85 @@ module initia_std::staking { set_staking_share_ratio( *string::bytes(&validator), &metadata, - 1, - 1, + &bigdecimal::from_u64(3), + 2 ); // Delegate with entry function delegate_script(user, metadata, validator, 100000); let delegation = get_delegation(user_addr, metadata, validator); - assert!(delegation.share == 100000, 0); + assert!(bigdecimal::truncate_u64(delegation.share) == 150000, 0); assert!(delegation.validator == validator, 1); assert!( coin::balance(user_addr, metadata) == 900000, - 2, + 2 ); // withdraw delegation - let delegation0 = withdraw_delegation(user, metadata, validator, 50000); + let delegation0 = + withdraw_delegation( + user, + metadata, + validator, + bigdecimal::from_ratio_u64(50000, 1) + ); let delegation = get_delegation(user_addr, metadata, validator); - assert!(delegation.share == 50000, 3); + assert!(bigdecimal::truncate_u64(delegation.share) == 100000, 3); // withdraw all of rest delegation - let delegation1 = withdraw_delegation(user, metadata, validator, 50000); + let delegation1 = + withdraw_delegation( + user, + metadata, + validator, + bigdecimal::from_ratio_u64(50000, 1) + ); let delegations = get_delegations( user_addr, metadata, option::none(), - 1, + 1 + ); + assert!(vector::length(&delegations) == 1, 4); + assert!( + bigdecimal::truncate_u64(vector::borrow(&delegations, 0).share) == 50000, 4 ); - assert!(vector::length(&delegations) == 0, 4); fund_reward_coin(chain, @relayer, 100000); deposit_reward_for_chain( chain, metadata, vector[validator], - vector[100000], + vector[100000] ); // deposit delegation let reward = deposit_delegation(user_addr, delegation0); - assert!(fungible_asset::amount(&reward) == 50000, 5); + assert!(fungible_asset::amount(&reward) == 66666, 5); let delegation = get_delegation(user_addr, metadata, validator); - assert!(delegation.share == 50000, 6); + assert!(bigdecimal::truncate_u64(delegation.share) == 100000, 6); assert!(delegation.validator == validator, 7); coin::deposit(user_addr, reward); // extract delegation - let delegation2 = extract_delegation(&mut delegation1, 10000); - assert!(delegation1.share == 40000, 8); - assert!(delegation2.share == 10000, 9); + let delegation2 = + extract_delegation(&mut delegation1, bigdecimal::from_ratio_u64(10000, 1)); + assert!(bigdecimal::truncate_u64(delegation1.share) == 40000, 8); + assert!(bigdecimal::truncate_u64(delegation2.share) == 10000, 9); // merge delegation let reward = merge_delegation(&mut delegation1, delegation2); - assert!(fungible_asset::amount(&reward) == 50000, 13); - assert!(delegation1.share == 50000, 14); + assert!(fungible_asset::amount(&reward) == 33332, 13); + assert!(bigdecimal::truncate_u64(delegation1.share) == 50000, 14); coin::deposit(user_addr, reward); // delegate let coin = coin::withdraw(user, metadata, 100000); let delegation3 = delegate(validator, coin); - assert!(delegation3.share == 100000, 12); + assert!(bigdecimal::truncate_u64(delegation3.share) == 150000, 12); let reward = merge_delegation(&mut delegation1, delegation3); fungible_asset::destroy_zero(reward); @@ -1943,22 +1963,22 @@ module initia_std::staking { fungible_asset::destroy_zero(reward); // 1000000 (mint) - 100000 (delegate_script) - 100000 (delegate) - // 100000 (rewards) + // 99998 (rewards) assert!( coin::balance(user_addr, metadata) == 800000, - 16, + 16 ); assert!( - coin::balance(user_addr, reward_metadata) == 100000, - 17, + coin::balance(user_addr, reward_metadata) == 99998, + 17 ); let delegation = get_delegation(user_addr, metadata, validator); - assert!(delegation.share == 200000, 6); + assert!(bigdecimal::truncate_u64(delegation.share) == 300000, 6); } #[test(chain = @0x1, user = @0x1234)] - public fun test_undelegate(chain: &signer, user: &signer,) acquires DelegationStore, ModuleStore { + public fun test_undelegate(chain: &signer, user: &signer) acquires DelegationStore, ModuleStore { test_setup(); let user_addr = signer::address_of(user); @@ -1975,8 +1995,8 @@ module initia_std::staking { set_staking_share_ratio( *string::bytes(&validator), &metadata, - 1, - 1, + &bigdecimal::from_u64(1), + 1 ); delegate_script(user, metadata, validator, 100000); @@ -1986,7 +2006,7 @@ module initia_std::staking { chain, metadata, vector[validator], - vector[100000], + vector[100000] ); // undelegate with script @@ -1997,11 +2017,11 @@ module initia_std::staking { chain, metadata, vector[validator], - vector[10000], + vector[10000] ); let delegation = get_delegation(user_addr, metadata, validator); - assert!(delegation.share == 90000, 0); + assert!(bigdecimal::truncate_u64(delegation.share) == 90000, 0); let unbondings = get_unbondings( @@ -2009,18 +2029,18 @@ module initia_std::staking { metadata, option::none(), option::none(), - 1, + 1 ); let unbonding = vector::borrow(&unbondings, 0); let release_time = unbonding.release_time; assert!(unbonding.unbonding_amount == 10000, 1); assert!( coin::balance(user_addr, metadata) == 900000, - 2, + 2 ); assert!( coin::balance(user_addr, reward_metadata) == 10000, - 3, + 3 ); // distribute reward @@ -2029,37 +2049,44 @@ module initia_std::staking { chain, metadata, vector[validator], - vector[90000], + vector[90000] ); // undelegate - let delegation = withdraw_delegation(user, metadata, validator, 10000); + let delegation = + withdraw_delegation( + user, + metadata, + validator, + bigdecimal::from_ratio_u64(10000, 1) + ); let (reward, unbonding0) = undelegate(delegation); assert!(fungible_asset::amount(&reward) == 20000, 4); - assert!(unbonding0.unbonding_share == 10000, 5); + assert!(bigdecimal::truncate_u64(unbonding0.unbonding_share) == 10000, 5); // undelegate trigger `deposit_unbonding_coin_for_chain` deposit_unbonding_coin_for_chain( chain, metadata, vector[validator], - vector[10000], + vector[10000] ); coin::deposit(user_addr, reward); assert!( coin::balance(user_addr, reward_metadata) == 30000, - 3, + 3 ); // extract unbonding - let unbonding1 = extract_unbonding(&mut unbonding0, 5000); - assert!(unbonding0.unbonding_share == 5000, 7); - assert!(unbonding1.unbonding_share == 5000, 8); + let unbonding1 = + extract_unbonding(&mut unbonding0, bigdecimal::from_ratio_u64(5000, 1)); + assert!(bigdecimal::truncate_u64(unbonding0.unbonding_share) == 5000, 7); + assert!(bigdecimal::truncate_u64(unbonding1.unbonding_share) == 5000, 8); // merge unbonding merge_unbonding(&mut unbonding0, unbonding1); - assert!(unbonding0.unbonding_share == 10000, 9); + assert!(bigdecimal::truncate_u64(unbonding0.unbonding_share) == 10000, 9); // deposit unbonding deposit_unbonding(user_addr, unbonding0); @@ -2067,7 +2094,7 @@ module initia_std::staking { user_addr, metadata, validator, - release_time, + release_time ); assert!(unbonding.unbonding_amount == 20000, 10); @@ -2077,9 +2104,9 @@ module initia_std::staking { metadata, validator, release_time, - 10000, + 10000 ); - assert!(unbonding.unbonding_share == 10000, 11); + assert!(bigdecimal::truncate_u64(unbonding.unbonding_share) == 10000, 11); // claim unbonding set_block_info(200, release_time); @@ -2092,19 +2119,17 @@ module initia_std::staking { user, metadata, validator, - release_time, + release_time ); assert!( coin::balance(user_addr, metadata) == 920000, - 13, + 13 ); } #[test(chain = @0x1, user1 = @0x1234, user2 = @0x4321)] fun test_claim_reward( - chain: &signer, - user1: &signer, - user2: &signer, + chain: &signer, user1: &signer, user2: &signer ) acquires DelegationStore, ModuleStore { test_setup(); @@ -2127,15 +2152,15 @@ module initia_std::staking { set_staking_share_ratio( *string::bytes(&validator), &metadata, - 1, - 1, + &bigdecimal::from_u64(1), + 1 ); delegate_script( user1, metadata, string::utf8(b"validator"), - 1000000, + 1000000 ); fund_reward_coin(chain, @relayer, 100000); @@ -2143,14 +2168,14 @@ module initia_std::staking { chain, metadata, vector[validator], - vector[100000], + vector[100000] ); // claim reward by script claim_reward_script(user1, metadata, validator); assert!( coin::balance(user1_addr, reward_metadata) == 100000, - 0, + 0 ); fund_reward_coin(chain, @relayer, 100000); @@ -2158,11 +2183,17 @@ module initia_std::staking { chain, metadata, vector[validator], - vector[100000], + vector[100000] ); // claim reward - let delegation = withdraw_delegation(user1, metadata, validator, 1000000); + let delegation = + withdraw_delegation( + user1, + metadata, + validator, + bigdecimal::from_ratio_u64(1000000, 1) + ); let reward = claim_reward(&mut delegation); assert!(fungible_asset::amount(&reward) == 100000, 1); coin::deposit(user1_addr, reward); @@ -2173,14 +2204,14 @@ module initia_std::staking { assert!( coin::balance(user1_addr, reward_metadata) == 200000, - 3, + 3 ); delegate_script( user2, metadata, string::utf8(b"validator"), - 1000000, + 1000000 ); fund_reward_coin(chain, @relayer, 100000); @@ -2188,25 +2219,25 @@ module initia_std::staking { chain, metadata, vector[validator], - vector[100000], + vector[100000] ); claim_reward_script(user1, metadata, validator); assert!( coin::balance(user1_addr, reward_metadata) == 250000, - 4, + 4 ); } #[test] #[expected_failure(abort_code = 0x10007, location = Self)] - public fun test_destroy_not_empty_delegation() acquires ModuleStore { + public fun test_staking_destroy_not_empty_delegation() acquires ModuleStore { test_setup(); let delegation = Delegation { metadata: staking_metadata_for_test(), validator: string::utf8(b"validator"), - reward_index: decimal128::zero(), - share: 100, + reward_index: bigdecimal::zero(), + share: bigdecimal::from_ratio_u64(100, 1) }; destroy_empty_delegation(delegation); @@ -2214,14 +2245,14 @@ module initia_std::staking { #[test] #[expected_failure(abort_code = 0x10007, location = Self)] - public fun test_destroy_not_empty_unbonding() acquires ModuleStore { + public fun test_staking_destroy_not_empty_unbonding() acquires ModuleStore { test_setup(); let unbonding = Unbonding { metadata: staking_metadata_for_test(), validator: string::utf8(b"validator"), - unbonding_share: 100, - release_time: 1234, + unbonding_share: bigdecimal::from_ratio_u64(100, 1), + release_time: 1234 }; destroy_empty_unbonding(unbonding); @@ -2229,21 +2260,21 @@ module initia_std::staking { #[test] #[expected_failure(abort_code = 0x10008, location = Self)] - public fun test_merge_delegation_validator_mistmatch() acquires ModuleStore { + public fun test_staking_merge_delegation_validator_mistmatch() acquires ModuleStore { test_setup(); let delegation1 = Delegation { metadata: staking_metadata_for_test(), validator: string::utf8(b"validator1"), - reward_index: decimal128::zero(), - share: 100, + reward_index: bigdecimal::zero(), + share: bigdecimal::from_ratio_u64(100, 1) }; let delegation2 = Delegation { metadata: staking_metadata_for_test(), validator: string::utf8(b"validator2"), - reward_index: decimal128::zero(), - share: 100, + reward_index: bigdecimal::zero(), + share: bigdecimal::from_ratio_u64(100, 1) }; let reward = merge_delegation(&mut delegation1, delegation2); @@ -2254,35 +2285,35 @@ module initia_std::staking { #[test] #[expected_failure(abort_code = 0x10009, location = Self)] - public fun test_merge_unbonding_release_time() acquires ModuleStore { + public fun test_staking_merge_unbonding_release_time() acquires ModuleStore { test_setup(); let validator = string::utf8(b"validator"); let unbonding1 = Unbonding { metadata: staking_metadata_for_test(), validator, - unbonding_share: 100, - release_time: 1000, + unbonding_share: bigdecimal::from_ratio_u64(100, 1), + release_time: 1000 }; let unbonding2 = Unbonding { metadata: staking_metadata_for_test(), validator, - unbonding_share: 100, - release_time: 1234, + unbonding_share: bigdecimal::from_ratio_u64(100, 1), + release_time: 1234 }; merge_unbonding(&mut unbonding1, unbonding2); let Unbonding { metadata: _, validator: _, unbonding_share, release_time: _ } = unbonding1; - assert!(unbonding_share == 200, 1); + assert!(bigdecimal::truncate_u64(unbonding_share) == 200, 1); } #[test(chain = @0x1, user = @0x1234)] #[expected_failure(abort_code = 0x3000A, location = Self)] - public fun test_claim_not_released_unbonding( - chain: &signer, user: &signer, + public fun test_staking_claim_not_released_unbonding( + chain: &signer, user: &signer ) acquires ModuleStore, DelegationStore { test_setup(); @@ -2297,8 +2328,8 @@ module initia_std::staking { set_staking_share_ratio( *string::bytes(&validator), &metadata, - 1, - 1, + &bigdecimal::from_u64(1), + 1 ); // dummy delegation to create global states @@ -2309,7 +2340,7 @@ module initia_std::staking { chain, metadata, vector[validator], - vector[100], + vector[100] ); set_block_info(100, 100); @@ -2317,8 +2348,8 @@ module initia_std::staking { let unbonding = Unbonding { metadata, validator, - unbonding_share: 100, - release_time: 1000, + unbonding_share: bigdecimal::from_ratio_u64(100, 1), + release_time: 1000 }; let coin = claim_unbonding(unbonding); @@ -2328,7 +2359,9 @@ module initia_std::staking { } #[test(chain = @0x1, user = @0x1234)] - public fun test_query_entry_functions(chain: &signer, user: &signer,) acquires DelegationStore, ModuleStore { + public fun test_staking_query_entry_functions( + chain: &signer, user: &signer + ) acquires DelegationStore, ModuleStore { test_setup(); let user_addr = signer::address_of(user); @@ -2345,14 +2378,14 @@ module initia_std::staking { set_staking_share_ratio( *string::bytes(&validator1), &metadata, - 1, - 1, + &bigdecimal::from_u64(1), + 1 ); set_staking_share_ratio( *string::bytes(&validator2), &metadata, - 1, - 1, + &bigdecimal::from_u64(1), + 1 ); delegate_script(user, metadata, validator1, 100000); @@ -2366,7 +2399,7 @@ module initia_std::staking { chain, metadata, vector[validator1, validator2], - vector[10000, 10000], + vector[10000, 10000] ); // update block info @@ -2379,7 +2412,7 @@ module initia_std::staking { chain, metadata, vector[validator1], - vector[10000], + vector[10000] ); let delegation = get_delegation(user_addr, metadata, validator1); @@ -2388,17 +2421,17 @@ module initia_std::staking { == DelegationResponse { metadata, validator: validator1, - share: 80000, - unclaimed_reward: 0, + share: bigdecimal::from_ratio_u64(80000, 1), + unclaimed_reward: 0 }, - 0, + 0 ); let delegations = get_delegations( user_addr, metadata, option::none(), - 10, + 10 ); assert!( delegations @@ -2406,42 +2439,43 @@ module initia_std::staking { DelegationResponse { metadata, validator: validator2, - share: 90000, - unclaimed_reward: 0, + share: bigdecimal::from_ratio_u64(90000, 1), + unclaimed_reward: 0 }, DelegationResponse { metadata, validator: validator1, - share: 80000, - unclaimed_reward: 0, - },], - 1, + share: bigdecimal::from_ratio_u64(80000, 1), + unclaimed_reward: 0 + } + ], + 1 ); - let delegations = - get_delegations( - user_addr, - metadata, - option::some(validator2), - 10, - ); + let delegations = get_delegations( + user_addr, + metadata, + option::some(validator2), + 10 + ); assert!( delegations == vector[ DelegationResponse { metadata, validator: validator1, - share: 80000, - unclaimed_reward: 0, - },], - 2, + share: bigdecimal::from_ratio_u64(80000, 1), + unclaimed_reward: 0 + } + ], + 2 ); let unbonding = get_unbonding( user_addr, metadata, validator1, - 10000 + 7 * 24 * 60 * 60, + 10000 + 7 * 24 * 60 * 60 ); assert!( unbonding @@ -2449,9 +2483,9 @@ module initia_std::staking { metadata, validator: validator1, unbonding_amount: 10000, - release_time: 10000 + 7 * 24 * 60 * 60, + release_time: 10000 + 7 * 24 * 60 * 60 }, - 3, + 3 ); let unbondings = @@ -2460,7 +2494,7 @@ module initia_std::staking { metadata, option::none(), option::none(), - 10, + 10 ); assert!( unbondings @@ -2469,21 +2503,22 @@ module initia_std::staking { metadata, validator: validator2, unbonding_amount: 10000, - release_time: 10000 + 7 * 24 * 60 * 60, + release_time: 10000 + 7 * 24 * 60 * 60 }, UnbondingResponse { metadata, validator: validator1, unbonding_amount: 10000, - release_time: 20000 + 7 * 24 * 60 * 60, + release_time: 20000 + 7 * 24 * 60 * 60 }, UnbondingResponse { metadata, validator: validator1, unbonding_amount: 10000, - release_time: 10000 + 7 * 24 * 60 * 60, - },], - 4, + release_time: 10000 + 7 * 24 * 60 * 60 + } + ], + 4 ); let unbondings = @@ -2492,7 +2527,7 @@ module initia_std::staking { metadata, option::some(validator1), option::some(20000 + 7 * 24 * 60 * 60), - 10, + 10 ); assert!( unbondings @@ -2501,38 +2536,46 @@ module initia_std::staking { metadata, validator: validator1, unbonding_amount: 10000, - release_time: 10000 + 7 * 24 * 60 * 60, - },], - 5, + release_time: 10000 + 7 * 24 * 60 * 60 + } + ], + 5 ); } #[test] - public fun test_share_to_amount() acquires ModuleStore { + public fun test_staking_share_to_amount() acquires ModuleStore { test_setup(); let metadata = staking_metadata_for_test(); let validator = vector::singleton(1u8); - set_staking_share_ratio(validator, &metadata, 100u64, 50u64); + set_staking_share_ratio(validator, &metadata, &bigdecimal::from_u64(100), 50u64); - let amount = share_to_amount(vector::singleton(1u8), &metadata, 2); + let amount = + share_to_amount( + vector::singleton(1u8), + &metadata, + &bigdecimal::from_ratio_u64(2, 1) + ); assert!(amount == 1u64, 0); } #[test] - public fun test_amount_to_share() acquires ModuleStore { + public fun test_staking_amount_to_share() acquires ModuleStore { test_setup(); let metadata = staking_metadata_for_test(); let validator = vector::singleton(1u8); - set_staking_share_ratio(validator, &metadata, 100u64, 50u64); + set_staking_share_ratio(validator, &metadata, &bigdecimal::from_u64(100), 50u64); let share = amount_to_share(validator, &metadata, 1); - assert!(share == 2u64, 0); + assert!(bigdecimal::truncate_u64(share) == 2u64, 0); } #[test(chain = @0x1, user = @0x1234)] - public fun test_slash_unbonding(chain: &signer, user: &signer,) acquires DelegationStore, ModuleStore { + public fun test_staking_slash_unbonding( + chain: &signer, user: &signer + ) acquires DelegationStore, ModuleStore { test_setup(); let user_addr = signer::address_of(user); @@ -2546,8 +2589,8 @@ module initia_std::staking { set_staking_share_ratio( *string::bytes(&validator), &metadata, - 1, - 1, + &bigdecimal::from_u64(1), + 1 ); register(user); @@ -2559,13 +2602,13 @@ module initia_std::staking { chain, metadata, vector[validator], - vector[10000], + vector[10000] ); slash_unbonding_for_chain( chain, metadata, validator, - string::utf8(b"0.1"), + bigdecimal::from_ratio_u64(1, 10) ); // 10% let unbonding_response = @@ -2573,11 +2616,11 @@ module initia_std::staking { user_addr, metadata, validator, - 10000 + 7 * 24 * 60 * 60, + 10000 + 7 * 24 * 60 * 60 ); assert!( unbonding_response.unbonding_amount == 9000, - 1, + 1 ); } } diff --git a/initia_stdlib/sources/string_utils.move b/initia_stdlib/sources/string_utils.move index 0909c52..d29064e 100644 --- a/initia_stdlib/sources/string_utils.move +++ b/initia_stdlib/sources/string_utils.move @@ -63,7 +63,7 @@ module initia_std::string_utils { // Helper struct to allow passing a generic heterogeneous list of values to native_format_list. struct Cons has copy, drop, store { car: T, - cdr: N, + cdr: N } struct NIL has copy, drop, store {} @@ -81,15 +81,18 @@ module initia_std::string_utils { // Create a list of values. inline fun list1(a: T0): Cons { cons(a, nil()) - } inline fun list2(a: T0, b: T1): Cons> { + } + inline fun list2(a: T0, b: T1): Cons> { cons(a, list1(b)) - } inline fun list3(a: T0, b: T1, c: T2): Cons>> { + } + inline fun list3(a: T0, b: T1, c: T2): Cons>> { cons(a, list2(b, c)) - } inline fun list4(a: T0, b: T1, c: T2, d: T3) + } - : Cons>>> { + inline fun list4(a: T0, b: T1, c: T2, d: T3): + Cons>>> { cons(a, list3(b, c, d)) } @@ -107,32 +110,32 @@ module initia_std::string_utils { fun test_format() { assert!( to_string(&1u64) == std::string::utf8(b"1"), - 1, + 1 ); assert!( to_string(&false) == std::string::utf8(b"false"), - 2, + 2 ); assert!( to_string(&1u256) == std::string::utf8(b"1"), - 3, + 3 ); assert!( to_string(&vector[1, 2, 3]) == std::string::utf8(b"[ 1, 2, 3 ]"), - 4, + 4 ); assert!( to_string(&cons(std::string::utf8(b"My string"), 2)) == std::string::utf8(b"Cons { car: \"My string\", cdr: 2 }"), - 5, + 5 ); assert!( to_string(&std::option::none()) == std::string::utf8(b"None"), - 6, + 6 ); assert!( to_string(&std::option::some(1)) == std::string::utf8(b"Some(1)"), - 7, + 7 ); } @@ -142,11 +145,11 @@ module initia_std::string_utils { &b"a = {} b = {} c = {}", 1, 2, - std::string::utf8(b"My string"), + std::string::utf8(b"My string") ); assert!( s == std::string::utf8(b"a = 1 b = 2 c = \"My string\""), - 1, + 1 ); } @@ -172,7 +175,7 @@ module initia_std::string_utils { /// #[test_only] struct FakeCons has copy, drop, store { car: T, - cdr: N, + cdr: N } #[test] @@ -205,7 +208,7 @@ module initia_std::string_utils { let s = format3(&b"{{a = {} b = {} c = {}}}", 1, 2, 3); assert!( s == std::string::utf8(b"{a = 1 b = 2 c = 3}"), - 1, + 1 ); } } diff --git a/initia_stdlib/sources/table.move b/initia_stdlib/sources/table.move index ca5056f..7b220c1 100644 --- a/initia_stdlib/sources/table.move +++ b/initia_stdlib/sources/table.move @@ -15,26 +15,26 @@ module initia_std::table { /// Type of tables struct Table has store { handle: address, - length: u64, + length: u64 } /// Type of table iterators struct TableIter has drop { - iterator_id: u64, + iterator_id: u64 } /// Create a new Table. public fun new(): Table { let handle = new_table_handle(); account::create_table_account(handle); - Table { handle, length: 0, } + Table { handle, length: 0 } } /// Destroy a table. The table must be empty to succeed. public fun destroy_empty(table: Table) { assert!( table.length == 0, - error::invalid_state(ENOT_EMPTY), + error::invalid_state(ENOT_EMPTY) ); destroy_empty_box>(&table); drop_unchecked_box>(table) @@ -155,7 +155,7 @@ module initia_std::table { table: &Table, start: Option, /* inclusive */ end: Option, /* exclusive */ - order: u8 /* 1: Ascending, 2: Descending */, + order: u8 /* 1: Ascending, 2: Descending */ ): &TableIter { let start_bytes: vector = if (option::is_some(&start)) { @@ -186,13 +186,13 @@ module initia_std::table { /// Create mutable iterator for `table`. /// A user has to check `prepare` before calling `next` to prevent abort. /// - /// let iter = table::iter_mut(&t, start, end, order); + /// let iter = table::iter_mut(&mut t, start, end, order); /// loop { - /// if (!table::prepare_mut(&mut iter)) { + /// if (!table::prepare_mut(iter)) { /// break; /// } /// - /// let (key, value) = table::next_mut(&mut iter); + /// let (key, value) = table::next_mut(iter); /// } /// /// NOTE: The default BCS number encoding follows the Little Endian method. @@ -204,7 +204,7 @@ module initia_std::table { table: &mut Table, start: Option, /* inclusive */ end: Option, /* exclusive */ - order: u8 /* 1: Ascending, 2: Descending */, + order: u8 /* 1: Ascending, 2: Descending */ ): &mut TableIter { let start_bytes: vector = if (option::is_some(&start)) { @@ -246,35 +246,51 @@ module initia_std::table { // can use this to determine serialization layout. native fun new_table_handle(): address; - native fun add_box(table: &mut Table, key: K, val: Box); + native fun add_box( + table: &mut Table, key: K, val: Box + ); native fun borrow_box(table: &Table, key: K): &Box; - native fun borrow_box_mut(table: &mut Table, key: K): &mut Box; + native fun borrow_box_mut( + table: &mut Table, key: K + ): &mut Box; native fun contains_box(table: &Table, key: K): bool; - native fun remove_box(table: &mut Table, key: K): Box; + native fun remove_box( + table: &mut Table, key: K + ): Box; native fun destroy_empty_box(table: &Table); native fun drop_unchecked_box(table: Table); native fun new_table_iter( - table: &Table, start: vector, end: vector, order: u8 + table: &Table, + start: vector, + end: vector, + order: u8 ): &TableIter; native fun new_table_iter_mut( - table: &mut Table, start: vector, end: vector, order: u8 + table: &mut Table, + start: vector, + end: vector, + order: u8 ): &mut TableIter; native fun next_box(table_iter: &TableIter): (K, &Box); native fun prepare_box(table_iter: &TableIter): bool; - native fun next_box_mut(table_iter: &mut TableIter): (K, &mut Box); + native fun next_box_mut( + table_iter: &mut TableIter + ): (K, &mut Box); - native fun prepare_box_mut(table_iter: &mut TableIter): bool; + native fun prepare_box_mut( + table_iter: &mut TableIter + ): bool; // ====================================================================================================== // Tests @@ -306,12 +322,12 @@ module initia_std::table { assert!(!contains(&t, key), error_code); assert!( *borrow_with_default(&t, key, &12) == 12, - error_code, + error_code ); add(&mut t, key, 1); assert!( *borrow_with_default(&t, key, &12) == 1, - error_code, + error_code ); move_to(&account, TableHolder { t }); diff --git a/initia_stdlib/sources/token/collection.move b/initia_stdlib/sources/token/collection.move index 594d82f..0803ad1 100644 --- a/initia_stdlib/sources/token/collection.move +++ b/initia_stdlib/sources/token/collection.move @@ -62,12 +62,12 @@ module initia_std::collection { /// storage; the URL length will likely need a maximum any suggestions? uri: String, /// index to object map. - nfts: Table, + nfts: Table } /// This enables mutating description and URI by higher level services. struct MutatorRef has drop, store { - self: address, + self: address } #[event] @@ -86,39 +86,39 @@ module initia_std::collection { /// Total minted - total burned current_supply: u64, max_supply: u64, - total_minted: u64, + total_minted: u64 } /// Unlimited supply tracker, this is useful for adding events and supply tracking to a collection. struct UnlimitedSupply has key { current_supply: u64, - total_minted: u64, + total_minted: u64 } struct NftResponse has drop { token_id: String, - nft: address, + nft: address } #[event] struct CreateCollectionEvent has drop, store { collection: address, creator: address, - name: String, + name: String } #[event] struct BurnEvent has drop, store { collection: address, token_id: String, - nft: address, + nft: address } #[event] struct MintEvent has drop, store { collection: address, token_id: String, - nft: address, + nft: address } /// Creates a fixed-sized collection, or a collection that supports a fixed amount of nfts. @@ -132,16 +132,16 @@ module initia_std::collection { max_supply: u64, name: String, royalty: Option, - uri: String, + uri: String ): ConstructorRef { assert!( max_supply != 0, - error::invalid_argument(EMAX_SUPPLY_CANNOT_BE_ZERO), + error::invalid_argument(EMAX_SUPPLY_CANNOT_BE_ZERO) ); let collection_seed = create_collection_seed(&name); let constructor_ref = object::create_named_object(creator, collection_seed); - let supply = FixedSupply { current_supply: 0, max_supply, total_minted: 0, }; + let supply = FixedSupply { current_supply: 0, max_supply, total_minted: 0 }; create_collection_internal( creator, @@ -150,7 +150,7 @@ module initia_std::collection { name, royalty, uri, - option::some(supply), + option::some(supply) ) } @@ -161,12 +161,12 @@ module initia_std::collection { description: String, name: String, royalty: Option, - uri: String, + uri: String ): ConstructorRef { let collection_seed = create_collection_seed(&name); let constructor_ref = object::create_named_object(creator, collection_seed); - let supply = UnlimitedSupply { current_supply: 0, total_minted: 0, }; + let supply = UnlimitedSupply { current_supply: 0, total_minted: 0 }; create_collection_internal( creator, @@ -175,7 +175,7 @@ module initia_std::collection { name, royalty, uri, - option::some(supply), + option::some(supply) ) } @@ -187,7 +187,7 @@ module initia_std::collection { description: String, name: String, royalty: Option, - uri: String, + uri: String ): ConstructorRef { let collection_seed = create_collection_seed(&name); let constructor_ref = object::create_named_object(creator, collection_seed); @@ -199,7 +199,7 @@ module initia_std::collection { name, royalty, uri, - option::none(), + option::none() ) } @@ -207,11 +207,11 @@ module initia_std::collection { let len = string::length(name); assert!( len <= MAX_COLLECTION_NAME_LENGTH, - error::out_of_range(ECOLLECTION_NAME_TOO_LONG), + error::out_of_range(ECOLLECTION_NAME_TOO_LONG) ); assert!( - string::index_of(name, &string::utf8(b"::")) == len, - error::invalid_argument(EINVALID_COLLECTION_NAME), + string::index_of(name, &string::utf8(b":")) == len, + error::invalid_argument(EINVALID_COLLECTION_NAME) ); } @@ -222,17 +222,17 @@ module initia_std::collection { name: String, royalty: Option, uri: String, - supply: Option, + supply: Option ): ConstructorRef { assert_collection_name(&name); assert!( string::length(&uri) <= MAX_URI_LENGTH, - error::out_of_range(EURI_TOO_LONG), + error::out_of_range(EURI_TOO_LONG) ); assert!( string::length(&description) <= MAX_DESCRIPTION_LENGTH, - error::out_of_range(EDESCRIPTION_TOO_LONG), + error::out_of_range(EDESCRIPTION_TOO_LONG) ); let object_signer = &object::generate_signer(&constructor_ref); @@ -243,14 +243,14 @@ module initia_std::collection { description, name, uri, - nfts: table::new(), + nfts: table::new() }; move_to(object_signer, collection); if (option::is_some(&supply)) { move_to( object_signer, - option::destroy_some(supply), + option::destroy_some(supply) ); let collection_addr = signer::address_of(object_signer); event::emit( @@ -258,7 +258,7 @@ module initia_std::collection { collection: collection_addr, creator: creator_addr, name - }, + } ); } else { option::destroy_none(supply) @@ -267,13 +267,10 @@ module initia_std::collection { if (option::is_some(&royalty)) { royalty::init( &constructor_ref, - option::extract(&mut royalty), + option::extract(&mut royalty) ) }; - let transfer_ref = object::generate_transfer_ref(&constructor_ref); - object::disable_ungated_transfer(&transfer_ref); - constructor_ref } @@ -286,16 +283,14 @@ module initia_std::collection { public fun create_collection_seed(name: &String): vector { assert!( string::length(name) <= MAX_COLLECTION_NAME_LENGTH, - error::out_of_range(ECOLLECTION_NAME_TOO_LONG), + error::out_of_range(ECOLLECTION_NAME_TOO_LONG) ); *string::bytes(name) } /// Called by nft on mint to increment supply if there's an appropriate Supply struct. public(friend) fun increment_supply( - collection: Object, - token_id: String, - nft: address, + collection: Object, token_id: String, nft: address ) acquires Collection, FixedSupply, UnlimitedSupply { let collection_addr = object::object_address(&collection); let collection = borrow_global_mut(collection_addr); @@ -305,28 +300,22 @@ module initia_std::collection { supply.total_minted = supply.total_minted + 1; assert!( supply.current_supply <= supply.max_supply, - error::out_of_range(ECOLLECTION_SUPPLY_EXCEEDED), + error::out_of_range(ECOLLECTION_SUPPLY_EXCEEDED) ); table::add(&mut collection.nfts, token_id, nft); - event::emit( - MintEvent { collection: collection_addr, token_id, nft }, - ); + event::emit(MintEvent { collection: collection_addr, token_id, nft }); } else if (exists(collection_addr)) { let supply = borrow_global_mut(collection_addr); supply.current_supply = supply.current_supply + 1; supply.total_minted = supply.total_minted + 1; table::add(&mut collection.nfts, token_id, nft); - event::emit( - MintEvent { collection: collection_addr, token_id, nft }, - ); + event::emit(MintEvent { collection: collection_addr, token_id, nft }); } } /// Called by nft on burn to decrement supply if there's an appropriate Supply struct. public(friend) fun decrement_supply( - collection: Object, - token_id: String, - nft: address, + collection: Object, token_id: String, nft: address ) acquires Collection, FixedSupply, UnlimitedSupply { let collection_addr = object::object_address(&collection); let collection = borrow_global_mut(collection_addr); @@ -334,16 +323,12 @@ module initia_std::collection { let supply = borrow_global_mut(collection_addr); supply.current_supply = supply.current_supply - 1; table::remove(&mut collection.nfts, token_id); - event::emit( - BurnEvent { collection: collection_addr, token_id, nft }, - ); + event::emit(BurnEvent { collection: collection_addr, token_id, nft }); } else if (exists(collection_addr)) { let supply = borrow_global_mut(collection_addr); supply.current_supply = supply.current_supply - 1; table::remove(&mut collection.nfts, token_id); - event::emit( - BurnEvent { collection: collection_addr, token_id, nft }, - ); + event::emit(BurnEvent { collection: collection_addr, token_id, nft }); } } @@ -358,7 +343,7 @@ module initia_std::collection { inline fun check_collection_exists(addr: address) { assert!( exists(addr), - error::not_found(ECOLLECTION_DOES_NOT_EXIST), + error::not_found(ECOLLECTION_DOES_NOT_EXIST) ); } @@ -409,9 +394,7 @@ module initia_std::collection { /// get nft list from collection /// if `start_after` is not none, seach nfts in range (start_after, ...] public fun nfts( - collection: Object, - start_after: Option, - limit: u64, + collection: Object, start_after: Option, limit: u64 ): vector acquires Collection { let collection = borrow(collection); @@ -423,18 +406,18 @@ module initia_std::collection { &collection.nfts, option::none(), start_after, - 2, + 2 ); let res: vector = vector[]; while (table::prepare(nfts_iter) - && vector::length(&res) < (limit as u64)) { + && vector::length(&res) < (limit as u64)) { let (token_id, nft) = table::next(nfts_iter); vector::push_back( &mut res, - NftResponse { token_id, nft: *nft, }, + NftResponse { token_id, nft: *nft } ); }; @@ -457,7 +440,7 @@ module initia_std::collection { ) acquires Collection { assert!( string::length(&description) <= MAX_DESCRIPTION_LENGTH, - error::out_of_range(EDESCRIPTION_TOO_LONG), + error::out_of_range(EDESCRIPTION_TOO_LONG) ); let collection = borrow_mut(mutator_ref); event::emit( @@ -466,7 +449,7 @@ module initia_std::collection { mutated_field_name: string::utf8(b"description"), old_value: collection.description, new_value: description - }, + } ); collection.description = description; } @@ -474,7 +457,7 @@ module initia_std::collection { public fun set_uri(mutator_ref: &MutatorRef, uri: String) acquires Collection { assert!( string::length(&uri) <= MAX_URI_LENGTH, - error::out_of_range(EURI_TOO_LONG), + error::out_of_range(EURI_TOO_LONG) ); let collection = borrow_mut(mutator_ref); event::emit( @@ -483,7 +466,7 @@ module initia_std::collection { mutated_field_name: string::utf8(b"uri"), old_value: collection.uri, new_value: uri - }, + } ); collection.uri = uri; } @@ -491,7 +474,9 @@ module initia_std::collection { // Tests #[test(creator = @0x123)] - fun test_create_mint_burn_for_unlimited(creator: &signer) acquires Collection, FixedSupply, UnlimitedSupply { + fun test_create_mint_burn_for_unlimited( + creator: &signer + ) acquires Collection, FixedSupply, UnlimitedSupply { let creator_address = signer::address_of(creator); let name = string::utf8(b"collection name"); create_unlimited_collection( @@ -499,7 +484,7 @@ module initia_std::collection { string::utf8(b""), name, option::none(), - string::utf8(b""), + string::utf8(b"") ); let collection_address = create_collection_address(creator_address, &name); let collection = object::address_to_object(collection_address); @@ -507,19 +492,21 @@ module initia_std::collection { increment_supply( collection, string::utf8(b"token_id"), - @0x11111, + @0x11111 ); assert!(count(collection) == option::some(1), 0); decrement_supply( collection, string::utf8(b"token_id"), - @0x11112, + @0x11112 ); assert!(count(collection) == option::some(0), 0); } #[test(creator = @0x123)] - fun test_create_mint_burn_for_fixed(creator: &signer) acquires Collection, FixedSupply, UnlimitedSupply { + fun test_create_mint_burn_for_fixed( + creator: &signer + ) acquires Collection, FixedSupply, UnlimitedSupply { let creator_address = signer::address_of(creator); let name = string::utf8(b"collection name"); create_fixed_collection( @@ -528,7 +515,7 @@ module initia_std::collection { 1, name, option::none(), - string::utf8(b""), + string::utf8(b"") ); let collection_address = create_collection_address(creator_address, &name); let collection = object::address_to_object(collection_address); @@ -536,26 +523,19 @@ module initia_std::collection { increment_supply( collection, string::utf8(b"token_id"), - @0x11111, + @0x11111 ); assert!(count(collection) == option::some(1), 0); decrement_supply( collection, string::utf8(b"token_id"), - @0x11112, + @0x11112 ); assert!(count(collection) == option::some(0), 0); } - #[test(creator = @0x123)] - #[expected_failure(abort_code = 0x10007, location = Self)] - fun test_create_collection_with_invalid_name(creator: &signer) { - create_collection_helper(creator, string::utf8(b"collection::hello")); - } - - #[test(creator = @0x123, trader = @0x456)] - #[expected_failure(abort_code = 0x50003, location = initia_std::object)] - entry fun test_create_and_transfer(creator: &signer, trader: &signer) { + #[test(creator = @0x123, receipient = @0x456)] + entry fun test_create_and_transfer(creator: &signer, receipient: &signer) { let creator_address = signer::address_of(creator); let collection_name = string::utf8(b"collection name"); create_collection_helper(creator, collection_name); @@ -566,15 +546,21 @@ module initia_std::collection { ); assert!( object::owner(collection) == creator_address, - 1, + 1 ); object::transfer( creator, collection, - signer::address_of(trader), + signer::address_of(receipient) ); } + #[test(creator = @0x123)] + #[expected_failure(abort_code = 0x10007, location = Self)] + fun test_create_collection_with_invalid_name(creator: &signer) { + create_collection_helper(creator, string::utf8(b"collection::hello")); + } + #[test(creator = @0x123)] #[expected_failure(abort_code = 0x80001, location = initia_std::object)] entry fun test_duplicate_collection(creator: &signer) { @@ -591,8 +577,8 @@ module initia_std::collection { object::address_to_object( create_collection_address( signer::address_of(creator), - &collection_name, - ), + &collection_name + ) ); let mutator_ref = generate_mutator_ref(&constructor_ref); let description = string::utf8(b"no fail"); @@ -610,8 +596,8 @@ module initia_std::collection { object::address_to_object( create_collection_address( signer::address_of(creator), - &collection_name, - ), + &collection_name + ) ); let uri = string::utf8(b"no fail"); assert!(uri != uri(collection), 0); @@ -628,24 +614,24 @@ module initia_std::collection { string::utf8(b""), name, option::none(), - string::utf8(b""), + string::utf8(b"") ); let collection_address = create_collection_address(creator_address, &name); let collection = object::address_to_object(collection_address); increment_supply( collection, string::utf8(b"1"), - @0x001, + @0x001 ); increment_supply( collection, string::utf8(b"2"), - @0x002, + @0x002 ); increment_supply( collection, string::utf8(b"3"), - @0x003, + @0x003 ); let nfts = nfts(collection, option::none(), 5); @@ -654,21 +640,23 @@ module initia_std::collection { == vector[ NftResponse { token_id: string::utf8(b"3"), nft: @0x003 }, NftResponse { token_id: string::utf8(b"2"), nft: @0x002 }, - NftResponse { token_id: string::utf8(b"1"), nft: @0x001 },], - 0, + NftResponse { token_id: string::utf8(b"1"), nft: @0x001 } + ], + 0 ); nfts = nfts( collection, option::some(string::utf8(b"3")), - 5, + 5 ); assert!( nfts == vector[ NftResponse { token_id: string::utf8(b"2"), nft: @0x002 }, - NftResponse { token_id: string::utf8(b"1"), nft: @0x001 },], - 1, + NftResponse { token_id: string::utf8(b"1"), nft: @0x001 } + ], + 1 ) } @@ -679,7 +667,7 @@ module initia_std::collection { string::utf8(b"collection description"), name, option::none(), - string::utf8(b"collection uri"), + string::utf8(b"collection uri") ) } } diff --git a/initia_stdlib/sources/token/initia_nft.move b/initia_stdlib/sources/token/initia_nft.move index b9baa99..eefe1ea 100644 --- a/initia_stdlib/sources/token/initia_nft.move +++ b/initia_stdlib/sources/token/initia_nft.move @@ -13,10 +13,10 @@ module initia_std::initia_nft { use std::string::String; use std::signer; use initia_std::object::{Self, ConstructorRef, ExtendRef, Object}; - use initia_std::collection; + use initia_std::collection::{Self, Collection}; use initia_std::royalty; use initia_std::nft; - use initia_std::decimal128::Decimal128; + use initia_std::bigdecimal::BigDecimal; /// The collection does not exist const ECOLLECTION_DOES_NOT_EXIST: u64 = 1; @@ -44,7 +44,7 @@ module initia_std::initia_nft { /// Determines if the creator can mutate nft descriptions mutable_nft_description: bool, /// Determines if the creator can mutate nft uris - mutable_nft_uri: bool, + mutable_nft_uri: bool } /// Storage state for managing the no-code Nft. @@ -52,7 +52,7 @@ module initia_std::initia_nft { /// Used to burn. burn_ref: Option, /// Used to mutate fields - mutator_ref: Option, + mutator_ref: Option } /// Create a new collection @@ -67,7 +67,7 @@ module initia_std::initia_nft { mutable_uri: bool, mutable_nft_description: bool, mutable_nft_uri: bool, - royalty: Decimal128, + royalty: BigDecimal ) { create_collection_object( creator, @@ -80,7 +80,7 @@ module initia_std::initia_nft { mutable_uri, mutable_nft_description, mutable_nft_uri, - royalty, + royalty ); } @@ -95,7 +95,7 @@ module initia_std::initia_nft { mutable_uri: bool, mutable_nft_description: bool, mutable_nft_uri: bool, - royalty: Decimal128, + royalty: BigDecimal ): (Object, ExtendRef) { let creator_addr = signer::address_of(creator); let royalty = royalty::create(royalty, creator_addr); @@ -107,7 +107,7 @@ module initia_std::initia_nft { option::extract(&mut max_supply), name, option::some(royalty), - uri, + uri ) } else { collection::create_unlimited_collection( @@ -115,7 +115,7 @@ module initia_std::initia_nft { description, name, option::some(royalty), - uri, + uri ) }; @@ -132,7 +132,7 @@ module initia_std::initia_nft { option::some( royalty::generate_mutator_ref( object::generate_extend_ref(&constructor_ref) - ), + ) ) } else { option::none() @@ -146,7 +146,7 @@ module initia_std::initia_nft { mutable_description, mutable_uri, mutable_nft_description, - mutable_nft_uri, + mutable_nft_uri }; move_to(&object_signer, initia_nft_collection); (object::object_from_constructor_ref(&constructor_ref), extend_ref) @@ -160,7 +160,7 @@ module initia_std::initia_nft { token_id: String, uri: String, can_burn: bool, - to: Option
, + to: Option
) acquires InitiaNftCollection { let (nft_object, _) = mint_nft_object( @@ -169,13 +169,13 @@ module initia_std::initia_nft { description, token_id, uri, - can_burn, + can_burn ); if (option::is_some(&to)) { object::transfer( creator, nft_object, - option::extract(&mut to), + option::extract(&mut to) ); } } @@ -187,7 +187,7 @@ module initia_std::initia_nft { description: String, token_id: String, uri: String, - can_burn: bool, + can_burn: bool ): (Object, ExtendRef) acquires InitiaNftCollection { let constructor_ref = mint_internal( @@ -196,7 +196,7 @@ module initia_std::initia_nft { description, token_id, uri, - can_burn, + can_burn ); let extend_ref = object::generate_extend_ref(&constructor_ref); @@ -205,25 +205,24 @@ module initia_std::initia_nft { fun mint_internal( creator: &signer, - collection: String, + collection_name: String, description: String, token_id: String, uri: String, - can_burn: bool, + can_burn: bool ): ConstructorRef acquires InitiaNftCollection { + let collection_obj = collection_object(creator, &collection_name); let constructor_ref = nft::create( creator, - collection, + object::convert(collection_obj), description, token_id, option::none(), - uri, + uri ); let object_signer = object::generate_signer(&constructor_ref); - - let collection_obj = collection_object(creator, &collection); let collection = borrow_collection(collection_obj); let mutator_ref = @@ -240,7 +239,7 @@ module initia_std::initia_nft { option::none() }; - let initia_nft = InitiaNft { burn_ref, mutator_ref, }; + let initia_nft = InitiaNft { burn_ref, mutator_ref }; move_to(&object_signer, initia_nft); constructor_ref @@ -252,7 +251,7 @@ module initia_std::initia_nft { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); borrow_global(nft_address) } @@ -273,12 +272,12 @@ module initia_std::initia_nft { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); assert!( nft::creator(nft) == signer::address_of(creator), - error::permission_denied(ENOT_CREATOR), + error::permission_denied(ENOT_CREATOR) ); borrow_global(nft_address) } @@ -287,46 +286,42 @@ module initia_std::initia_nft { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); assert!( object::owns(nft, signer::address_of(owner)), - error::permission_denied(ENOT_OWNER), + error::permission_denied(ENOT_OWNER) ); let initia_nft = move_from(object::object_address(&nft)); assert!( option::is_some(&initia_nft.burn_ref), - error::invalid_state(ECAN_NOT_BURN), + error::invalid_state(ECAN_NOT_BURN) ); - let InitiaNft { burn_ref, mutator_ref: _, } = initia_nft; + let InitiaNft { burn_ref, mutator_ref: _ } = initia_nft; nft::burn(option::extract(&mut burn_ref)); } public entry fun set_description( - creator: &signer, - nft: Object, - description: String, + creator: &signer, nft: Object, description: String ) acquires InitiaNftCollection, InitiaNft { assert!( is_mutable_description(nft), - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); let initia_nft = authorized_borrow(nft, creator); nft::set_description( option::borrow(&initia_nft.mutator_ref), - description, + description ); } public entry fun set_uri( - creator: &signer, - nft: Object, - uri: String, + creator: &signer, nft: Object, uri: String ) acquires InitiaNftCollection, InitiaNft { assert!( is_mutable_uri(nft), - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); let initia_nft = authorized_borrow(nft, creator); nft::set_uri(option::borrow(&initia_nft.mutator_ref), uri); @@ -344,35 +339,37 @@ module initia_std::initia_nft { let collection_address = object::object_address(&nft); assert!( exists(collection_address), - error::not_found(ECOLLECTION_DOES_NOT_EXIST), + error::not_found(ECOLLECTION_DOES_NOT_EXIST) ); borrow_global(collection_address) } public fun is_mutable_collection_description( - collection: Object, + collection: Object ): bool acquires InitiaNftCollection { borrow_collection(collection).mutable_description } public fun is_mutable_collection_royalty( - collection: Object, + collection: Object ): bool acquires InitiaNftCollection { option::is_some(&borrow_collection(collection).royalty_mutator_ref) } - public fun is_mutable_collection_uri(collection: Object,): bool acquires InitiaNftCollection { + public fun is_mutable_collection_uri( + collection: Object + ): bool acquires InitiaNftCollection { borrow_collection(collection).mutable_uri } public fun is_mutable_collection_nft_description( - collection: Object, + collection: Object ): bool acquires InitiaNftCollection { borrow_collection(collection).mutable_nft_description } public fun is_mutable_collection_nft_uri( - collection: Object, + collection: Object ): bool acquires InitiaNftCollection { borrow_collection(collection).mutable_nft_uri } @@ -385,70 +382,64 @@ module initia_std::initia_nft { let collection_address = object::object_address(&collection); assert!( exists(collection_address), - error::not_found(ECOLLECTION_DOES_NOT_EXIST), + error::not_found(ECOLLECTION_DOES_NOT_EXIST) ); assert!( collection::creator(collection) == signer::address_of(creator), - error::permission_denied(ENOT_CREATOR), + error::permission_denied(ENOT_CREATOR) ); borrow_global(collection_address) } public entry fun set_collection_description( - creator: &signer, - collection: Object, - description: String, + creator: &signer, collection: Object, description: String ) acquires InitiaNftCollection { let initia_nft_collection = authorized_borrow_collection(collection, creator); assert!( initia_nft_collection.mutable_description, - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); collection::set_description( option::borrow(&initia_nft_collection.mutator_ref), - description, + description ); } public fun set_collection_royalties( - creator: &signer, - collection: Object, - royalty: royalty::Royalty, + creator: &signer, collection: Object, royalty: royalty::Royalty ) acquires InitiaNftCollection { let initia_nft_collection = authorized_borrow_collection(collection, creator); assert!( option::is_some(&initia_nft_collection.royalty_mutator_ref), - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); royalty::update( option::borrow(&initia_nft_collection.royalty_mutator_ref), - royalty, + royalty ); } public fun set_collection_royalties_call( creator: &signer, collection: Object, - royalty: Decimal128, - payee_address: address, + royalty: BigDecimal, + payee_address: address ) acquires InitiaNftCollection { let royalty = royalty::create(royalty, payee_address); set_collection_royalties(creator, collection, royalty); } public entry fun set_collection_uri( - creator: &signer, - collection: Object, - uri: String, + creator: &signer, collection: Object, uri: String ) acquires InitiaNftCollection { let initia_nft_collection = authorized_borrow_collection(collection, creator); assert!( initia_nft_collection.mutable_uri, - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); collection::set_uri( option::borrow(&initia_nft_collection.mutator_ref), - uri, + uri ); } @@ -458,7 +449,7 @@ module initia_std::initia_nft { use std::string; #[test_only] - use initia_std::decimal128; + use initia_std::bigdecimal; #[test(creator = @0x123)] fun test_create_and_transfer(creator: &signer) acquires InitiaNftCollection { @@ -470,7 +461,7 @@ module initia_std::initia_nft { assert!( object::owner(nft) == signer::address_of(creator), - 1, + 1 ); object::transfer(creator, nft, @0x345); assert!(object::owner(nft) == @0x345, 1); @@ -505,7 +496,7 @@ module initia_std::initia_nft { #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] fun test_set_description_non_creator( - creator: &signer, noncreator: &signer, + creator: &signer, noncreator: &signer ) acquires InitiaNftCollection, InitiaNft { let collection_name = string::utf8(b"collection name"); let token_id = string::utf8(b"nft name"); @@ -545,7 +536,9 @@ module initia_std::initia_nft { #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] - fun test_set_uri_non_creator(creator: &signer, noncreator: &signer,) acquires InitiaNftCollection, InitiaNft { + fun test_set_uri_non_creator( + creator: &signer, noncreator: &signer + ) acquires InitiaNftCollection, InitiaNft { let collection_name = string::utf8(b"collection name"); let token_id = string::utf8(b"nft name"); @@ -572,7 +565,9 @@ module initia_std::initia_nft { #[test(creator = @0x123, nonowner = @0x456)] #[expected_failure(abort_code = 0x50005, location = Self)] - fun test_burn_non_owner(creator: &signer, nonowner: &signer,) acquires InitiaNftCollection, InitiaNft { + fun test_burn_non_owner( + creator: &signer, nonowner: &signer + ) acquires InitiaNftCollection, InitiaNft { let collection_name = string::utf8(b"collection name"); let token_id = string::utf8(b"nft name"); @@ -589,12 +584,12 @@ module initia_std::initia_nft { let value = string::utf8(b"not"); assert!( collection::description(collection) != value, - 0, + 0 ); set_collection_description(creator, collection, value); assert!( collection::description(collection) == value, - 1, + 1 ); } @@ -606,21 +601,21 @@ module initia_std::initia_nft { set_collection_description( creator, collection, - string::utf8(b""), + string::utf8(b"") ); } #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] fun test_set_collection_description_non_creator( - creator: &signer, noncreator: &signer, + creator: &signer, noncreator: &signer ) acquires InitiaNftCollection { let collection_name = string::utf8(b"collection name"); let collection = create_collection_helper(creator, collection_name, true); set_collection_description( noncreator, collection, - string::utf8(b""), + string::utf8(b"") ); } @@ -642,21 +637,21 @@ module initia_std::initia_nft { set_collection_uri( creator, collection, - string::utf8(b""), + string::utf8(b"") ); } #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] fun test_set_collection_uri_non_creator( - creator: &signer, noncreator: &signer, + creator: &signer, noncreator: &signer ) acquires InitiaNftCollection { let collection_name = string::utf8(b"collection name"); let collection = create_collection_helper(creator, collection_name, true); set_collection_uri( noncreator, collection, - string::utf8(b""), + string::utf8(b"") ); } @@ -672,8 +667,8 @@ module initia_std::initia_nft { set_collection_royalties_call( creator, collection, - decimal128::from_ratio(2, 3), - @0x444, + bigdecimal::from_ratio_u64(2, 3), + @0x444 ); let royalty_after = option::extract(&mut nft::royalty(nft)); assert!(royalty_before != royalty_after, 0); @@ -681,9 +676,7 @@ module initia_std::initia_nft { #[test_only] fun create_collection_helper( - creator: &signer, - collection_name: String, - flag: bool, + creator: &signer, collection_name: String, flag: bool ): Object { let (obj, _) = create_collection_object( @@ -697,7 +690,7 @@ module initia_std::initia_nft { flag, flag, flag, - decimal128::from_ratio(1, 100), + bigdecimal::from_ratio_u64(1, 100) ); obj @@ -705,9 +698,7 @@ module initia_std::initia_nft { #[test_only] fun mint_helper( - creator: &signer, - collection_name: String, - token_id: String, + creator: &signer, collection_name: String, token_id: String ): Object acquires InitiaNftCollection { let (obj, _) = mint_nft_object( @@ -716,7 +707,7 @@ module initia_std::initia_nft { string::utf8(b"description"), token_id, string::utf8(b"uri"), - true, + true ); obj diff --git a/initia_stdlib/sources/token/nft.move b/initia_stdlib/sources/token/nft.move index 8bf8690..bff6566 100644 --- a/initia_stdlib/sources/token/nft.move +++ b/initia_stdlib/sources/token/nft.move @@ -31,6 +31,8 @@ module initia_std::nft { const EQUERY_LENGTH_TOO_LONG: u64 = 8; /// The provided token id is invalid const EINVALID_TOKEN_ID: u64 = 9; + /// The calling signer is not the owner + const ENOT_OWNER: u64 = 10; const MAX_NFT_TOKEN_ID_LENGTH: u64 = 128; const MAX_URI_LENGTH: u64 = 512; @@ -48,19 +50,19 @@ module initia_std::nft { token_id: String, /// The Uniform Resource Identifier (uri) pointing to the JSON file stored in off-chain /// storage; the URL length will likely need a maximum any suggestions? - uri: String, + uri: String } /// This enables burning an NFT, if possible, it will also delete the object. Note, the data /// in inner and self occupies 32-bytes each, rather than have both, this data structure makes /// a small optimization to support either and take a fixed amount of 34-bytes. struct BurnRef has drop, store { - delete_ref: object::DeleteRef, + delete_ref: object::DeleteRef } /// This enables mutating descritpion and URI by higher level services. struct MutatorRef has drop, store { - self: address, + self: address } #[event] @@ -78,58 +80,59 @@ module initia_std::nft { collection: Object, description: String, token_id: String, - uri: String, + uri: String } fun assert_token_id(token_id: &String) { let len = string::length(token_id); assert!( len <= MAX_NFT_TOKEN_ID_LENGTH, - error::out_of_range(ENFT_TOKEN_ID_TOO_LONG), + error::out_of_range(ENFT_TOKEN_ID_TOO_LONG) ); assert!( - string::index_of(token_id, &string::utf8(b"::")) == len, - error::invalid_argument(EINVALID_TOKEN_ID), + string::index_of(token_id, &string::utf8(b":")) == len, + error::invalid_argument(EINVALID_TOKEN_ID) ); } inline fun create_common( + owner: &signer, constructor_ref: &ConstructorRef, - creator_address: address, - collection_name: String, + collection: Object, description: String, token_id: String, royalty: Option, - uri: String, + uri: String ) { + // only the collection owner can create nfts + assert!( + object::owner(collection) == signer::address_of(owner), + error::unauthenticated(ENOT_OWNER) + ); assert_token_id(&token_id); assert!( string::length(&description) <= MAX_DESCRIPTION_LENGTH, - error::out_of_range(EDESCRIPTION_TOO_LONG), + error::out_of_range(EDESCRIPTION_TOO_LONG) ); assert!( string::length(&uri) <= MAX_URI_LENGTH, - error::out_of_range(EURI_TOO_LONG), + error::out_of_range(EURI_TOO_LONG) ); let object_signer = object::generate_signer(constructor_ref); - - let collection_addr = - collection::create_collection_address(creator_address, &collection_name); - let collection = object::address_to_object(collection_addr); collection::increment_supply( collection, token_id, - signer::address_of(&object_signer), + signer::address_of(&object_signer) ); - let nft = Nft { collection, description, token_id, uri, }; + let nft = Nft { collection, description, token_id, uri }; move_to(&object_signer, nft); if (option::is_some(&royalty)) { royalty::init( constructor_ref, - option::extract(&mut royalty), + option::extract(&mut royalty) ) }; } @@ -137,25 +140,28 @@ module initia_std::nft { /// Creates a new nft object from a nft name and returns the ConstructorRef for /// additional specialization. public fun create( - creator: &signer, - collection_name: String, + owner: &signer, + collection: Object, description: String, token_id: String, royalty: Option, - uri: String, + uri: String ): ConstructorRef { - let creator_address = signer::address_of(creator); + let owner_address = signer::address_of(owner); + let creator_address = collection::creator(collection); + let collection_name = collection::name(collection); let seed = create_nft_seed(&collection_name, &token_id); - let constructor_ref = object::create_deletable_named_object(creator, seed); + let constructor_ref = + object::create_nft_object(owner_address, creator_address, seed); create_common( + owner, &constructor_ref, - creator_address, - collection_name, + collection, description, token_id, royalty, - uri, + uri ); constructor_ref } @@ -166,7 +172,7 @@ module initia_std::nft { ): address { object::create_object_address( &creator, - create_nft_seed(collection, token_id), + create_nft_seed(collection, token_id) ) } @@ -174,7 +180,7 @@ module initia_std::nft { public fun create_nft_seed(collection: &String, token_id: &String): vector { assert!( string::length(token_id) <= MAX_NFT_TOKEN_ID_LENGTH, - error::out_of_range(ENFT_TOKEN_ID_TOO_LONG), + error::out_of_range(ENFT_TOKEN_ID_TOO_LONG) ); let seed = *string::bytes(collection); vector::append(&mut seed, b"::"); @@ -205,7 +211,7 @@ module initia_std::nft { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); borrow_global(nft_address) } @@ -269,7 +275,7 @@ module initia_std::nft { collection: nft.collection, description: nft.description, token_id: nft.token_id, - uri: nft.uri, + uri: nft.uri } } @@ -278,7 +284,7 @@ module initia_std::nft { let len = vector::length(&nfts); assert!( len <= MAX_QUERY_LENGTH, - error::invalid_argument(EQUERY_LENGTH_TOO_LONG), + error::invalid_argument(EQUERY_LENGTH_TOO_LONG) ); let index = 0; let res: vector = vector[]; @@ -296,7 +302,7 @@ module initia_std::nft { inline fun borrow_mut(mutator_ref: &MutatorRef): &mut Nft acquires Nft { assert!( exists(mutator_ref.self), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); borrow_global_mut(mutator_ref.self) } @@ -310,7 +316,7 @@ module initia_std::nft { royalty::delete(addr) }; - let Nft { collection, description: _, token_id, uri: _, } = move_from(addr); + let Nft { collection, description: _, token_id, uri: _ } = move_from(addr); collection::decrement_supply(collection, token_id, addr); } @@ -320,7 +326,7 @@ module initia_std::nft { ) acquires Nft { assert!( string::length(&description) <= MAX_DESCRIPTION_LENGTH, - error::out_of_range(EDESCRIPTION_TOO_LONG), + error::out_of_range(EDESCRIPTION_TOO_LONG) ); let nft = borrow_mut(mutator_ref); event::emit( @@ -329,7 +335,7 @@ module initia_std::nft { mutated_field_name: string::utf8(b"description"), old_value: nft.description, new_value: description - }, + } ); nft.description = description; } @@ -337,7 +343,7 @@ module initia_std::nft { public fun set_uri(mutator_ref: &MutatorRef, uri: String) acquires Nft { assert!( string::length(&uri) <= MAX_URI_LENGTH, - error::out_of_range(EURI_TOO_LONG), + error::out_of_range(EURI_TOO_LONG) ); let nft = borrow_mut(mutator_ref); event::emit( @@ -345,46 +351,89 @@ module initia_std::nft { nft: mutator_ref.self, mutated_field_name: string::utf8(b"uri"), old_value: nft.uri, - new_value: uri, - }, + new_value: uri + } ); nft.uri = uri; } + #[test_only] + use initia_std::bigdecimal; + + #[test_only] + fun generate_collection_object( + creator: &signer, collection_name: &String + ): Object { + let creator_address = signer::address_of(creator); + let collection_address = + collection::create_collection_address(creator_address, collection_name); + object::address_to_object(collection_address) + } + + #[test(creator = @0x123, owner = @0x456, trader = @0x789)] + fun test_create_after_collection_transfer( + creator: &signer, owner: &signer + ) { + let collection_name = string::utf8(b"collection name"); + let token_id = string::utf8(b"nft token_id"); + + create_collection_helper(creator, collection_name, 1); + + // transfer collection to owner + let owner_address = signer::address_of(owner); + object::transfer( + creator, + generate_collection_object(creator, &collection_name), + owner_address + ); + + // create nft + create_nft_helper(owner, creator, collection_name, token_id); + + let creator_address = signer::address_of(creator); + let nft_addr = create_nft_address( + creator_address, + &collection_name, + &token_id + ); + let nft = object::address_to_object(nft_addr); + assert!(object::owner(nft) == owner_address, 1); + } + #[test(creator = @0x123, trader = @0x456)] fun test_create_and_transfer(creator: &signer, trader: &signer) acquires Nft { let collection_name = string::utf8(b"collection name"); let token_id = string::utf8(b"nft token_id"); create_collection_helper(creator, collection_name, 1); - create_nft_helper(creator, collection_name, token_id); + create_nft_helper(creator, creator, collection_name, token_id); let creator_address = signer::address_of(creator); let nft_addr = create_nft_address( creator_address, &collection_name, - &token_id, + &token_id ); let nft = object::address_to_object(nft_addr); assert!(object::owner(nft) == creator_address, 1); object::transfer( creator, nft, - signer::address_of(trader), + signer::address_of(trader) ); assert!( object::owner(nft) == signer::address_of(trader), - 1, + 1 ); let expected_royalty = royalty::create( - initia_std::decimal128::from_ratio(25, 10000), - creator_address, + bigdecimal::from_ratio_u64(25, 10000), + creator_address ); assert!( option::some(expected_royalty) == royalty(nft), - 2, + 2 ); } @@ -396,8 +445,8 @@ module initia_std::nft { let creator_address = signer::address_of(creator); let expected_royalty = royalty::create( - initia_std::decimal128::from_ratio(10, 1000), - creator_address, + bigdecimal::from_ratio_u64(10, 1000), + creator_address ); collection::create_fixed_collection( creator, @@ -405,27 +454,27 @@ module initia_std::nft { 5, collection_name, option::some(expected_royalty), - string::utf8(b"collection uri"), + string::utf8(b"collection uri") ); create( creator, - collection_name, + generate_collection_object(creator, &collection_name), string::utf8(b"nft description"), token_id, option::none(), - string::utf8(b"nft uri"), + string::utf8(b"nft uri") ); let nft_addr = create_nft_address( creator_address, &collection_name, - &token_id, + &token_id ); let nft = object::address_to_object(nft_addr); assert!( option::some(expected_royalty) == royalty(nft), - 0, + 0 ); } @@ -439,23 +488,23 @@ module initia_std::nft { string::utf8(b"collection description"), collection_name, option::none(), - string::utf8(b"collection uri"), + string::utf8(b"collection uri") ); create( creator, - collection_name, + generate_collection_object(creator, &collection_name), string::utf8(b"nft description"), token_id, option::none(), - string::utf8(b"nft uri"), + string::utf8(b"nft uri") ); let creator_address = signer::address_of(creator); let nft_addr = create_nft_address( creator_address, &collection_name, - &token_id, + &token_id ); let nft = object::address_to_object(nft_addr); assert!(option::none() == royalty(nft), 0); @@ -467,7 +516,7 @@ module initia_std::nft { let collection_name = string::utf8(b"collection name"); let token_id = string::utf8(b"nft token_id::hello"); create_collection_helper(creator, collection_name, 1); - create_nft_helper(creator, collection_name, token_id); + create_nft_helper(creator, creator, collection_name, token_id); } #[test(creator = @0x123)] @@ -478,8 +527,8 @@ module initia_std::nft { let token_id2 = string::utf8(b"nft token_id2"); create_collection_helper(creator, collection_name, 1); - create_nft_helper(creator, collection_name, token_id); - create_nft_helper(creator, collection_name, token_id2); + create_nft_helper(creator, creator, collection_name, token_id); + create_nft_helper(creator, creator, collection_name, token_id2); } #[test(creator = @0x123)] @@ -489,8 +538,8 @@ module initia_std::nft { let token_id = string::utf8(b"nft token_id"); create_collection_helper(creator, collection_name, 2); - create_nft_helper(creator, collection_name, token_id); - create_nft_helper(creator, collection_name, token_id); + create_nft_helper(creator, creator, collection_name, token_id); + create_nft_helper(creator, creator, collection_name, token_id); } #[test(creator = @0x123)] @@ -505,8 +554,8 @@ module initia_std::nft { create_nft_address( signer::address_of(creator), &collection_name, - &token_id, - ), + &token_id + ) ); let description = string::utf8(b"no fail"); @@ -527,8 +576,8 @@ module initia_std::nft { create_nft_address( signer::address_of(creator), &collection_name, - &token_id, - ), + &token_id + ) ); let uri = string::utf8(b"no fail"); @@ -546,11 +595,11 @@ module initia_std::nft { let constructor_ref = create( creator, - collection_name, + generate_collection_object(creator, &collection_name), string::utf8(b"nft description"), token_id, option::none(), - string::utf8(b"nft uri"), + string::utf8(b"nft uri") ); let burn_ref = generate_burn_ref(&constructor_ref); let nft_addr = object::address_from_constructor_ref(&constructor_ref); @@ -570,16 +619,16 @@ module initia_std::nft { let constructor_ref = create( creator, - collection_name, + generate_collection_object(creator, &collection_name), string::utf8(b"nft description"), token_id, option::some( royalty::create( - initia_std::decimal128::from_ratio(1, 1), - signer::address_of(creator), - ), + bigdecimal::from_ratio_u64(1, 1), + signer::address_of(creator) + ) ), - string::utf8(b"nft uri"), + string::utf8(b"nft uri") ); let burn_ref = generate_burn_ref(&constructor_ref); let nft_addr = object::address_from_constructor_ref(&constructor_ref); @@ -600,11 +649,11 @@ module initia_std::nft { let constructor_ref = create( creator, - collection_name, + generate_collection_object(creator, &collection_name), string::utf8(b"nft description"), token_id, option::none(), - string::utf8(b"nft uri"), + string::utf8(b"nft uri") ); let burn_ref = generate_burn_ref(&constructor_ref); let nft_addr = object::address_from_constructor_ref(&constructor_ref); @@ -614,11 +663,11 @@ module initia_std::nft { // mint again create( creator, - collection_name, + generate_collection_object(creator, &collection_name), string::utf8(b"nft description"), token_id, option::none(), - string::utf8(b"nft uri"), + string::utf8(b"nft uri") ); assert!(exists(nft_addr), 2); } @@ -633,36 +682,39 @@ module initia_std::nft { max_supply, collection_name, option::none(), - string::utf8(b"collection uri"), + string::utf8(b"collection uri") ); } #[test_only] fun create_nft_helper( - creator: &signer, collection_name: String, token_id: String + owner: &signer, + creator: &signer, + collection_name: String, + token_id: String ): ConstructorRef { create( - creator, - collection_name, + owner, + generate_collection_object(creator, &collection_name), string::utf8(b"nft description"), token_id, option::some( royalty::create( - initia_std::decimal128::from_ratio(25, 10000), - signer::address_of(creator), - ), + bigdecimal::from_ratio_u64(25, 10000), + signer::address_of(creator) + ) ), - string::utf8(b"uri"), + string::utf8(b"uri") ) } #[test_only] fun create_nft_with_mutation_ref( - creator: &signer, - collection_name: String, - token_id: String, + creator: &signer, collection_name: String, token_id: String ): MutatorRef { - let constructor_ref = create_nft_helper(creator, collection_name, token_id); + let constructor_ref = create_nft_helper( + creator, creator, collection_name, token_id + ); generate_mutator_ref(&constructor_ref) } } diff --git a/initia_stdlib/sources/token/property_map.move b/initia_stdlib/sources/token/property_map.move index 96b3b9e..97c4c60 100644 --- a/initia_stdlib/sources/token/property_map.move +++ b/initia_stdlib/sources/token/property_map.move @@ -53,18 +53,18 @@ module initia_std::property_map { /// A Map for typed key to value mapping, the contract using it /// should keep track of what keys are what types, and parse them accordingly. struct PropertyMap has drop, key { - inner: SimpleMap, + inner: SimpleMap } /// A typed value for the `PropertyMap` to ensure that typing is always consistent struct PropertyValue has drop, store { type: u8, - value: vector, + value: vector } /// A mutator ref that allows for mutation of the property map struct MutatorRef has drop, store { - self: address, + self: address } public fun init(s: &signer, container: PropertyMap) { @@ -81,20 +81,20 @@ module initia_std::property_map { public fun prepare_input( keys: vector, types: vector, - values: vector>, + values: vector> ): PropertyMap { let length = vector::length(&keys); assert!( length <= MAX_PROPERTY_MAP_SIZE, - error::invalid_argument(ETOO_MANY_PROPERTIES), + error::invalid_argument(ETOO_MANY_PROPERTIES) ); assert!( length == vector::length(&values), - error::invalid_argument(EKEY_VALUE_COUNT_MISMATCH), + error::invalid_argument(EKEY_VALUE_COUNT_MISMATCH) ); assert!( length == vector::length(&types), - error::invalid_argument(EKEY_TYPE_COUNT_MISMATCH), + error::invalid_argument(EKEY_TYPE_COUNT_MISMATCH) ); let container = simple_map::create(); @@ -102,7 +102,7 @@ module initia_std::property_map { let key = vector::pop_back(&mut keys); assert!( string::length(&key) <= MAX_PROPERTY_NAME_LENGTH, - error::invalid_argument(EPROPERTY_MAP_KEY_TOO_LONG), + error::invalid_argument(EPROPERTY_MAP_KEY_TOO_LONG) ); let value = vector::pop_back(&mut values); @@ -114,7 +114,7 @@ module initia_std::property_map { simple_map::add( &mut container, key, - PropertyValue { value, type: new_type }, + PropertyValue { value, type: new_type } ); }; @@ -232,7 +232,7 @@ module initia_std::property_map { inline fun assert_exists(object: address) { assert!( exists(object), - error::not_found(EPROPERTY_MAP_DOES_NOT_EXIST), + error::not_found(EPROPERTY_MAP_DOES_NOT_EXIST) ); } @@ -241,7 +241,7 @@ module initia_std::property_map { let (type, value) = read(object, key); assert!( type == type_info::type_name(), - error::invalid_argument(ETYPE_MISMATCH), + error::invalid_argument(ETYPE_MISMATCH) ); value } @@ -326,7 +326,7 @@ module initia_std::property_map { simple_map::add( &mut property_map.inner, key, - PropertyValue { type, value }, + PropertyValue { type, value } ); } @@ -384,24 +384,29 @@ module initia_std::property_map { b"u32" ), string::utf8(b"u64"), string::utf8(b"u128"), string::utf8(b"u256"), string::utf8( b"vector" - ), string::utf8(b"0x1::string::String"),], + ), string::utf8(b"0x1::string::String") + ], vector[ string::utf8(b"bool"), string::utf8(b"u8"), string::utf8(b"u16"), string::utf8( b"u32" ), string::utf8(b"u64"), string::utf8(b"u128"), string::utf8(b"u256"), string::utf8( b"vector" - ), string::utf8(b"0x1::string::String"),], + ), string::utf8(b"0x1::string::String") + ], vector[ - bcs::to_bytes(&true), bcs::to_bytes(&0x12), bcs::to_bytes( - &0x1234 - ), bcs::to_bytes(&0x12345678), bcs::to_bytes( - &0x1234567812345678 - ), bcs::to_bytes(&0x12345678123456781234567812345678), bcs::to_bytes( + bcs::to_bytes(&true), + bcs::to_bytes(&0x12), + bcs::to_bytes(&0x1234), + bcs::to_bytes(&0x12345678), + bcs::to_bytes(&0x1234567812345678), + bcs::to_bytes(&0x12345678123456781234567812345678), + bcs::to_bytes( & 0x1234567812345678123456781234567812345678123456781234567812345678 - ), bcs::to_bytes>(&vector[0x01]), bcs::to_bytes( - &string::utf8(b"a") - ),], + ), + bcs::to_bytes>(&vector[0x01]), + bcs::to_bytes(&string::utf8(b"a")) + ] ); init(&s, input); let mutator = generate_mutator_ref(&s); @@ -409,43 +414,43 @@ module initia_std::property_map { assert!(read_bool(object, &string::utf8(b"bool")), 0); assert!( read_u8(object, &string::utf8(b"u8")) == 0x12, - 1, + 1 ); assert!( read_u16(object, &string::utf8(b"u16")) == 0x1234, - 2, + 2 ); assert!( read_u32(object, &string::utf8(b"u32")) == 0x12345678, - 3, + 3 ); assert!( read_u64(object, &string::utf8(b"u64")) == 0x1234567812345678, - 4, + 4 ); assert!( - read_u128(object, &string::utf8(b"u128")) == - 0x12345678123456781234567812345678, - 5, + read_u128(object, &string::utf8(b"u128")) + == 0x12345678123456781234567812345678, + 5 ); assert!( read_u256(object, &string::utf8(b"u256")) == 0x1234567812345678123456781234567812345678123456781234567812345678, - 6, + 6 ); assert!( read_bytes( object, - &string::utf8(b"vector"), + &string::utf8(b"vector") ) == vector[0x01], - 7, + 7 ); assert!( read_string( object, - &string::utf8(b"0x1::string::String"), + &string::utf8(b"0x1::string::String") ) == string::utf8(b"a"), - 8, + 8 ); assert!(length(object) == 9, 9); @@ -453,86 +458,86 @@ module initia_std::property_map { update_typed( &mutator, &string::utf8(b"bool"), - false, + false ); update_typed(&mutator, &string::utf8(b"u8"), 0x21); update_typed( &mutator, &string::utf8(b"u16"), - 0x22, + 0x22 ); update_typed( &mutator, &string::utf8(b"u32"), - 0x23, + 0x23 ); update_typed( &mutator, &string::utf8(b"u64"), - 0x24, + 0x24 ); update_typed( &mutator, &string::utf8(b"u128"), - 0x25, + 0x25 ); update_typed( &mutator, &string::utf8(b"u256"), - 0x26, + 0x26 ); update_typed>( &mutator, &string::utf8(b"vector"), - vector[0x02], + vector[0x02] ); update_typed( &mutator, &string::utf8(b"0x1::string::String"), - string::utf8(b"ha"), + string::utf8(b"ha") ); assert!( !read_bool(object, &string::utf8(b"bool")), - 10, + 10 ); assert!( read_u8(object, &string::utf8(b"u8")) == 0x21, - 11, + 11 ); assert!( read_u16(object, &string::utf8(b"u16")) == 0x22, - 12, + 12 ); assert!( read_u32(object, &string::utf8(b"u32")) == 0x23, - 13, + 13 ); assert!( read_u64(object, &string::utf8(b"u64")) == 0x24, - 14, + 14 ); assert!( read_u128(object, &string::utf8(b"u128")) == 0x25, - 15, + 15 ); assert!( read_u256(object, &string::utf8(b"u256")) == 0x26, - 16, + 16 ); assert!( read_bytes( object, - &string::utf8(b"vector"), + &string::utf8(b"vector") ) == vector[0x02], - 17, + 17 ); assert!( read_string( object, - &string::utf8(b"0x1::string::String"), + &string::utf8(b"0x1::string::String") ) == string::utf8(b"ha"), - 18, + 18 ); assert!(length(object) == 9, 19); @@ -547,7 +552,7 @@ module initia_std::property_map { remove(&mutator, &string::utf8(b"vector")); remove( &mutator, - &string::utf8(b"0x1::string::String"), + &string::utf8(b"0x1::string::String") ); assert!(length(object) == 0, 20); @@ -555,7 +560,7 @@ module initia_std::property_map { add_typed( &mutator, string::utf8(b"bool"), - false, + false ); add_typed(&mutator, string::utf8(b"u8"), 0x21); add_typed(&mutator, string::utf8(b"u16"), 0x22); @@ -564,65 +569,65 @@ module initia_std::property_map { add_typed( &mutator, string::utf8(b"u128"), - 0x25, + 0x25 ); add_typed( &mutator, string::utf8(b"u256"), - 0x26, + 0x26 ); add_typed>( &mutator, string::utf8(b"vector"), - vector[0x02], + vector[0x02] ); add_typed( &mutator, string::utf8(b"0x1::string::String"), - string::utf8(b"ha"), + string::utf8(b"ha") ); assert!( !read_bool(object, &string::utf8(b"bool")), - 21, + 21 ); assert!( read_u8(object, &string::utf8(b"u8")) == 0x21, - 22, + 22 ); assert!( read_u16(object, &string::utf8(b"u16")) == 0x22, - 23, + 23 ); assert!( read_u32(object, &string::utf8(b"u32")) == 0x23, - 24, + 24 ); assert!( read_u64(object, &string::utf8(b"u64")) == 0x24, - 25, + 25 ); assert!( read_u128(object, &string::utf8(b"u128")) == 0x25, - 26, + 26 ); assert!( read_u256(object, &string::utf8(b"u256")) == 0x26, - 27, + 27 ); assert!( read_bytes( object, - &string::utf8(b"vector"), + &string::utf8(b"vector") ) == vector[0x02], - 28, + 28 ); assert!( read_string( object, - &string::utf8(b"0x1::string::String"), + &string::utf8(b"0x1::string::String") ) == string::utf8(b"ha"), - 29, + 29 ); assert!(length(object) == 9, 30); @@ -637,7 +642,7 @@ module initia_std::property_map { remove(&mutator, &string::utf8(b"vector")); remove( &mutator, - &string::utf8(b"0x1::string::String"), + &string::utf8(b"0x1::string::String") ); assert!(length(object) == 0, 31); @@ -646,37 +651,37 @@ module initia_std::property_map { &mutator, string::utf8(b"bool"), string::utf8(b"bool"), - bcs::to_bytes(&true), + bcs::to_bytes(&true) ); add( &mutator, string::utf8(b"u8"), string::utf8(b"u8"), - bcs::to_bytes(&0x12), + bcs::to_bytes(&0x12) ); add( &mutator, string::utf8(b"u16"), string::utf8(b"u16"), - bcs::to_bytes(&0x1234), + bcs::to_bytes(&0x1234) ); add( &mutator, string::utf8(b"u32"), string::utf8(b"u32"), - bcs::to_bytes(&0x12345678), + bcs::to_bytes(&0x12345678) ); add( &mutator, string::utf8(b"u64"), string::utf8(b"u64"), - bcs::to_bytes(&0x1234567812345678), + bcs::to_bytes(&0x1234567812345678) ); add( &mutator, string::utf8(b"u128"), string::utf8(b"u128"), - bcs::to_bytes(&0x12345678123456781234567812345678), + bcs::to_bytes(&0x12345678123456781234567812345678) ); add( &mutator, @@ -684,61 +689,61 @@ module initia_std::property_map { string::utf8(b"u256"), bcs::to_bytes( &0x1234567812345678123456781234567812345678123456781234567812345678 - ), + ) ); add( &mutator, string::utf8(b"vector"), string::utf8(b"vector"), - bcs::to_bytes>(&vector[0x01]), + bcs::to_bytes>(&vector[0x01]) ); add( &mutator, string::utf8(b"0x1::string::String"), string::utf8(b"0x1::string::String"), - bcs::to_bytes(&string::utf8(b"a")), + bcs::to_bytes(&string::utf8(b"a")) ); assert!(read_bool(object, &string::utf8(b"bool")), 32); assert!( read_u8(object, &string::utf8(b"u8")) == 0x12, - 33, + 33 ); assert!( read_u16(object, &string::utf8(b"u16")) == 0x1234, - 34, + 34 ); assert!( read_u32(object, &string::utf8(b"u32")) == 0x12345678, - 35, + 35 ); assert!( read_u64(object, &string::utf8(b"u64")) == 0x1234567812345678, - 36, + 36 ); assert!( - read_u128(object, &string::utf8(b"u128")) == - 0x12345678123456781234567812345678, - 37, + read_u128(object, &string::utf8(b"u128")) + == 0x12345678123456781234567812345678, + 37 ); assert!( read_u256(object, &string::utf8(b"u256")) == 0x1234567812345678123456781234567812345678123456781234567812345678, - 38, + 38 ); assert!( read_bytes( object, - &string::utf8(b"vector"), + &string::utf8(b"vector") ) == vector[0x01], - 39, + 39 ); assert!( read_string( object, - &string::utf8(b"0x1::string::String"), + &string::utf8(b"0x1::string::String") ) == string::utf8(b"a"), - 40, + 40 ); assert!(length(object) == 9, 41); @@ -747,98 +752,98 @@ module initia_std::property_map { &mutator, &string::utf8(b"bool"), string::utf8(b"bool"), - bcs::to_bytes(&false), + bcs::to_bytes(&false) ); update( &mutator, &string::utf8(b"u8"), string::utf8(b"u8"), - bcs::to_bytes(&0x21), + bcs::to_bytes(&0x21) ); update( &mutator, &string::utf8(b"u16"), string::utf8(b"u16"), - bcs::to_bytes(&0x22), + bcs::to_bytes(&0x22) ); update( &mutator, &string::utf8(b"u32"), string::utf8(b"u32"), - bcs::to_bytes(&0x23), + bcs::to_bytes(&0x23) ); update( &mutator, &string::utf8(b"u64"), string::utf8(b"u64"), - bcs::to_bytes(&0x24), + bcs::to_bytes(&0x24) ); update( &mutator, &string::utf8(b"u128"), string::utf8(b"u128"), - bcs::to_bytes(&0x25), + bcs::to_bytes(&0x25) ); update( &mutator, &string::utf8(b"u256"), string::utf8(b"u256"), - bcs::to_bytes(&0x26), + bcs::to_bytes(&0x26) ); update( &mutator, &string::utf8(b"vector"), string::utf8(b"vector"), - bcs::to_bytes>(&vector[0x02]), + bcs::to_bytes>(&vector[0x02]) ); update( &mutator, &string::utf8(b"0x1::string::String"), string::utf8(b"0x1::string::String"), - bcs::to_bytes(&string::utf8(b"ha")), + bcs::to_bytes(&string::utf8(b"ha")) ); assert!( !read_bool(object, &string::utf8(b"bool")), - 10, + 10 ); assert!( read_u8(object, &string::utf8(b"u8")) == 0x21, - 11, + 11 ); assert!( read_u16(object, &string::utf8(b"u16")) == 0x22, - 12, + 12 ); assert!( read_u32(object, &string::utf8(b"u32")) == 0x23, - 13, + 13 ); assert!( read_u64(object, &string::utf8(b"u64")) == 0x24, - 14, + 14 ); assert!( read_u128(object, &string::utf8(b"u128")) == 0x25, - 15, + 15 ); assert!( read_u256(object, &string::utf8(b"u256")) == 0x26, - 16, + 16 ); assert!( read_bytes( object, - &string::utf8(b"vector"), + &string::utf8(b"vector") ) == vector[0x02], - 17, + 17 ); assert!( read_string( object, - &string::utf8(b"0x1::string::String"), + &string::utf8(b"0x1::string::String") ) == string::utf8(b"ha"), - 18, + 18 ); } @@ -852,7 +857,7 @@ module initia_std::property_map { prepare_input( vector[string::utf8(b"bool")], vector[string::utf8(b"u16")], - vector[bcs::to_bytes(&true)], + vector[bcs::to_bytes(&true)] ); init(&s, input); } @@ -867,7 +872,7 @@ module initia_std::property_map { prepare_input( vector[string::utf8(b"bool"), string::utf8(b"u8")], vector[string::utf8(b"bool"), string::utf8(b"u8")], - vector[bcs::to_bytes(&true)], + vector[bcs::to_bytes(&true)] ); init(&s, input); } @@ -882,7 +887,7 @@ module initia_std::property_map { prepare_input( vector[string::utf8(b"bool"), string::utf8(b"u8")], vector[string::utf8(b"bool")], - vector[bcs::to_bytes(&true), bcs::to_bytes(&0x2)], + vector[bcs::to_bytes(&true), bcs::to_bytes(&0x2)] ); init(&s, input); } @@ -897,7 +902,7 @@ module initia_std::property_map { prepare_input( vector[string::utf8(b"bool")], vector[string::utf8(b"bool")], - vector[bcs::to_bytes(&true)], + vector[bcs::to_bytes(&true)] ); init(&s, input); let mutator = generate_mutator_ref(&s); @@ -906,7 +911,7 @@ module initia_std::property_map { &mutator, &string::utf8(b"u16"), string::utf8(b"bool"), - bcs::to_bytes(&0x1234), + bcs::to_bytes(&0x1234) ); } @@ -920,7 +925,7 @@ module initia_std::property_map { prepare_input( vector[string::utf8(b"bool")], vector[string::utf8(b"bool")], - vector[bcs::to_bytes(&true)], + vector[bcs::to_bytes(&true)] ); init(&s, input); let mutator = generate_mutator_ref(&s); @@ -929,7 +934,7 @@ module initia_std::property_map { &mutator, &string::utf8(b"bool"), string::utf8(b"bool"), - bcs::to_bytes(&0x1234), + bcs::to_bytes(&0x1234) ); } @@ -945,7 +950,7 @@ module initia_std::property_map { prepare_input( vector[string::utf8(b"bool")], vector[string::utf8(b"bool")], - vector[bcs::to_bytes(&true)], + vector[bcs::to_bytes(&true)] ); init(&s, input); read_u8(object, &string::utf8(b"bool")); diff --git a/initia_stdlib/sources/token/royalty.move b/initia_stdlib/sources/token/royalty.move index 7764aac..c9ced8f 100644 --- a/initia_stdlib/sources/token/royalty.move +++ b/initia_stdlib/sources/token/royalty.move @@ -4,7 +4,7 @@ module initia_std::royalty { use std::error; use std::option::{Self, Option}; - use initia_std::decimal128::{Self, Decimal128}; + use initia_std::bigdecimal::{Self, BigDecimal}; use initia_std::object::{Self, ConstructorRef, ExtendRef, Object}; friend initia_std::nft; @@ -20,14 +20,14 @@ module initia_std::royalty { /// /// Royalties are optional for a collection. struct Royalty has copy, drop, key { - royalty: Decimal128, + royalty: BigDecimal, /// creators. - payee_address: address, + payee_address: address } /// This enables creating or overwriting a `MutatorRef`. struct MutatorRef has drop, store { - inner: ExtendRef, + inner: ExtendRef } /// Add a royalty, given a ConstructorRef. @@ -48,10 +48,10 @@ module initia_std::royalty { } /// Creates a new royalty, verifying that it is a valid percentage - public fun create(royalty: Decimal128, payee_address: address): Royalty { + public fun create(royalty: BigDecimal, payee_address: address): Royalty { assert!( - decimal128::val(&royalty) <= decimal128::val(&decimal128::one()), - error::out_of_range(EROYALTY_EXCEEDS_MAXIMUM), + bigdecimal::le(royalty, bigdecimal::one()), + error::out_of_range(EROYALTY_EXCEEDS_MAXIMUM) ); Royalty { royalty, payee_address } @@ -68,7 +68,7 @@ module initia_std::royalty { public(friend) fun delete(addr: address) acquires Royalty { assert!( exists(addr), - error::not_found(EROYALTY_DOES_NOT_EXIST), + error::not_found(EROYALTY_DOES_NOT_EXIST) ); move_from(addr); } @@ -83,7 +83,7 @@ module initia_std::royalty { } } - public fun royalty(royalty: &Royalty): Decimal128 { + public fun royalty(royalty: &Royalty): BigDecimal { royalty.royalty } @@ -104,26 +104,26 @@ module initia_std::royalty { let constructor_ref = object::create_named_object(creator, b""); let object = object::object_from_constructor_ref(&constructor_ref); - let init_royalty = create(decimal128::from_ratio(1, 2), @0x123); + let init_royalty = create(bigdecimal::from_ratio_u64(1, 2), @0x123); init(&constructor_ref, init_royalty); assert!(option::some(init_royalty) == get(object), 0); assert!( - royalty(&init_royalty) == decimal128::from_ratio(1, 2), - 1, + royalty(&init_royalty) == bigdecimal::from_ratio_u64(1, 2), + 1 ); assert!(payee_address(&init_royalty) == @0x123, 2); let mutator_ref = generate_mutator_ref(object::generate_extend_ref(&constructor_ref)); - let update_royalty = create(decimal128::from_ratio(2, 5), @0x456); + let update_royalty = create(bigdecimal::from_ratio_u64(2, 5), @0x456); update(&mutator_ref, update_royalty); assert!( option::some(update_royalty) == get(object), - 3, + 3 ); assert!( - royalty(&update_royalty) == decimal128::from_ratio(2, 5), - 4, + royalty(&update_royalty) == bigdecimal::from_ratio_u64(2, 5), + 4 ); assert!(payee_address(&update_royalty) == @0x456, 5); } @@ -137,11 +137,11 @@ module initia_std::royalty { let mutator_ref = generate_mutator_ref(object::generate_extend_ref(&constructor_ref)); - let update_royalty = create(decimal128::from_ratio(1, 5), @0x123); + let update_royalty = create(bigdecimal::from_ratio_u64(1, 5), @0x123); update(&mutator_ref, update_royalty); assert!( option::some(update_royalty) == get(object), - 1, + 1 ); } @@ -154,6 +154,6 @@ module initia_std::royalty { #[test] #[expected_failure(abort_code = 0x20002, location = Self)] fun test_exceeds_maximum() { - create(decimal128::from_ratio(6, 5), @0x1); + create(bigdecimal::from_ratio_u64(6, 5), @0x1); } } diff --git a/initia_stdlib/sources/token/simple_nft.move b/initia_stdlib/sources/token/simple_nft.move index 286ac70..66c8e9f 100644 --- a/initia_stdlib/sources/token/simple_nft.move +++ b/initia_stdlib/sources/token/simple_nft.move @@ -10,7 +10,7 @@ module initia_std::simple_nft { use initia_std::royalty; use initia_std::nft; use initia_std::initia_nft::{Self, InitiaNft}; - use initia_std::decimal128::Decimal128; + use initia_std::bigdecimal::BigDecimal; /// The collection does not exist const ECOLLECTION_DOES_NOT_EXIST: u64 = 1; @@ -26,13 +26,13 @@ module initia_std::simple_nft { /// Storage state for managing the no-code Collection. struct SimpleNftCollection has key { /// Determines if the creator can mutate nft properties - mutable_nft_properties: bool, + mutable_nft_properties: bool } /// Storage state for managing the no-code Nft. struct SimpleNft has key { /// Used to mutate properties - property_mutator_ref: property_map::MutatorRef, + property_mutator_ref: property_map::MutatorRef } /// Create a new collection @@ -48,7 +48,7 @@ module initia_std::simple_nft { mutable_nft_description: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, - royalty: Decimal128, + royalty: BigDecimal ) { create_collection_object( creator, @@ -62,7 +62,7 @@ module initia_std::simple_nft { mutable_nft_description, mutable_nft_properties, mutable_nft_uri, - royalty, + royalty ); } @@ -78,7 +78,7 @@ module initia_std::simple_nft { mutable_nft_description: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, - royalty: Decimal128, + royalty: BigDecimal ): Object { let (_, extend_ref) = initia_nft::create_collection_object( @@ -92,12 +92,12 @@ module initia_std::simple_nft { mutable_uri, mutable_nft_description, mutable_nft_uri, - royalty, + royalty ); let object_signer = object::generate_signer_for_extending(&extend_ref); - let simple_nft_collection = SimpleNftCollection { mutable_nft_properties, }; + let simple_nft_collection = SimpleNftCollection { mutable_nft_properties }; move_to(&object_signer, simple_nft_collection); object::address_to_object(signer::address_of(&object_signer)) } @@ -112,7 +112,7 @@ module initia_std::simple_nft { property_keys: vector, property_types: vector, property_values: vector>, - to: Option
, + to: Option
) { let nft_object = mint_nft_object( @@ -123,13 +123,13 @@ module initia_std::simple_nft { uri, property_keys, property_types, - property_values, + property_values ); if (option::is_some(&to)) { object::transfer( creator, nft_object, - option::extract(&mut to), + option::extract(&mut to) ); } } @@ -143,7 +143,7 @@ module initia_std::simple_nft { uri: String, property_keys: vector, property_types: vector, - property_values: vector>, + property_values: vector> ): Object { let (object, extend_ref) = initia_nft::mint_nft_object( @@ -152,7 +152,7 @@ module initia_std::simple_nft { description, token_id, uri, - true, + true ); let s = object::generate_signer_for_extending(&extend_ref); @@ -160,12 +160,12 @@ module initia_std::simple_nft { property_map::prepare_input( property_keys, property_types, - property_values, + property_values ); property_map::init(&s, properties); let simple_nft = SimpleNft { - property_mutator_ref: property_map::generate_mutator_ref(&s), + property_mutator_ref: property_map::generate_mutator_ref(&s) }; move_to(&s, simple_nft); @@ -178,7 +178,7 @@ module initia_std::simple_nft { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); borrow_global(nft_address) } @@ -195,12 +195,12 @@ module initia_std::simple_nft { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); assert!( nft::creator(nft) == signer::address_of(creator), - error::permission_denied(ENOT_CREATOR), + error::permission_denied(ENOT_CREATOR) ); borrow_global(nft_address) } @@ -209,11 +209,11 @@ module initia_std::simple_nft { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); assert!( object::owns(nft, signer::address_of(owner)), - error::permission_denied(ENOT_OWNER), + error::permission_denied(ENOT_OWNER) ); let simple_nft = move_from(object::object_address(&nft)); @@ -223,17 +223,13 @@ module initia_std::simple_nft { } public entry fun set_description( - creator: &signer, - nft: Object, - description: String, + creator: &signer, nft: Object, description: String ) { initia_nft::set_description(creator, nft, description); } public entry fun set_uri( - creator: &signer, - nft: Object, - uri: String, + creator: &signer, nft: Object, uri: String ) { initia_nft::set_uri(creator, nft, uri); } @@ -243,19 +239,19 @@ module initia_std::simple_nft { nft: Object, key: String, type: String, - value: vector, + value: vector ) acquires SimpleNftCollection, SimpleNft { let simple_nft = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::add( &simple_nft.property_mutator_ref, key, type, - value, + value ); } @@ -263,26 +259,24 @@ module initia_std::simple_nft { creator: &signer, nft: Object, key: String, - value: V, + value: V ) acquires SimpleNftCollection, SimpleNft { let simple_nft = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::add_typed(&simple_nft.property_mutator_ref, key, value); } public entry fun remove_property( - creator: &signer, - nft: Object, - key: String, + creator: &signer, nft: Object, key: String ) acquires SimpleNftCollection, SimpleNft { let simple_nft = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::remove(&simple_nft.property_mutator_ref, &key); @@ -293,19 +287,19 @@ module initia_std::simple_nft { nft: Object, key: String, type: String, - value: vector, + value: vector ) acquires SimpleNftCollection, SimpleNft { let simple_nft = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::update( &simple_nft.property_mutator_ref, &key, type, - value, + value ); } @@ -313,18 +307,18 @@ module initia_std::simple_nft { creator: &signer, nft: Object, key: String, - value: V, + value: V ) acquires SimpleNftCollection, SimpleNft { let simple_nft = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::update_typed( &simple_nft.property_mutator_ref, &key, - value, + value ); } @@ -340,41 +334,41 @@ module initia_std::simple_nft { let collection_address = object::object_address(&nft); assert!( exists(collection_address), - error::not_found(ECOLLECTION_DOES_NOT_EXIST), + error::not_found(ECOLLECTION_DOES_NOT_EXIST) ); borrow_global(collection_address) } public fun is_mutable_collection_description( - collection: Object, + collection: Object ): bool { initia_nft::is_mutable_collection_description(collection) } public fun is_mutable_collection_royalty( - collection: Object, + collection: Object ): bool { initia_nft::is_mutable_collection_royalty(collection) } - public fun is_mutable_collection_uri(collection: Object,): bool { + public fun is_mutable_collection_uri(collection: Object): bool { initia_nft::is_mutable_collection_uri(collection) } public fun is_mutable_collection_nft_description( - collection: Object, + collection: Object ): bool { initia_nft::is_mutable_collection_nft_description(collection) } public fun is_mutable_collection_nft_uri( - collection: Object, + collection: Object ): bool { initia_nft::is_mutable_collection_nft_uri(collection) } public fun is_mutable_collection_nft_properties( - collection: Object, + collection: Object ): bool acquires SimpleNftCollection { borrow_collection(collection).mutable_nft_properties } @@ -387,27 +381,23 @@ module initia_std::simple_nft { let collection_address = object::object_address(&collection); assert!( exists(collection_address), - error::not_found(ECOLLECTION_DOES_NOT_EXIST), + error::not_found(ECOLLECTION_DOES_NOT_EXIST) ); assert!( collection::creator(collection) == signer::address_of(creator), - error::permission_denied(ENOT_CREATOR), + error::permission_denied(ENOT_CREATOR) ); borrow_global(collection_address) } public entry fun set_collection_description( - creator: &signer, - collection: Object, - description: String, + creator: &signer, collection: Object, description: String ) { initia_nft::set_collection_description(creator, collection, description); } public fun set_collection_royalties( - creator: &signer, - collection: Object, - royalty: royalty::Royalty, + creator: &signer, collection: Object, royalty: royalty::Royalty ) { initia_nft::set_collection_royalties(creator, collection, royalty); } @@ -415,17 +405,15 @@ module initia_std::simple_nft { entry fun set_collection_royalties_call( creator: &signer, collection: Object, - royalty: Decimal128, - payee_address: address, + royalty: BigDecimal, + payee_address: address ) { let royalty = royalty::create(royalty, payee_address); set_collection_royalties(creator, collection, royalty); } public entry fun set_collection_uri( - creator: &signer, - collection: Object, - uri: String, + creator: &signer, collection: Object, uri: String ) { initia_nft::set_collection_uri(creator, collection, uri); } @@ -436,7 +424,7 @@ module initia_std::simple_nft { use std::string; #[test_only] - use initia_std::decimal128; + use initia_std::bigdecimal; #[test(creator = @0x123)] fun test_create_and_transfer(creator: &signer) { @@ -448,7 +436,7 @@ module initia_std::simple_nft { assert!( object::owner(nft) == signer::address_of(creator), - 1, + 1 ); object::transfer(creator, nft, @0x345); assert!(object::owner(nft) == @0x345, 1); @@ -468,12 +456,12 @@ module initia_std::simple_nft { nft, property_name, property_type, - vector[0x08], + vector[0x08] ); assert!( property_map::read_u8(nft, &property_name) == 0x8, - 0, + 0 ); } @@ -489,7 +477,7 @@ module initia_std::simple_nft { assert!( property_map::read_u8(nft, &property_name) == 0x8, - 0, + 0 ); } @@ -507,12 +495,12 @@ module initia_std::simple_nft { nft, property_name, property_type, - vector[0x00], + vector[0x00] ); assert!( !property_map::read_bool(nft, &property_name), - 0, + 0 ); } @@ -528,7 +516,7 @@ module initia_std::simple_nft { assert!( !property_map::read_bool(nft, &property_name), - 0, + 0 ); } @@ -545,9 +533,7 @@ module initia_std::simple_nft { #[test_only] fun create_collection_helper( - creator: &signer, - collection_name: String, - flag: bool, + creator: &signer, collection_name: String, flag: bool ): Object { create_collection_object( creator, @@ -561,15 +547,13 @@ module initia_std::simple_nft { flag, flag, flag, - decimal128::from_ratio(1, 100), + bigdecimal::from_ratio_u64(1, 100) ) } #[test_only] fun mint_helper( - creator: &signer, - collection_name: String, - token_id: String, + creator: &signer, collection_name: String, token_id: String ): Object { mint_nft_object( creator, @@ -579,7 +563,7 @@ module initia_std::simple_nft { string::utf8(b"uri"), vector[string::utf8(b"bool")], vector[string::utf8(b"bool")], - vector[vector[0x01]], + vector[vector[0x01]] ) } } diff --git a/initia_stdlib/sources/token/soul_bound_token.move b/initia_stdlib/sources/token/soul_bound_token.move index 1577843..68c957d 100644 --- a/initia_stdlib/sources/token/soul_bound_token.move +++ b/initia_stdlib/sources/token/soul_bound_token.move @@ -6,11 +6,11 @@ module initia_std::soul_bound_token { use std::string::String; use std::signer; use initia_std::object::{Self, ConstructorRef, Object}; - use initia_std::collection; + use initia_std::collection::{Self, Collection}; use initia_std::property_map; use initia_std::royalty; use initia_std::nft; - use initia_std::decimal128::Decimal128; + use initia_std::bigdecimal::BigDecimal; /// The collection does not exist const ECOLLECTION_DOES_NOT_EXIST: u64 = 1; @@ -40,7 +40,7 @@ module initia_std::soul_bound_token { /// Determines if the creator can mutate nft properties mutable_nft_properties: bool, /// Determines if the creator can mutate nft uris - mutable_nft_uri: bool, + mutable_nft_uri: bool } /// Storage state for managing the no-code Token. @@ -48,7 +48,7 @@ module initia_std::soul_bound_token { /// Used to mutate fields mutator_ref: Option, /// Used to mutate properties - property_mutator_ref: property_map::MutatorRef, + property_mutator_ref: property_map::MutatorRef } /// Create a new collection @@ -65,7 +65,7 @@ module initia_std::soul_bound_token { mutable_nft_name: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, - royalty: Decimal128, + royalty: BigDecimal ) { create_collection_object( creator, @@ -80,7 +80,7 @@ module initia_std::soul_bound_token { mutable_nft_name, mutable_nft_properties, mutable_nft_uri, - royalty, + royalty ); } @@ -97,7 +97,7 @@ module initia_std::soul_bound_token { mutable_nft_name: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, - royalty: Decimal128, + royalty: BigDecimal ): Object { let creator_addr = signer::address_of(creator); let royalty = royalty::create(royalty, creator_addr); @@ -108,7 +108,7 @@ module initia_std::soul_bound_token { max_supply, name, option::some(royalty), - uri, + uri ); let object_signer = object::generate_signer(&constructor_ref); @@ -124,7 +124,7 @@ module initia_std::soul_bound_token { option::some( royalty::generate_mutator_ref( object::generate_extend_ref(&constructor_ref) - ), + ) ) } else { option::none() @@ -138,7 +138,7 @@ module initia_std::soul_bound_token { mutable_nft_description, mutable_nft_name, mutable_nft_properties, - mutable_nft_uri, + mutable_nft_uri }; move_to(&object_signer, soul_bound_token_collection); object::object_from_constructor_ref(&constructor_ref) @@ -154,7 +154,7 @@ module initia_std::soul_bound_token { property_keys: vector, property_types: vector, property_values: vector>, - soul_bound_to: address, + soul_bound_to: address ) acquires SoulBoundTokenCollection { mint_soul_bound_token_object( creator, @@ -165,7 +165,7 @@ module initia_std::soul_bound_token { property_keys, property_types, property_values, - soul_bound_to, + soul_bound_to ); } @@ -179,7 +179,7 @@ module initia_std::soul_bound_token { property_keys: vector, property_types: vector, property_values: vector>, - soul_bound_to: address, + soul_bound_to: address ): Object acquires SoulBoundTokenCollection { let constructor_ref = mint_internal( @@ -190,7 +190,7 @@ module initia_std::soul_bound_token { uri, property_keys, property_types, - property_values, + property_values ); let transfer_ref = object::generate_transfer_ref(&constructor_ref); @@ -203,28 +203,28 @@ module initia_std::soul_bound_token { fun mint_internal( creator: &signer, - collection: String, + collection_name: String, description: String, name: String, uri: String, property_keys: vector, property_types: vector, - property_values: vector>, + property_values: vector> ): ConstructorRef acquires SoulBoundTokenCollection { + let collection_obj = collection_object(creator, &collection_name); let constructor_ref = nft::create( creator, - collection, + object::convert(collection_obj), description, name, option::none(), - uri, + uri ); let s = object::generate_signer(&constructor_ref); let object_signer = object::generate_signer(&constructor_ref); - let collection_obj = collection_object(creator, &collection); let collection = borrow_collection(collection_obj); let mutator_ref = @@ -238,7 +238,7 @@ module initia_std::soul_bound_token { let soul_bound_token = SoulBoundToken { mutator_ref, - property_mutator_ref: property_map::generate_mutator_ref(&s), + property_mutator_ref: property_map::generate_mutator_ref(&s) }; move_to(&object_signer, soul_bound_token); @@ -246,7 +246,7 @@ module initia_std::soul_bound_token { property_map::prepare_input( property_keys, property_types, - property_values, + property_values ); property_map::init(&s, properties); @@ -259,7 +259,7 @@ module initia_std::soul_bound_token { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); borrow_global(nft_address) } @@ -291,45 +291,41 @@ module initia_std::soul_bound_token { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); assert!( nft::creator(nft) == signer::address_of(creator), - error::permission_denied(ENOT_CREATOR), + error::permission_denied(ENOT_CREATOR) ); borrow_global(nft_address) } public entry fun set_description( - creator: &signer, - nft: Object, - description: String, + creator: &signer, nft: Object, description: String ) acquires SoulBoundTokenCollection, SoulBoundToken { assert!( is_mutable_description(nft), - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); let soul_bound_token = authorized_borrow(nft, creator); nft::set_description( option::borrow(&soul_bound_token.mutator_ref), - description, + description ); } public entry fun set_uri( - creator: &signer, - nft: Object, - uri: String, + creator: &signer, nft: Object, uri: String ) acquires SoulBoundTokenCollection, SoulBoundToken { assert!( is_mutable_uri(nft), - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); let soul_bound_token = authorized_borrow(nft, creator); nft::set_uri( option::borrow(&soul_bound_token.mutator_ref), - uri, + uri ); } @@ -338,19 +334,19 @@ module initia_std::soul_bound_token { nft: Object, key: String, type: String, - value: vector, + value: vector ) acquires SoulBoundTokenCollection, SoulBoundToken { let soul_bound_token = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::add( &soul_bound_token.property_mutator_ref, key, type, - value, + value ); } @@ -358,30 +354,28 @@ module initia_std::soul_bound_token { creator: &signer, nft: Object, key: String, - value: V, + value: V ) acquires SoulBoundTokenCollection, SoulBoundToken { let soul_bound_token = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::add_typed( &soul_bound_token.property_mutator_ref, key, - value, + value ); } public entry fun remove_property( - creator: &signer, - nft: Object, - key: String, + creator: &signer, nft: Object, key: String ) acquires SoulBoundTokenCollection, SoulBoundToken { let soul_bound_token = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::remove(&soul_bound_token.property_mutator_ref, &key); @@ -392,19 +386,19 @@ module initia_std::soul_bound_token { nft: Object, key: String, type: String, - value: vector, + value: vector ) acquires SoulBoundTokenCollection, SoulBoundToken { let soul_bound_token = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::update( &soul_bound_token.property_mutator_ref, &key, type, - value, + value ); } @@ -412,25 +406,25 @@ module initia_std::soul_bound_token { creator: &signer, nft: Object, key: String, - value: V, + value: V ) acquires SoulBoundTokenCollection, SoulBoundToken { let soul_bound_token = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::update_typed( &soul_bound_token.property_mutator_ref, &key, - value, + value ); } // Collection accessors - inline fun collection_object(creator: &signer, name: &String) - : Object { + inline fun collection_object(creator: &signer, name: &String): + Object { let collection_addr = collection::create_collection_address(signer::address_of(creator), name); object::address_to_object(collection_addr) @@ -440,47 +434,49 @@ module initia_std::soul_bound_token { let collection_address = object::object_address(&nft); assert!( exists(collection_address), - error::not_found(ECOLLECTION_DOES_NOT_EXIST), + error::not_found(ECOLLECTION_DOES_NOT_EXIST) ); borrow_global(collection_address) } public fun is_mutable_collection_description( - collection: Object, + collection: Object ): bool acquires SoulBoundTokenCollection { borrow_collection(collection).mutable_description } public fun is_mutable_collection_royalty( - collection: Object, + collection: Object ): bool acquires SoulBoundTokenCollection { option::is_some(&borrow_collection(collection).royalty_mutator_ref) } - public fun is_mutable_collection_uri(collection: Object,): bool acquires SoulBoundTokenCollection { + public fun is_mutable_collection_uri( + collection: Object + ): bool acquires SoulBoundTokenCollection { borrow_collection(collection).mutable_uri } public fun is_mutable_collection_nft_description( - collection: Object, + collection: Object ): bool acquires SoulBoundTokenCollection { borrow_collection(collection).mutable_nft_description } public fun is_mutable_collection_nft_name( - collection: Object, + collection: Object ): bool acquires SoulBoundTokenCollection { borrow_collection(collection).mutable_nft_name } public fun is_mutable_collection_nft_uri( - collection: Object, + collection: Object ): bool acquires SoulBoundTokenCollection { borrow_collection(collection).mutable_nft_uri } public fun is_mutable_collection_nft_properties( - collection: Object, + collection: Object ): bool acquires SoulBoundTokenCollection { borrow_collection(collection).mutable_nft_properties } @@ -493,73 +489,67 @@ module initia_std::soul_bound_token { let collection_address = object::object_address(&collection); assert!( exists(collection_address), - error::not_found(ECOLLECTION_DOES_NOT_EXIST), + error::not_found(ECOLLECTION_DOES_NOT_EXIST) ); assert!( collection::creator(collection) == signer::address_of(creator), - error::permission_denied(ENOT_CREATOR), + error::permission_denied(ENOT_CREATOR) ); borrow_global(collection_address) } public entry fun set_collection_description( - creator: &signer, - collection: Object, - description: String, + creator: &signer, collection: Object, description: String ) acquires SoulBoundTokenCollection { let soul_bound_token_collection = authorized_borrow_collection(collection, creator); assert!( soul_bound_token_collection.mutable_description, - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); collection::set_description( option::borrow(&soul_bound_token_collection.mutator_ref), - description, + description ); } public fun set_collection_royalties( - creator: &signer, - collection: Object, - royalty: royalty::Royalty, + creator: &signer, collection: Object, royalty: royalty::Royalty ) acquires SoulBoundTokenCollection { let soul_bound_token_collection = authorized_borrow_collection(collection, creator); assert!( option::is_some(&soul_bound_token_collection.royalty_mutator_ref), - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); royalty::update( option::borrow(&soul_bound_token_collection.royalty_mutator_ref), - royalty, + royalty ); } entry fun set_collection_royalties_call( creator: &signer, collection: Object, - royalty: Decimal128, - payee_address: address, + royalty: BigDecimal, + payee_address: address ) acquires SoulBoundTokenCollection { let royalty = royalty::create(royalty, payee_address); set_collection_royalties(creator, collection, royalty); } public entry fun set_collection_uri( - creator: &signer, - collection: Object, - uri: String, + creator: &signer, collection: Object, uri: String ) acquires SoulBoundTokenCollection { let soul_bound_token_collection = authorized_borrow_collection(collection, creator); assert!( soul_bound_token_collection.mutable_uri, - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); collection::set_uri( option::borrow(&soul_bound_token_collection.mutator_ref), - uri, + uri ); } @@ -569,7 +559,7 @@ module initia_std::soul_bound_token { use std::string; #[test_only] - use initia_std::decimal128; + use initia_std::bigdecimal; #[test(creator = @0x123)] fun test_set_description(creator: &signer) acquires SoulBoundTokenCollection, SoulBoundToken { @@ -581,7 +571,7 @@ module initia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); let description = string::utf8(b"not"); @@ -592,7 +582,9 @@ module initia_std::soul_bound_token { #[test(creator = @0x123)] #[expected_failure(abort_code = 0x50004, location = Self)] - fun test_set_immutable_description(creator: &signer) acquires SoulBoundTokenCollection, SoulBoundToken { + fun test_set_immutable_description( + creator: &signer + ) acquires SoulBoundTokenCollection, SoulBoundToken { let collection_name = string::utf8(b"collection name"); let nft_name = string::utf8(b"nft name"); @@ -601,7 +593,7 @@ module initia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); set_description(creator, nft, string::utf8(b"")); @@ -610,7 +602,7 @@ module initia_std::soul_bound_token { #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] fun test_set_description_non_creator( - creator: &signer, noncreator: &signer, + creator: &signer, noncreator: &signer ) acquires SoulBoundTokenCollection, SoulBoundToken { let collection_name = string::utf8(b"collection name"); let nft_name = string::utf8(b"nft name"); @@ -620,7 +612,7 @@ module initia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); let description = string::utf8(b"not"); @@ -637,7 +629,7 @@ module initia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); let uri = string::utf8(b"not"); @@ -657,7 +649,7 @@ module initia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); set_uri(creator, nft, string::utf8(b"")); @@ -665,7 +657,9 @@ module initia_std::soul_bound_token { #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] - fun test_set_uri_non_creator(creator: &signer, noncreator: &signer,) acquires SoulBoundTokenCollection, SoulBoundToken { + fun test_set_uri_non_creator( + creator: &signer, noncreator: &signer + ) acquires SoulBoundTokenCollection, SoulBoundToken { let collection_name = string::utf8(b"collection name"); let nft_name = string::utf8(b"nft name"); @@ -674,7 +668,7 @@ module initia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); let uri = string::utf8(b"not"); @@ -688,38 +682,40 @@ module initia_std::soul_bound_token { let value = string::utf8(b"not"); assert!( collection::description(collection) != value, - 0, + 0 ); set_collection_description(creator, collection, value); assert!( collection::description(collection) == value, - 1, + 1 ); } #[test(creator = @0x123)] #[expected_failure(abort_code = 0x50004, location = Self)] - fun test_set_immutable_collection_description(creator: &signer) acquires SoulBoundTokenCollection { + fun test_set_immutable_collection_description( + creator: &signer + ) acquires SoulBoundTokenCollection { let collection_name = string::utf8(b"collection name"); let collection = create_collection_helper(creator, collection_name, false); set_collection_description( creator, collection, - string::utf8(b""), + string::utf8(b"") ); } #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] fun test_set_collection_description_non_creator( - creator: &signer, noncreator: &signer, + creator: &signer, noncreator: &signer ) acquires SoulBoundTokenCollection { let collection_name = string::utf8(b"collection name"); let collection = create_collection_helper(creator, collection_name, true); set_collection_description( noncreator, collection, - string::utf8(b""), + string::utf8(b"") ); } @@ -741,21 +737,21 @@ module initia_std::soul_bound_token { set_collection_uri( creator, collection, - string::utf8(b""), + string::utf8(b"") ); } #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] fun test_set_collection_uri_non_creator( - creator: &signer, noncreator: &signer, + creator: &signer, noncreator: &signer ) acquires SoulBoundTokenCollection { let collection_name = string::utf8(b"collection name"); let collection = create_collection_helper(creator, collection_name, true); set_collection_uri( noncreator, collection, - string::utf8(b""), + string::utf8(b"") ); } @@ -771,19 +767,19 @@ module initia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); add_property( creator, nft, property_name, property_type, - vector[0x08], + vector[0x08] ); assert!( property_map::read_u8(nft, &property_name) == 0x8, - 0, + 0 ); } @@ -798,13 +794,13 @@ module initia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); add_typed_property(creator, nft, property_name, 0x8); assert!( property_map::read_u8(nft, &property_name) == 0x8, - 0, + 0 ); } @@ -820,24 +816,26 @@ module initia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); update_property( creator, nft, property_name, property_type, - vector[0x00], + vector[0x00] ); assert!( !property_map::read_bool(nft, &property_name), - 0, + 0 ); } #[test(creator = @0x123)] - fun test_property_update_typed(creator: &signer) acquires SoulBoundTokenCollection, SoulBoundToken { + fun test_property_update_typed( + creator: &signer + ) acquires SoulBoundTokenCollection, SoulBoundToken { let collection_name = string::utf8(b"collection name"); let nft_name = string::utf8(b"nft name"); let property_name = string::utf8(b"bool"); @@ -847,13 +845,13 @@ module initia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); update_typed_property(creator, nft, property_name, false); assert!( !property_map::read_bool(nft, &property_name), - 0, + 0 ); } @@ -868,7 +866,7 @@ module initia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); remove_property(creator, nft, property_name); } @@ -883,15 +881,15 @@ module initia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); let royalty_before = option::extract(&mut nft::royalty(nft)); set_collection_royalties_call( creator, collection, - decimal128::from_ratio(2, 3), - @0x444, + bigdecimal::from_ratio_u64(2, 3), + @0x444 ); let royalty_after = option::extract(&mut nft::royalty(nft)); assert!(royalty_before != royalty_after, 0); @@ -899,9 +897,7 @@ module initia_std::soul_bound_token { #[test_only] fun create_collection_helper( - creator: &signer, - collection_name: String, - flag: bool, + creator: &signer, collection_name: String, flag: bool ): Object { create_collection_object( creator, @@ -916,7 +912,7 @@ module initia_std::soul_bound_token { flag, flag, flag, - decimal128::from_ratio(1, 100), + bigdecimal::from_ratio_u64(1, 100) ) } @@ -936,7 +932,7 @@ module initia_std::soul_bound_token { vector[string::utf8(b"bool")], vector[string::utf8(b"bool")], vector[vector[0x01]], - soul_bound_to, + soul_bound_to ) } } diff --git a/initia_stdlib/sources/transaction_context.move b/initia_stdlib/sources/transaction_context.move index 634d958..34268c7 100644 --- a/initia_stdlib/sources/transaction_context.move +++ b/initia_stdlib/sources/transaction_context.move @@ -12,6 +12,18 @@ module initia_std::transaction_context { #[test_only] native fun get_session_id(): vector; + #[test_only] + use initia_std::vector; + + #[test_only] + public fun set_transaction_hash(transaction_hash: vector) { + assert!(vector::length(&transaction_hash) == 32, 100); + set_transaction_hash_internal(transaction_hash); + } + + #[test_only] + native fun set_transaction_hash_internal(transaction_hash: vector); + #[test] fun test_address_uniquess() { use std::vector; @@ -23,7 +35,7 @@ module initia_std::transaction_context { i = i + 1; vector::push_back( &mut addrs, - generate_unique_address(), + generate_unique_address() ); }; @@ -33,7 +45,7 @@ module initia_std::transaction_context { while (j < count) { assert!( *vector::borrow(&addrs, i) != *vector::borrow(&addrs, j), - 0, + 0 ); j = j + 1; }; @@ -63,4 +75,16 @@ module initia_std::transaction_context { let addr2 = initia_std::from_bcs::to_address(std::hash::sha3_256(bytes)); assert!(addr1 == addr2, 0); } + + #[test] + fun test_get_transaction_hash() { + set_transaction_hash( + x"0000000000000000000000000000000000000000000000000000000000000001" + ); + assert!( + get_transaction_hash() + == x"0000000000000000000000000000000000000000000000000000000000000001", + 0 + ); + } } diff --git a/initia_stdlib/sources/type_info.move b/initia_stdlib/sources/type_info.move index 7bdb0b0..f971b05 100644 --- a/initia_stdlib/sources/type_info.move +++ b/initia_stdlib/sources/type_info.move @@ -4,7 +4,7 @@ module initia_std::type_info { struct TypeInfo has copy, drop, store { account_address: address, module_name: vector, - struct_name: vector, + struct_name: vector } public fun account_address(type_info: &TypeInfo): address { @@ -42,39 +42,39 @@ module initia_std::type_info { assert!(type_name() == string::utf8(b"u128"), 3); assert!( type_name
() == string::utf8(b"address"), - 4, + 4 ); assert!( type_name() == string::utf8(b"signer"), - 5, + 5 ); // vector assert!( type_name>() == string::utf8(b"vector"), - 6, + 6 ); assert!( type_name>>() == string::utf8(b"vector>"), - 7, + 7 ); assert!( type_name>>() == string::utf8(b"vector>"), - 8, + 8 ); // struct assert!( type_name() == string::utf8(b"0x1::type_info::TypeInfo"), - 9, + 9 ); assert!( type_name>>>() == string::utf8( - b"0x1::table::Table<0x1::type_info::TypeInfo, 0x1::table::Table>>", + b"0x1::table::Table<0x1::type_info::TypeInfo, 0x1::table::Table>>" ), - 10, + 10 ); } } diff --git a/initia_stdlib/sources/vip/operator.move b/initia_stdlib/sources/vip/operator.move deleted file mode 100644 index e7bea24..0000000 --- a/initia_stdlib/sources/vip/operator.move +++ /dev/null @@ -1,418 +0,0 @@ -module initia_std::vip_operator { - use std::error; - use std::signer; - use std::vector; - use std::event; - - use initia_std::object; - use initia_std::decimal256::{Self, Decimal256}; - use initia_std::bcs; - - friend initia_std::vip; - // - // Errors - // - - const EOPERATOR_STORE_ALREADY_EXISTS: u64 = 1; - const EOPERATOR_STORE_NOT_FOUND: u64 = 2; - const EINVALID_COMMISSION_CHANGE_RATE: u64 = 3; - const EOVER_MAX_COMMISSION_RATE: u64 = 4; - const EINVALID_STAGE: u64 = 5; - const EINVALID_COMMISSION_RATE: u64 = 6; - const EUNAUTHORIZED: u64 = 7; - - // - // Constants - // - - const OPERATOR_STORE_PREFIX: u8 = 0xf6; - - // - // Resources - // - - struct OperatorStore has key { - last_changed_stage: u64, - commission_max_rate: Decimal256, - commission_max_change_rate: Decimal256, - commission_rate: Decimal256, - } - - // - // Responses - // - - struct OperatorStoreResponse has drop { - last_changed_stage: u64, - commission_max_rate: Decimal256, - commission_max_change_rate: Decimal256, - commission_rate: Decimal256, - } - - // - // Events - // - - #[event] - struct UpdateCommissionEvent has drop, store { - operator: address, - bridge_id: u64, - stage: u64, - commission_rate: Decimal256, - } - - // - // Helper Functions - // - - fun check_chain_permission(chain: &signer) { - assert!( - signer::address_of(chain) == @initia_std, - error::permission_denied(EUNAUTHORIZED), - ); - } - - fun check_valid_rate(rate: &Decimal256) { - assert!( - decimal256::val(rate) <= decimal256::val(&decimal256::one()), - error::invalid_argument(EINVALID_COMMISSION_RATE), - ); - } - - fun is_valid_commission_rates( - commission_max_rate: &Decimal256, - commission_max_change_rate: &Decimal256, - commission_rate: &Decimal256 - ) { - check_valid_rate(commission_max_rate); - check_valid_rate(commission_max_change_rate); - check_valid_rate(commission_rate); - assert!( - decimal256::val(commission_rate) <= decimal256::val(commission_max_rate), - error::invalid_argument(EOVER_MAX_COMMISSION_RATE), - ); - } - - // - // Friend Functions - // - - public(friend) fun register_operator_store( - chain: &signer, - operator: address, - bridge_id: u64, - stage: u64, - commission_max_rate: Decimal256, - commission_max_change_rate: Decimal256, - commission_rate: Decimal256 - ) { - check_chain_permission(chain); - let seed = generate_operator_store_seed(operator, bridge_id); - let operator_addr = - object::create_object_address(&signer::address_of(chain), seed); - assert!( - !exists(operator_addr), - error::already_exists(EOPERATOR_STORE_ALREADY_EXISTS), - ); - - is_valid_commission_rates( - &commission_max_rate, - &commission_max_change_rate, - &commission_rate, - ); - - let constructor_ref = object::create_named_object(chain, seed); - let transfer_ref = object::generate_transfer_ref(&constructor_ref); - object::disable_ungated_transfer(&transfer_ref); - let object = object::generate_signer(&constructor_ref); - - let operator_store = OperatorStore { - last_changed_stage: stage, - commission_max_rate, - commission_max_change_rate, - commission_rate, - }; - move_to(&object, operator_store); - } - - public(friend) fun update_operator_commission( - operator: &signer, - bridge_id: u64, - stage: u64, - commission_rate: Decimal256 - ) acquires OperatorStore { - let operator_addr = signer::address_of(operator); - let operator_store_addr = get_operator_store_address(operator_addr, bridge_id); - let operator_store = borrow_global_mut(operator_store_addr); - - // commission can be updated once per a stage. - assert!( - stage > operator_store.last_changed_stage, - error::invalid_argument(EINVALID_STAGE), - ); - - let old_commission_rate = decimal256::val(&operator_store.commission_rate); - let new_commission_rate = decimal256::val(&commission_rate); - let max_commission_change_rate = - decimal256::val(&operator_store.commission_max_change_rate); - let max_commission_rate = decimal256::val(&operator_store.commission_max_rate); - - assert!( - new_commission_rate <= max_commission_rate, - error::invalid_argument(EOVER_MAX_COMMISSION_RATE), - ); - - let change = - if (old_commission_rate > new_commission_rate) { - old_commission_rate - new_commission_rate - } else { - new_commission_rate - old_commission_rate - }; - - assert!( - change <= max_commission_change_rate, - error::invalid_argument(EINVALID_COMMISSION_CHANGE_RATE), - ); - - operator_store.commission_rate = commission_rate; - operator_store.last_changed_stage = stage; - - event::emit( - UpdateCommissionEvent { - operator: operator_addr, - bridge_id: bridge_id, - stage: operator_store.last_changed_stage, - commission_rate - }, - ); - } - - // - // Helper Functions - // - - fun generate_operator_store_seed(operator: address, bridge_id: u64): vector { - let seed = vector[OPERATOR_STORE_PREFIX]; - vector::append(&mut seed, bcs::to_bytes(&operator)); - vector::append(&mut seed, bcs::to_bytes(&bridge_id)); - return seed - } - - fun create_operator_store_address( - operator_addr: address, bridge_id: u64 - ): address { - let seed = generate_operator_store_seed(operator_addr, bridge_id); - object::create_object_address(&@initia_std, seed) - } - - // - // View Functions - // - - #[view] - public fun is_operator_store_registered( - operator_addr: address, bridge_id: u64 - ): bool { - exists(create_operator_store_address(operator_addr, bridge_id)) - } - - #[view] - public fun get_operator_store_address( - operator_addr: address, bridge_id: u64 - ): address { - let operator_store_addr = create_operator_store_address(operator_addr, bridge_id); - assert!( - exists(operator_store_addr), - error::not_found(EOPERATOR_STORE_NOT_FOUND), - ); - operator_store_addr - } - - #[view] - public fun get_operator_store(operator: address, bridge_id: u64): OperatorStoreResponse acquires OperatorStore { - let operator_store_addr = get_operator_store_address(operator, bridge_id); - let operator_store = borrow_global(operator_store_addr); - OperatorStoreResponse { - last_changed_stage: operator_store.last_changed_stage, - commission_max_rate: operator_store.commission_max_rate, - commission_max_change_rate: operator_store.commission_max_change_rate, - commission_rate: operator_store.commission_rate, - } - } - - #[view] - public fun get_operator_commission(operator: address, bridge_id: u64): Decimal256 acquires OperatorStore { - let operator_store_addr = get_operator_store_address(operator, bridge_id); - let operator_store = borrow_global(operator_store_addr); - operator_store.commission_rate - } - - // - // Tests - // - - #[test_only] - use std::string; - - #[test(chain = @0x1, operator = @0x999)] - fun test_update_operator_commission( - chain: &signer, operator: &signer, - ) acquires OperatorStore { - let bridge_id = 1; - let operator_addr = signer::address_of(operator); - - register_operator_store( - chain, - operator_addr, - bridge_id, - 10, - decimal256::from_string(&string::utf8(b"0.2")), - decimal256::from_string(&string::utf8(b"0.2")), - decimal256::from_string(&string::utf8(b"0")), - ); - - assert!( - get_operator_store(operator_addr, bridge_id) - == OperatorStoreResponse { - last_changed_stage: 10, - commission_max_rate: decimal256::from_string(&string::utf8(b"0.2")), - commission_max_change_rate: decimal256::from_string( - &string::utf8(b"0.2") - ), - commission_rate: decimal256::from_string(&string::utf8(b"0")), - }, - 1, - ); - - update_operator_commission( - operator, - bridge_id, - 11, - decimal256::from_string(&string::utf8(b"0.2")), - ); - - assert!( - get_operator_store(operator_addr, bridge_id) - == OperatorStoreResponse { - last_changed_stage: 11, - commission_max_rate: decimal256::from_string(&string::utf8(b"0.2")), - commission_max_change_rate: decimal256::from_string( - &string::utf8(b"0.2") - ), - commission_rate: decimal256::from_string(&string::utf8(b"0.2")), - }, - 2, - ); - - update_operator_commission( - operator, - bridge_id, - 12, - decimal256::from_string(&string::utf8(b"0.1")), - ); - - assert!( - get_operator_store(operator_addr, bridge_id) - == OperatorStoreResponse { - last_changed_stage: 12, - commission_max_rate: decimal256::from_string(&string::utf8(b"0.2")), - commission_max_change_rate: decimal256::from_string( - &string::utf8(b"0.2") - ), - commission_rate: decimal256::from_string(&string::utf8(b"0.1")), - }, - 3, - ); - } - - #[test(chain = @0x1, operator = @0x999)] - #[expected_failure(abort_code = 0x10003, location = Self)] - fun failed_invalid_change_rate(chain: &signer, operator: &signer,) acquires OperatorStore { - let bridge_id = 1; - let operator_addr = signer::address_of(operator); - - register_operator_store( - chain, - operator_addr, - bridge_id, - 10, - decimal256::from_string(&string::utf8(b"0.2")), - decimal256::from_string(&string::utf8(b"0.1")), - decimal256::from_string(&string::utf8(b"0")), - ); - - update_operator_commission( - operator, - bridge_id, - 11, - decimal256::from_string(&string::utf8(b"0.2")), - ); - } - - #[test(chain = @0x1, operator = @0x999)] - #[expected_failure(abort_code = 0x10004, location = Self)] - fun failed_over_max_rate(chain: &signer, operator: &signer,) acquires OperatorStore { - let bridge_id = 1; - let operator_addr = signer::address_of(operator); - - register_operator_store( - chain, - operator_addr, - bridge_id, - 10, - decimal256::from_string(&string::utf8(b"0.2")), - decimal256::from_string(&string::utf8(b"0.2")), - decimal256::from_string(&string::utf8(b"0")), - ); - - update_operator_commission( - operator, - bridge_id, - 11, - decimal256::from_string(&string::utf8(b"0.3")), - ); - } - - #[test(chain = @0x1, operator = @0x999)] - #[expected_failure(abort_code = 0x10005, location = Self)] - fun failed_not_valid_stage(chain: &signer, operator: &signer,) acquires OperatorStore { - let bridge_id = 1; - let operator_addr = signer::address_of(operator); - - register_operator_store( - chain, - operator_addr, - bridge_id, - 10, - decimal256::from_string(&string::utf8(b"0.2")), - decimal256::from_string(&string::utf8(b"0.2")), - decimal256::from_string(&string::utf8(b"0")), - ); - - update_operator_commission( - operator, - bridge_id, - 10, - decimal256::from_string(&string::utf8(b"0")), - ); - } - - #[test(chain = @0x1, operator = @0x999)] - #[expected_failure(abort_code = 0x10006, location = Self)] - fun failed_invalid_commission_rate( - chain: &signer, operator: &signer, - ) { - let bridge_id = 1; - let operator_addr = signer::address_of(operator); - - register_operator_store( - chain, - operator_addr, - bridge_id, - 10, - decimal256::from_string(&string::utf8(b"0.2")), - decimal256::from_string(&string::utf8(b"0.2")), - decimal256::from_string(&string::utf8(b"1.5")), - ); - } -} diff --git a/initia_stdlib/sources/vip/reward.move b/initia_stdlib/sources/vip/reward.move deleted file mode 100644 index 78a0ae9..0000000 --- a/initia_stdlib/sources/vip/reward.move +++ /dev/null @@ -1,180 +0,0 @@ -module initia_std::vip_reward { - use std::error; - use std::string; - use std::signer; - use std::vector; - - use initia_std::object::{Self, Object, ExtendRef}; - use initia_std::fungible_asset::{Metadata, FungibleAsset, FungibleStore}; - use initia_std::primary_fungible_store; - use initia_std::table; - use initia_std::table_key; - use initia_std::coin; - use initia_std::bcs; - use initia_std::fungible_asset; - use initia_std::type_info; - - friend initia_std::vip_weight_vote; - friend initia_std::vip_vesting; - friend initia_std::vip_zapping; - friend initia_std::vip_vault; - friend initia_std::vip; - - // - // Errors - // - - const EREWARD_STORE_ALREADY_EXISTS: u64 = 1; - const EREWARD_STORE_NOT_FOUND: u64 = 2; - - // - // Constants - // - - const OPERATOR_REWARD_PREFIX: u8 = 0xf2; - const USER_REWARD_PREFIX: u8 = 0xf3; - const REWARD_SYMBOL: vector = b"uinit"; - - // - // Resources - // - - struct RewardStore has key { - extend_ref: ExtendRef, - reward_store: Object, - reward_per_stage: table::Table /* stage */, u64>, - } - - // - // Public Functions - // - - public fun reward_metadata(): Object { - coin::metadata(@initia_std, string::utf8(REWARD_SYMBOL)) - } - - // - // Helper Functions - // - - fun generate_reward_store_seed( - bridge_id: u64 - ): vector { - let seed = - if (type_info::type_name() - == string::utf8(b"0x1::vip_vesting::OperatorVesting")) { - vector[OPERATOR_REWARD_PREFIX] - } else { - vector[USER_REWARD_PREFIX] - }; - - vector::append(&mut seed, bcs::to_bytes(&bridge_id)); - return seed - } - - fun create_reward_store_address( - bridge_id: u64 - ): address { - let seed = generate_reward_store_seed(bridge_id); - object::create_object_address(&@initia_std, seed) - } - - // - // Friend Functions - // - - public(friend) fun register_reward_store( - chain: &signer, bridge_id: u64, - ) { - let seed = generate_reward_store_seed(bridge_id); - let reward_store_addr = - object::create_object_address(&signer::address_of(chain), seed); - assert!( - !exists(reward_store_addr), - error::already_exists(EREWARD_STORE_ALREADY_EXISTS), - ); - - let constructor_ref = object::create_named_object(chain, seed); - let object = object::generate_signer(&constructor_ref); - let extend_ref = object::generate_extend_ref(&constructor_ref); - let reward_store = - primary_fungible_store::ensure_primary_store_exists( - reward_store_addr, reward_metadata() - ); - - move_to( - &object, - RewardStore { - extend_ref, - reward_store, - reward_per_stage: table::new, u64>(), - }, - ); - } - - public(friend) fun add_reward_per_stage( - reward_store_addr: address, stage: u64, reward: u64 - ) acquires RewardStore { - let reward_store = borrow_global_mut(reward_store_addr); - let stage_reward = - table::borrow_mut_with_default( - &mut reward_store.reward_per_stage, - table_key::encode_u64(stage), - 0, - ); - *stage_reward = *stage_reward + reward; - } - - public(friend) fun withdraw(reward_store_addr: address, amount: u64,): FungibleAsset acquires RewardStore { - let reward_store = borrow_global(reward_store_addr); - let reward_signer = - object::generate_signer_for_extending(&reward_store.extend_ref); - - fungible_asset::withdraw( - &reward_signer, - reward_store.reward_store, - amount, - ) - } - - // - // View Functions - // - - #[view] - public fun balance(reward_store_addr: address): u64 { - primary_fungible_store::balance(reward_store_addr, reward_metadata()) - } - - #[view] - public fun get_stage_reward(reward_store_addr: address, stage: u64): u64 acquires RewardStore { - let reward_store = borrow_global(reward_store_addr); - - let stage_reward = - table::borrow_with_default( - &reward_store.reward_per_stage, - table_key::encode_u64(stage), - &0, - ); - *stage_reward - } - - #[view] - public fun is_reward_store_registered( - bridge_id: u64 - ): bool { - exists(create_reward_store_address(bridge_id)) - } - - #[view] - public fun get_reward_store_address( - bridge_id: u64 - ): address { - let reward_addr = create_reward_store_address(bridge_id); - assert!( - exists(reward_addr), - error::not_found(EREWARD_STORE_NOT_FOUND), - ); - reward_addr - } -} diff --git a/initia_stdlib/sources/vip/tvl_manager.move b/initia_stdlib/sources/vip/tvl_manager.move deleted file mode 100644 index f7201d0..0000000 --- a/initia_stdlib/sources/vip/tvl_manager.move +++ /dev/null @@ -1,242 +0,0 @@ -module initia_std::vip_tvl_manager { - use std::error; - use initia_std::vector; - use initia_std::option; - use initia_std::table_key; - use initia_std::table; - use initia_std::block; - friend initia_std::vip; - const EINVALID_EPOCH: u64 = 1; - /// - const EINVALID_BRIDGE_ID: u64 = 2; - struct ModuleStore has key { - // The average tvl each epoch(vip stage) and bridge id - average_tvl: table::Table /*epoch*/, table::Table /*bridge id*/, table::Table /*count*/, TVLSnapshot>>> - } - - struct TVLSnapshot has store { - time: u64, - tvl: u64, - } - - struct TVLSnapshotResponse has drop, store { - time: u64, - tvl: u64, - } - - fun init_module(chain: &signer) { - move_to( - chain, - ModuleStore { - average_tvl: table::new /*epoch*/, table::Table /*bridge id*/, table::Table /*count*/, TVLSnapshot>>>() - }, - ); - - } - - // add the snapshot of the tvl on the bridge at the epoch - public(friend) fun add_snapshot( - epoch: u64, bridge_id: u64, balance: u64 - ) acquires ModuleStore { - let (_, block_time) = block::get_block_info(); - let module_store = borrow_global_mut(@initia_std); - - // create the average tvl table for the epoch(vip stage) if not exist - if (!table::contains( - &module_store.average_tvl, - table_key::encode_u64(epoch), - )) { - table::add( - &mut module_store.average_tvl, - table_key::encode_u64(epoch), - table::new /*bridge id*/, table::Table /*count*/, TVLSnapshot>>(), - ); - }; - let average_tvl_epoch = - table::borrow_mut( - &mut module_store.average_tvl, - table_key::encode_u64(epoch), - ); - if (!table::contains( - average_tvl_epoch, - table_key::encode_u64(bridge_id), - )) { - table::add( - average_tvl_epoch, - table_key::encode_u64(bridge_id), - table::new /*count*/, TVLSnapshot>(), - ); - }; - let average_tvl_table = - table::borrow_mut( - average_tvl_epoch, - table_key::encode_u64(bridge_id), - ); - let count = table::length(average_tvl_table); - - // add the snapshot of the tvl and block time - let snapshot = TVLSnapshot { time: block_time, tvl: balance, }; - table::add( - average_tvl_table, - table_key::encode_u64(count), - snapshot, - ); - } - - // calculate the average tvl of the bridge at the epoch from accumulated snapshots - public fun calculate_average_tvl( - epoch_key: vector, bridge_id_key: vector - ): u64 acquires ModuleStore { - let module_store = borrow_global_mut(@initia_std); - if (!table::contains( - &module_store.average_tvl, - epoch_key, - )) { - return 0 - }; - let tvl_by_epoch = table::borrow_mut(&mut module_store.average_tvl, epoch_key); - if (!table::contains(tvl_by_epoch, bridge_id_key)) { - return 0 - }; - let tvl_by_bridge_id = table::borrow_mut(tvl_by_epoch, bridge_id_key); - let total_snapshot_count = table::length(tvl_by_bridge_id); - let iter = table::iter( - tvl_by_bridge_id, - option::none(), - option::none(), - 1, - ); - let total_tvl = 0; - loop { - if (!table::prepare, TVLSnapshot>(iter)) { break }; - let (_, snapshot) = table::next, TVLSnapshot>(iter); - total_tvl = total_tvl + snapshot.tvl; - }; - - total_tvl / total_snapshot_count - } - - #[view] - public fun get_average_tvl(epoch: u64, bridge_id: u64): u64 acquires ModuleStore { - calculate_average_tvl( - table_key::encode_u64(epoch), - table_key::encode_u64(bridge_id), - ) - } - - #[view] - public fun get_snapshots(epoch: u64, bridge_id: u64): vector acquires ModuleStore { - let module_store = borrow_global_mut(@initia_std); - if (!table::contains( - &module_store.average_tvl, - table_key::encode_u64(epoch), - )) { - assert!( - false, - error::not_found(EINVALID_EPOCH), - ); - }; - let average_tvl_epoch = - table::borrow_mut( - &mut module_store.average_tvl, - table_key::encode_u64(epoch), - ); - if (!table::contains( - average_tvl_epoch, - table_key::encode_u64(bridge_id), - )) { - assert!( - false, - error::not_found(EINVALID_BRIDGE_ID), - ); - }; - let average_tvl_table = - table::borrow_mut( - average_tvl_epoch, - table_key::encode_u64(bridge_id), - ); - let count = table::length(average_tvl_table); - let snapshots = vector::empty(); - let i = 0; - loop { - if (i >= count) break; - let snapshot = table::borrow( - average_tvl_table, - table_key::encode_u64(i), - ); - vector::push_back( - &mut snapshots, - TVLSnapshotResponse { time: snapshot.time, tvl: snapshot.tvl, }, - ); - }; - snapshots - } - - #[test_only] - const DEFAULT_EPOCH_FOR_TEST: u64 = 1; - - #[test_only] - const DEFAULT_BRIDE_ID_FOR_TEST: u64 = 2; - - #[test_only] - const DEFAULT_SKIP_FOR_TEST: u64 = 100; - #[test_only] - public fun init_module_for_test() { - init_module(&initia_std::account::create_signer_for_test(@initia_std)); - } - - #[test_only] - fun skip_period(period: u64) { - let (height, curr_time) = block::get_block_info(); - block::set_block_info(height, curr_time + period); - } - - #[test] - public fun add_snapshot_for_test() acquires ModuleStore { - init_module_for_test(); - let balance = 1_000_000_000_000; - add_snapshot( - DEFAULT_EPOCH_FOR_TEST, - DEFAULT_BRIDE_ID_FOR_TEST, - balance, - ); - - let average_tvl = - calculate_average_tvl( - table_key::encode_u64(DEFAULT_EPOCH_FOR_TEST), - table_key::encode_u64(DEFAULT_BRIDE_ID_FOR_TEST), - ); - assert!(average_tvl == balance, 0); - } - - #[test] - public fun add_multi_snapshot_for_test() acquires ModuleStore { - init_module_for_test(); - let balance1 = 1_000_000_000_000; - let balance2 = 2_000_000_000_000; - let balance3 = 3_000_000_000_000; - add_snapshot( - DEFAULT_EPOCH_FOR_TEST, - DEFAULT_BRIDE_ID_FOR_TEST, - balance1, - ); - skip_period(DEFAULT_SKIP_FOR_TEST); - add_snapshot( - DEFAULT_EPOCH_FOR_TEST, - DEFAULT_BRIDE_ID_FOR_TEST, - balance2, - ); - skip_period(DEFAULT_SKIP_FOR_TEST); - add_snapshot( - DEFAULT_EPOCH_FOR_TEST, - DEFAULT_BRIDE_ID_FOR_TEST, - balance3, - ); - let average_tvl = - calculate_average_tvl( - table_key::encode_u64(DEFAULT_EPOCH_FOR_TEST), - table_key::encode_u64(DEFAULT_BRIDE_ID_FOR_TEST), - ); - assert!(average_tvl == 2_000_000_000_000, 0); - } -} diff --git a/initia_stdlib/sources/vip/vault.move b/initia_stdlib/sources/vip/vault.move deleted file mode 100644 index 402df04..0000000 --- a/initia_stdlib/sources/vip/vault.move +++ /dev/null @@ -1,167 +0,0 @@ -module initia_std::vip_vault { - use std::error; - use std::signer; - - use initia_std::object::{Self, ExtendRef}; - use initia_std::fungible_asset::FungibleAsset; - use initia_std::primary_fungible_store; - use initia_std::fungible_asset; - use initia_std::vip_reward; - - friend initia_std::vip; - - // - // Errors - // - - const EINVALID_AMOUNT: u64 = 1; - const EINVALID_STAGE: u64 = 2; - const EUNAUTHORIZED: u64 = 3; - const EINVALID_REWARD_PER_STAGE: u64 = 4; - - // - // Constants - // - - const VAULT_PREFIX: u8 = 0xf1; - const REWARD_SYMBOL: vector = b"uinit"; - - // - // Resources - // - - struct ModuleStore has key { - extend_ref: ExtendRef, - claimable_stage: u64, - reward_per_stage: u64, - vault_store_addr: address, - } - - // - // Implementations - // - - fun init_module(chain: &signer) { - let seed = generate_vault_store_seed(); - let vault_store_addr = - object::create_object_address(&signer::address_of(chain), seed); - - let constructor_ref = object::create_named_object(chain, seed); - let extend_ref = object::generate_extend_ref(&constructor_ref); - - move_to( - chain, - ModuleStore { - extend_ref, - claimable_stage: 1, - reward_per_stage: 0, // set zero for safety - vault_store_addr - }, - ); - } - - fun check_chain_permission(chain: &signer) { - assert!( - signer::address_of(chain) == @initia_std, - error::permission_denied(EUNAUTHORIZED), - ); - } - - fun generate_vault_store_seed(): vector { - let seed = vector[VAULT_PREFIX]; - return seed - } - - // - // Friend Functions - // - - public(friend) fun get_vault_store_address(): address acquires ModuleStore { - borrow_global(@initia_std).vault_store_addr - } - - public(friend) fun claim(stage: u64,): FungibleAsset acquires ModuleStore { - let module_store = borrow_global_mut(@initia_std); - assert!( - stage == module_store.claimable_stage, - error::invalid_argument(EINVALID_STAGE), - ); - assert!( - module_store.reward_per_stage > 0, - error::invalid_state(EINVALID_REWARD_PER_STAGE), - ); - - module_store.claimable_stage = stage + 1; - let vault_signer = - object::generate_signer_for_extending(&module_store.extend_ref); - let vault_store = - primary_fungible_store::ensure_primary_store_exists( - module_store.vault_store_addr, - vip_reward::reward_metadata(), - ); - fungible_asset::withdraw( - &vault_signer, - vault_store, - module_store.reward_per_stage, - ) - } - - // - // Entry Functions - // - - public entry fun deposit(funder: &signer, amount: u64) acquires ModuleStore { - let vault_store_addr = get_vault_store_address(); - assert!( - amount > 0, - error::invalid_argument(EINVALID_AMOUNT), - ); - primary_fungible_store::transfer( - funder, - vip_reward::reward_metadata(), - vault_store_addr, - amount, - ); - } - - public entry fun update_reward_per_stage( - chain: &signer, reward_per_stage: u64 - ) acquires ModuleStore { - check_chain_permission(chain); - - let vault_store = borrow_global_mut(@initia_std); - assert!( - reward_per_stage > 0, - error::invalid_argument(EINVALID_REWARD_PER_STAGE), - ); - vault_store.reward_per_stage = reward_per_stage; - } - - // - // View Functions - // - - #[view] - public fun balance(): u64 acquires ModuleStore { - let vault_store_addr = get_vault_store_address(); - primary_fungible_store::balance( - vault_store_addr, - vip_reward::reward_metadata(), - ) - } - - #[view] - public fun reward_per_stage(): u64 acquires ModuleStore { - let vault_store = borrow_global(@initia_std); - vault_store.reward_per_stage - } - - // - // Tests - // - - #[test_only] - public fun init_module_for_test() { - init_module(&initia_std::account::create_signer_for_test(@initia_std)); - } -} diff --git a/initia_stdlib/sources/vip/vesting.move b/initia_stdlib/sources/vip/vesting.move deleted file mode 100644 index e192d8a..0000000 --- a/initia_stdlib/sources/vip/vesting.move +++ /dev/null @@ -1,1237 +0,0 @@ -module initia_std::vip_vesting { - use std::error; - use std::signer; - use std::vector; - use std::option; - use std::event; - - use initia_std::object; - use initia_std::fungible_asset::{Self, FungibleAsset}; - use initia_std::primary_fungible_store; - use initia_std::table; - use initia_std::table_key; - use initia_std::decimal256::{Self, Decimal256}; - use initia_std::bcs; - use initia_std::vip_reward; - use initia_std::type_info; - - friend initia_std::vip; - - // - // Errors - // - - const EVESTING_STORE_ALREADY_EXISTS: u64 = 1; - const EVESTING_STORE_NOT_FOUND: u64 = 2; - const EVESTING_ALREADY_CLAIMED: u64 = 3; - const EVESTING_NOT_FOUND: u64 = 4; - const EVESTING_NOT_CLAIMED: u64 = 5; - const ESTAGE_ALREADY_CLAIMED: u64 = 6; - const EREWARD_NOT_ENOUGH: u64 = 7; - const EINVALID_VESTING_TYPE: u64 = 8; - - // - // Constants - // - - const USER_VESTING_PREFIX: u8 = 0xf4; - const OPERATOR_VESTING_PREFIX: u8 = 0xf5; - - const REWARD_SYMBOL: vector = b"uinit"; - - // - // Resources - // - - struct VestingStore has key { - claimed_stages: table::Table, bool>, - vestings: table::Table /* vesting start stage */, Vesting>, - vestings_finalized: table::Table /* vesting start stage */, Vesting>, - } - - struct UserVesting has copy, drop, store { - initial_reward: u64, - remaining_reward: u64, - start_stage: u64, - end_stage: u64, - l2_score: u64, - minimum_score: u64, - } - - struct OperatorVesting has copy, drop, store { - initial_reward: u64, - remaining_reward: u64, - start_stage: u64, - end_stage: u64, - } - - struct VestingChange has drop, store { - vesting_start_stage: u64, - initial_reward: u64, - remaining_reward: u64, - } - - // - // Events - // - - #[event] - struct UserVestingCreateEvent has drop, store { - account: address, - bridge_id: u64, - start_stage: u64, - end_stage: u64, - l2_score: u64, - minimum_score: u64, - initial_reward: u64, - } - - #[event] - struct OperatorVestingCreateEvent has drop, store { - account: address, - bridge_id: u64, - start_stage: u64, - end_stage: u64, - initial_reward: u64, - } - - #[event] - struct UserVestingFinalizedEvent has drop, store { - account: address, - bridge_id: u64, - stage: u64, - remaining_reward: u64, - } - - #[event] - struct OperatorVestingFinalizedEvent has drop, store { - account: address, - bridge_id: u64, - stage: u64, - remaining_reward: u64, - } - - #[event] - struct UserVestingClaimEvent has drop, store { - account: address, - bridge_id: u64, - stage: u64, - vesting_reward_amount: u64, - vested_reward_amount: u64, - vesting_changes: vector, - } - - #[event] - struct OperatorVestingClaimEvent has drop, store { - account: address, - bridge_id: u64, - stage: u64, - vesting_reward_amount: u64, - vested_reward_amount: u64, - vesting_changes: vector, - } - - // - // Implementations - // - - fun register_vesting_store( - account: &signer, bridge_id: u64 - ) { - let seed = generate_vesting_store_seed(bridge_id); - let vesting_addr = - object::create_object_address(&signer::address_of(account), seed); - assert!( - !exists>(vesting_addr), - error::already_exists(EVESTING_STORE_ALREADY_EXISTS), - ); - - let constructor_ref = object::create_named_object(account, seed); - let transfer_ref = object::generate_transfer_ref(&constructor_ref); - object::disable_ungated_transfer(&transfer_ref); - let object = object::generate_signer(&constructor_ref); - - let vesting_store = VestingStore { - claimed_stages: table::new, bool>(), - vestings: table::new, Vesting>(), - vestings_finalized: table::new, Vesting>(), - }; - move_to(&object, vesting_store); - } - - fun generate_vesting_store_seed( - bridge_id: u64 - ): vector { - let seed = - if (type_info::type_name() == type_info::type_name()) { - vector[OPERATOR_VESTING_PREFIX] - } else if (type_info::type_name() == type_info::type_name()) { - vector[USER_VESTING_PREFIX] - } else { - abort(error::invalid_argument(EINVALID_VESTING_TYPE)) - }; - - vector::append(&mut seed, bcs::to_bytes(&bridge_id)); - return seed - } - - fun add_vesting( - account_addr: address, - bridge_id: u64, - stage: u64, - vesting: Vesting - ) acquires VestingStore { - let vesting_store_addr = - get_vesting_store_address(account_addr, bridge_id); - let vesting_store = borrow_global_mut>(vesting_store_addr); - assert!( - !table::contains( - &vesting_store.claimed_stages, - table_key::encode_u64(stage), - ), - error::already_exists(EVESTING_ALREADY_CLAIMED), - ); - - table::add( - &mut vesting_store.claimed_stages, - table_key::encode_u64(stage), - true, - ); - table::add( - &mut vesting_store.vestings, - table_key::encode_u64(stage), - vesting, - ); - } - - fun create_vesting_store_address( - account: address, bridge_id: u64 - ): address { - let seed = generate_vesting_store_seed(bridge_id); - object::create_object_address(&account, seed) - } - - fun get_vesting_store_address( - account_addr: address, bridge_id: u64 - ): address { - let vesting_addr = create_vesting_store_address(account_addr, bridge_id); - assert!( - exists>(vesting_addr), - error::not_found(EVESTING_STORE_NOT_FOUND), - ); - vesting_addr - } - - fun calculate_operator_vest(value: &OperatorVesting,): u64 { - // vest_ratio = 1 / vesting_period - // vest_amount = value.initial_reward * vest_ratio - let vesting_period = value.end_stage - value.start_stage; - let vest_ratio = decimal256::div_u64(&decimal256::one(), vesting_period); - let vest_amount = decimal256::mul_u64(&vest_ratio, value.initial_reward); - - if (vest_amount > value.remaining_reward) { - vest_amount = value.remaining_reward; - }; - - vest_amount - } - - fun calculate_user_vest(value: &UserVesting, l2_score: u64,): u64 { - // vesting_period is the number of stages to vest the reward tokens. - // so we need to divide the vest_ratio by vesting_period to get proper - // vest amount of a stage. - - // score_ratio = s_j > minimum_score ? 1 : (s_j / minimu_score) where s_j is current l2_score - // max_ratio = 1 / vesting_period - // - // vest_ratio = max_ratio * score_ratio - // vest_amount = value.initial_reward * vest_ratio - let score_ratio = - if (l2_score >= value.minimum_score) { - decimal256::one() - } else { - decimal256::from_ratio_u64(l2_score, value.minimum_score) - }; - - let vesting_period = value.end_stage - value.start_stage; - let max_ratio = decimal256::div_u64(&decimal256::one(), vesting_period); - let vest_ratio = decimal256::mul(&max_ratio, &score_ratio); - let vest_amount = decimal256::mul_u64(&vest_ratio, value.initial_reward); - - if (vest_amount > value.remaining_reward) { - vest_amount = value.remaining_reward; - }; - - vest_amount - } - - fun get_vesting( - account_addr: address, bridge_id: u64, stage: u64 - ): Vesting acquires VestingStore { - let vesting_store_addr = - get_vesting_store_address(account_addr, bridge_id); - let vesting_store = borrow_global_mut>(vesting_store_addr); - - assert!( - table::contains( - &mut vesting_store.vestings, - table_key::encode_u64(stage), - ), - error::not_found(EVESTING_NOT_FOUND), - ); - let vesting = - table::borrow( - &vesting_store.vestings, - table_key::encode_u64(stage), - ); - - *vesting - } - - fun get_vesting_finalized( - account_addr: address, bridge_id: u64, stage: u64 - ): Vesting acquires VestingStore { - let vesting_store_addr = - get_vesting_store_address(account_addr, bridge_id); - let vesting_store = borrow_global_mut>(vesting_store_addr); - - assert!( - table::contains( - &mut vesting_store.vestings_finalized, - table_key::encode_u64(stage), - ), - error::not_found(EVESTING_NOT_FOUND), - ); - let vesting_finalized = - table::borrow( - &vesting_store.vestings_finalized, - table_key::encode_u64(stage), - ); - - *vesting_finalized - } - - fun get_last_claimed_stage( - account_addr: address, bridge_id: u64 - ): u64 acquires VestingStore { - let vesting_store_addr = - get_vesting_store_address(account_addr, bridge_id); - let vesting_store = borrow_global_mut>(vesting_store_addr); - - let iter = - table::iter( - &mut vesting_store.claimed_stages, - option::none(), - option::none(), - 2, - ); - if (!table::prepare, bool>(iter)) { - return 0 - }; - let (key, _) = table::next, bool>(iter); - table_key::decode_u64(key) - } - - fun vest_user_reward( - account_addr: address, - bridge_id: u64, - stage: u64, - l2_score: u64, - ): (u64, vector) acquires VestingStore { - let vested_reward = 0u64; - - let finalized_vestings = vector::empty(); - let vesting_changes = vector::empty(); - let vesting_store_addr = - get_vesting_store_address(account_addr, bridge_id); - let vesting_store = - borrow_global_mut>(vesting_store_addr); - let iter = - table::iter_mut( - &mut vesting_store.vestings, - option::none(), - option::none(), - 1, - ); - loop { - if (!table::prepare_mut, UserVesting>(iter)) { break }; - - let (_, value) = table::next_mut, UserVesting>(iter); - - // move vesting if end stage is over or the left reward is empty - if (stage > value.end_stage || value.remaining_reward == 0) { - event::emit( - UserVestingFinalizedEvent { - account: account_addr, - bridge_id, - stage: value.start_stage, - remaining_reward: value.remaining_reward, - }, - ); - - vector::push_back( - &mut finalized_vestings, - value.start_stage, - ); - continue - }; - - let vest_amount = calculate_user_vest(value, l2_score); - - vested_reward = vested_reward + vest_amount; - value.remaining_reward = value.remaining_reward - vest_amount; - - vector::push_back( - &mut vesting_changes, - VestingChange { - vesting_start_stage: value.start_stage, - initial_reward: value.initial_reward, - remaining_reward: value.remaining_reward, - }, - ); - }; - - // cleanup finalized vestings - vector::for_each_ref( - &finalized_vestings, - |stage| { - assert!( - table::contains( - &vesting_store.claimed_stages, - table_key::encode_u64(*stage), - ), - error::unavailable(EVESTING_NOT_CLAIMED), - ); - - let vesting = - table::remove( - &mut vesting_store.vestings, - table_key::encode_u64(*stage), - ); - table::add( - &mut vesting_store.vestings_finalized, - table_key::encode_u64(*stage), - vesting, - ); - }, - ); - - (vested_reward, vesting_changes) - } - - fun vest_operator_reward( - account_addr: address, - bridge_id: u64, - stage: u64, - ): (u64, vector) acquires VestingStore { - let vested_reward = 0u64; - - let finalized_vestings = vector::empty(); - let vesting_changes = vector::empty(); - let vesting_store_addr = - get_vesting_store_address(account_addr, bridge_id); - let vesting_store = - borrow_global_mut>(vesting_store_addr); - let iter = - table::iter_mut( - &mut vesting_store.vestings, - option::none(), - option::none(), - 1, - ); - loop { - if (!table::prepare_mut, OperatorVesting>(iter)) { break }; - - let (_, value) = table::next_mut, OperatorVesting>(iter); - - // move vesting if end stage is over or the left reward is empty - if (stage > value.end_stage || value.remaining_reward == 0) { - event::emit( - OperatorVestingFinalizedEvent { - account: account_addr, - bridge_id, - stage: value.start_stage, - remaining_reward: value.remaining_reward, - }, - ); - - vector::push_back( - &mut finalized_vestings, - value.start_stage, - ); - continue - }; - - let vest_amount = calculate_operator_vest(value); - - vested_reward = vested_reward + vest_amount; - value.remaining_reward = value.remaining_reward - vest_amount; - - vector::push_back( - &mut vesting_changes, - VestingChange { - vesting_start_stage: value.start_stage, - initial_reward: value.initial_reward, - remaining_reward: value.remaining_reward, - }, - ); - }; - - // cleanup finalized vestings - vector::for_each_ref( - &finalized_vestings, - |stage| { - assert!( - table::contains( - &vesting_store.claimed_stages, - table_key::encode_u64(*stage), - ), - error::unavailable(EVESTING_NOT_CLAIMED), - ); - - let vesting = - table::remove( - &mut vesting_store.vestings, - table_key::encode_u64(*stage), - ); - table::add( - &mut vesting_store.vestings_finalized, - table_key::encode_u64(*stage), - vesting, - ); - }, - ); - - (vested_reward, vesting_changes) - } - - fun claim_previous_operator_vestings( - account_addr: address, - bridge_id: u64, - stage: u64, - ): (FungibleAsset, vector) acquires VestingStore { - assert!( - get_last_claimed_stage(account_addr, bridge_id) < stage, - error::invalid_argument(ESTAGE_ALREADY_CLAIMED), - ); - - // vest previous vesting rewards until the stage - let (amount, vesting_changes) = - vest_operator_reward(account_addr, bridge_id, stage); - let reward_store_addr = get_operator_reward_store_address(bridge_id); - let vested_reward = vip_reward::withdraw(reward_store_addr, amount); - - (vested_reward, vesting_changes) - } - - fun claim_previous_user_vestings( - account_addr: address, - bridge_id: u64, - stage: u64, - l2_score: u64, - ): (FungibleAsset, vector) acquires VestingStore { - assert!( - get_last_claimed_stage(account_addr, bridge_id) < stage, - error::invalid_argument(ESTAGE_ALREADY_CLAIMED), - ); - - // vest previous vesting rewards until the stage - let (amount, vesting_changes) = - vest_user_reward( - account_addr, - bridge_id, - stage, - l2_score, - ); - let reward_store_addr = get_user_reward_store_address(bridge_id); - let vested_reward = vip_reward::withdraw(reward_store_addr, amount); - - (vested_reward, vesting_changes) - } - - fun add_user_vesting( - account_addr: address, - bridge_id: u64, - start_stage: u64, - end_stage: u64, - l2_score: u64, - total_l2_score: u64, - proportion: Decimal256, - ): u64 acquires VestingStore { - let reward_store_addr = get_user_reward_store_address(bridge_id); - let stage_reward = vip_reward::get_stage_reward(reward_store_addr, start_stage); - let score_ratio = decimal256::from_ratio_u64(l2_score, total_l2_score); - let vesting_reward_amount = decimal256::mul_u64(&score_ratio, stage_reward); - let minimum_score = decimal256::mul_u64(&proportion, l2_score); - - add_vesting( - account_addr, - bridge_id, - start_stage, - UserVesting { - initial_reward: vesting_reward_amount, - remaining_reward: vesting_reward_amount, - start_stage, - end_stage, - l2_score, - minimum_score, - }, - ); - - event::emit( - UserVestingCreateEvent { - account: account_addr, - bridge_id, - start_stage, - end_stage, - l2_score, - minimum_score, - initial_reward: vesting_reward_amount, - }, - ); - - vesting_reward_amount - } - - fun add_operator_vesting( - account_addr: address, - bridge_id: u64, - start_stage: u64, - end_stage: u64, - ): u64 acquires VestingStore { - let reward_store_addr = get_operator_reward_store_address(bridge_id); - let stage_reward = vip_reward::get_stage_reward(reward_store_addr, start_stage); - - add_vesting( - account_addr, - bridge_id, - start_stage, - OperatorVesting { - initial_reward: stage_reward, - remaining_reward: stage_reward, - start_stage, - end_stage, - }, - ); - - event::emit( - OperatorVestingCreateEvent { - account: account_addr, - bridge_id, - start_stage, - end_stage, - initial_reward: stage_reward, - }, - ); - - stage_reward - } - - // - // Public Functions - // - - public fun register_user_vesting_store( - account: &signer, bridge_id: u64 - ) { - register_vesting_store(account, bridge_id); - } - - public fun register_operator_vesting_store( - account: &signer, bridge_id: u64 - ) { - register_vesting_store(account, bridge_id); - } - - public fun is_user_vesting_store_registered( - addr: address, bridge_id: u64 - ): bool { - exists>( - create_vesting_store_address(addr, bridge_id) - ) - } - - public fun is_operator_vesting_store_registered( - addr: address, bridge_id: u64 - ): bool { - exists>( - create_vesting_store_address(addr, bridge_id) - ) - } - - public fun is_user_reward_store_registered(bridge_id: u64): bool { - vip_reward::is_reward_store_registered(bridge_id) - } - - public fun is_operator_reward_store_registered(bridge_id: u64): bool { - vip_reward::is_reward_store_registered(bridge_id) - } - - // - // Friends Functions - // - - public(friend) fun register_user_reward_store( - chain: &signer, bridge_id: u64, - ) { - vip_reward::register_reward_store(chain, bridge_id) - } - - public(friend) fun register_operator_reward_store( - chain: &signer, bridge_id: u64, - ) { - vip_reward::register_reward_store(chain, bridge_id) - } - - public(friend) fun supply_reward_on_user( - bridge_id: u64, - stage: u64, - reward: FungibleAsset, - ) { - let reward_store_addr = get_user_reward_store_address(bridge_id); - vip_reward::add_reward_per_stage( - reward_store_addr, - stage, - fungible_asset::amount(&reward), - ); - primary_fungible_store::deposit(reward_store_addr, reward); - } - - public(friend) fun supply_reward_on_operator( - bridge_id: u64, - stage: u64, - reward: FungibleAsset, - ) { - let reward_store_addr = get_operator_reward_store_address(bridge_id); - vip_reward::add_reward_per_stage( - reward_store_addr, - stage, - fungible_asset::amount(&reward), - ); - primary_fungible_store::deposit(reward_store_addr, reward); - } - - public(friend) fun claim_user_reward( - account_addr: address, - bridge_id: u64, - start_stage: u64, - end_stage: u64, - l2_score: u64, - total_l2_score: u64, - proportion: Decimal256, - ): FungibleAsset acquires VestingStore { - let (vested_reward, vesting_changes) = - claim_previous_user_vestings( - account_addr, - bridge_id, - start_stage, - l2_score, - ); - - let vesting_reward_amount = 0; - - // if l2_score is less than 0, do not create new position - if (l2_score >= 0) { - vesting_reward_amount = add_user_vesting( - account_addr, - bridge_id, - start_stage, - end_stage, - l2_score, - total_l2_score, - proportion, - ); - }; - - event::emit( - UserVestingClaimEvent { - account: account_addr, - bridge_id, - stage: start_stage, - vesting_reward_amount, - vested_reward_amount: fungible_asset::amount(&vested_reward), - vesting_changes, - }, - ); - - vested_reward - } - - public(friend) fun claim_operator_reward( - account_addr: address, - bridge_id: u64, - start_stage: u64, - end_stage: u64, - ): FungibleAsset acquires VestingStore { - let (vested_reward, vesting_changes) = - claim_previous_operator_vestings( - account_addr, - bridge_id, - start_stage, - ); - - let vesting_reward_amount = - add_operator_vesting( - account_addr, - bridge_id, - start_stage, - end_stage, - ); - - event::emit( - OperatorVestingClaimEvent { - account: account_addr, - bridge_id, - stage: start_stage, - vesting_reward_amount, - vested_reward_amount: fungible_asset::amount(&vested_reward), - vesting_changes, - }, - ); - - vested_reward - } - - public(friend) fun zapping_vesting( - account_addr: address, - bridge_id: u64, - stage: u64, - zapping_amount: u64 - ): FungibleAsset acquires VestingStore { - let vesting_store_addr = - get_vesting_store_address(account_addr, bridge_id); - let vesting_store = - borrow_global_mut>(vesting_store_addr); - assert!( - table::contains( - &vesting_store.vestings, - table_key::encode_u64(stage), - ), - error::not_found(EVESTING_NOT_FOUND), - ); - - let vesting = - table::borrow_mut( - &mut vesting_store.vestings, - table_key::encode_u64(stage), - ); - assert!( - vesting.remaining_reward >= zapping_amount, - error::invalid_argument(EREWARD_NOT_ENOUGH), - ); - vesting.remaining_reward = vesting.remaining_reward - zapping_amount; - - let reward_store_addr = get_user_reward_store_address(bridge_id); - vip_reward::withdraw(reward_store_addr, zapping_amount) - } - - // - // View Functions - // - - // <-- USER -----> - - #[view] - public fun get_user_reward_store_address(bridge_id: u64): address { - vip_reward::get_reward_store_address(bridge_id) - } - - #[view] - public fun get_user_last_claimed_stage( - account_addr: address, bridge_id: u64, - ): u64 acquires VestingStore { - get_last_claimed_stage(account_addr, bridge_id) - } - - #[view] - public fun get_user_claimed_stages( - account_addr: address, bridge_id: u64, - ): vector acquires VestingStore { - let claimed_stages = vector::empty(); - let vesting_store_addr = - get_vesting_store_address(account_addr, bridge_id); - let vesting_store = - borrow_global_mut>(vesting_store_addr); - let iter = - table::iter( - &mut vesting_store.claimed_stages, - option::none(), - option::none(), - 1, - ); - loop { - if (!table::prepare, bool>(iter)) { break }; - - let (key, _) = table::next, bool>(iter); - vector::push_back( - &mut claimed_stages, - table_key::decode_u64(key), - ); - }; - claimed_stages - } - - #[view] - public fun get_user_vesting( - account_addr: address, - bridge_id: u64, - stage: u64, - ): UserVesting acquires VestingStore { - get_vesting(account_addr, bridge_id, stage) - } - - #[view] - public fun get_user_vesting_finalized( - account_addr: address, - bridge_id: u64, - stage: u64, - ): UserVesting acquires VestingStore { - get_vesting_finalized(account_addr, bridge_id, stage) - } - - #[view] - public fun get_user_locked_reward( - account_addr: address, bridge_id: u64, stage: u64 - ): u64 acquires VestingStore { - let locked_reward = 0u64; - let vesting_store_addr = - get_vesting_store_address(account_addr, bridge_id); - let vesting_store = - borrow_global_mut>(vesting_store_addr); - let iter = - table::iter( - &mut vesting_store.vestings, - option::none(), - option::some(table_key::encode_u64(stage + 1)), - 1, - ); - loop { - if (!table::prepare, UserVesting>(iter)) { break }; - - let (_, value) = table::next, UserVesting>(iter); - locked_reward = locked_reward + value.remaining_reward; - }; - - locked_reward - } - - #[view] - public fun get_user_unlocked_reward( - account_addr: address, - bridge_id: u64, - stage: u64, - l2_score: u64 - ): u64 acquires VestingStore { - let vested_reward = 0u64; - let vesting_store_addr = - get_vesting_store_address(account_addr, bridge_id); - let vesting_store = - borrow_global_mut>(vesting_store_addr); - let iter = - table::iter_mut( - &mut vesting_store.vestings, - option::none(), - option::some(table_key::encode_u64(stage)), - 1, - ); - loop { - if (!table::prepare_mut, UserVesting>(iter)) { break }; - - let (_, value) = table::next_mut, UserVesting>(iter); - - let vest_amount = calculate_user_vest(value, l2_score); - vested_reward = vested_reward + vest_amount; - }; - vested_reward - } - - #[view] - public fun get_user_vesting_initial_reward( - account_addr: address, bridge_id: u64, stage: u64 - ): u64 acquires VestingStore { - let vesting = get_vesting(account_addr, bridge_id, stage); - vesting.initial_reward - } - - #[view] - public fun get_user_vesting_remaining_reward( - account_addr: address, bridge_id: u64, stage: u64 - ): u64 acquires VestingStore { - let vesting = get_vesting(account_addr, bridge_id, stage); - vesting.remaining_reward - } - - #[view] - public fun get_user_vesting_minimum_score( - account_addr: address, bridge_id: u64, stage: u64 - ): u64 acquires VestingStore { - let vesting = get_vesting(account_addr, bridge_id, stage); - vesting.minimum_score - } - - // <-- OPERATOR -----> - - #[view] - public fun get_operator_reward_store_address(bridge_id: u64): address { - vip_reward::get_reward_store_address(bridge_id) - } - - #[view] - public fun get_operator_last_claimed_stage( - account_addr: address, bridge_id: u64, - ): u64 acquires VestingStore { - get_last_claimed_stage(account_addr, bridge_id) - } - - #[view] - public fun get_operator_claimed_stages( - account_addr: address, bridge_id: u64, - ): vector acquires VestingStore { - let claimed_stages = vector::empty(); - let vesting_store_addr = - get_vesting_store_address(account_addr, bridge_id); - let vesting_store = - borrow_global_mut>(vesting_store_addr); - let iter = - table::iter( - &mut vesting_store.claimed_stages, - option::none(), - option::none(), - 1, - ); - loop { - if (!table::prepare, bool>(iter)) { break }; - - let (key, _) = table::next, bool>(iter); - vector::push_back( - &mut claimed_stages, - table_key::decode_u64(key), - ); - }; - claimed_stages - } - - #[view] - public fun get_operator_vesting( - account_addr: address, - bridge_id: u64, - stage: u64, - ): OperatorVesting acquires VestingStore { - get_vesting(account_addr, bridge_id, stage) - } - - #[view] - public fun get_operator_vesting_finalized( - account_addr: address, - bridge_id: u64, - stage: u64, - ): OperatorVesting acquires VestingStore { - get_vesting_finalized(account_addr, bridge_id, stage) - } - - #[view] - public fun get_operator_locked_reward( - account_addr: address, bridge_id: u64, stage: u64 - ): u64 acquires VestingStore { - let locked_reward = 0u64; - let vesting_store_addr = - get_vesting_store_address(account_addr, bridge_id); - let vesting_store = - borrow_global_mut>(vesting_store_addr); - let iter = - table::iter( - &mut vesting_store.vestings, - option::none(), - option::some(table_key::encode_u64(stage + 1)), - 1, - ); - loop { - if (!table::prepare, OperatorVesting>(iter)) { break }; - - let (_, value) = table::next, OperatorVesting>(iter); - locked_reward = locked_reward + value.remaining_reward; - }; - - locked_reward - } - - #[view] - public fun get_operator_unlocked_reward( - account_addr: address, bridge_id: u64, stage: u64 - ): u64 acquires VestingStore { - let vested_reward = 0u64; - let vesting_store_addr = - get_vesting_store_address(account_addr, bridge_id); - let vesting_store = - borrow_global_mut>(vesting_store_addr); - let iter = - table::iter_mut( - &mut vesting_store.vestings, - option::none(), - option::some(table_key::encode_u64(stage)), - 1, - ); - loop { - if (!table::prepare_mut, OperatorVesting>(iter)) { break }; - - let (_, value) = table::next_mut, OperatorVesting>(iter); - - let vest_amount = calculate_operator_vest(value); - vested_reward = vested_reward + vest_amount; - }; - vested_reward - } - - #[view] - public fun get_operator_vesting_initial_reward( - account_addr: address, bridge_id: u64, stage: u64 - ): u64 acquires VestingStore { - let vesting = get_vesting(account_addr, bridge_id, stage); - vesting.initial_reward - } - - #[view] - public fun get_operator_vesting_remaining_reward( - account_addr: address, bridge_id: u64, stage: u64 - ): u64 acquires VestingStore { - let vesting = get_vesting(account_addr, bridge_id, stage); - vesting.remaining_reward - } - - // - // Tests - // - - #[test_only] - use std::string; - - #[test_only] - use initia_std::coin; - - #[test_only] - use initia_std::object::Object; - - #[test_only] - use initia_std::fungible_asset::Metadata; - - #[test_only] - struct TestVesting has copy, drop, store { - initial_reward: u64, - remaining_reward: u64, - start_stage: u64, - end_stage: u64, - } - - #[test_only] - public fun initialize_coin(account: &signer, symbol: string::String,) - : ( - coin::BurnCapability, - coin::FreezeCapability, - coin::MintCapability, - Object - ) { - let (mint_cap, burn_cap, freeze_cap) = - coin::initialize( - account, - option::none(), - string::utf8(b""), - symbol, - 6, - string::utf8(b""), - string::utf8(b""), - ); - let metadata = coin::metadata(signer::address_of(account), symbol); - - (burn_cap, freeze_cap, mint_cap, metadata) - } - - // <-- VESTING -----> - - #[test(account = @0x99)] - fun test_register_vesting_store(account: &signer,) { - let account_addr = signer::address_of(account); - assert!( - !is_user_vesting_store_registered(account_addr, 1), - 1, - ); - register_user_vesting_store(account, 1); - assert!( - is_user_vesting_store_registered(account_addr, 1), - 2, - ); - register_user_vesting_store(account, 2); - } - - #[test(account = @0x99)] - fun test_add_vesting(account: &signer,) acquires VestingStore { - let account_addr = signer::address_of(account); - register_user_vesting_store(account, 1); - let vesting = UserVesting { - initial_reward: 100, - remaining_reward: 100, - start_stage: 1, - end_stage: 10, - l2_score: 100, - minimum_score: 10, - }; - add_vesting(account_addr, 1, 1, vesting); - } - - #[test(account = @0x99)] - #[expected_failure(abort_code = 0x80001, location = Self)] - fun failed_register_vesting_store_twice(account: &signer,) { - register_user_vesting_store(account, 1); - register_user_vesting_store(account, 1); - } - - // <-- REWARD -----> - - #[test(chain = @0x1)] - fun test_register_reward_store(chain: &signer,) { - primary_fungible_store::init_module_for_test(); - initialize_coin(chain, string::utf8(b"uinit")); - - assert!(!is_user_reward_store_registered(1), 1); - register_user_reward_store(chain, 1); - assert!(is_user_reward_store_registered(1), 2); - - assert!(!is_operator_reward_store_registered(1), 3); - register_operator_reward_store(chain, 1); - assert!(is_operator_reward_store_registered(1), 4); - - register_user_reward_store(chain, 2); - register_operator_reward_store(chain, 2); - } - - #[test(chain = @0x1)] - fun test_add_reward_per_stage(chain: &signer,) { - primary_fungible_store::init_module_for_test(); - initialize_coin(chain, string::utf8(b"uinit")); - - register_user_reward_store(chain, 1); - let reward_store_addr = get_user_reward_store_address(1); - vip_reward::add_reward_per_stage(reward_store_addr, 1, 100); - assert!( - vip_reward::get_stage_reward(reward_store_addr, 1) == 100, - 1, - ); - - register_operator_reward_store(chain, 1); - let reward_store_addr = get_operator_reward_store_address(1); - vip_reward::add_reward_per_stage(reward_store_addr, 1, 200); - assert!( - vip_reward::get_stage_reward(reward_store_addr, 1) == 200, - 2, - ); - } - - #[test(chain = @0x1)] - #[expected_failure(abort_code = 0x80001, location = initia_std::vip_reward)] - fun failed_register_reward_store_twice(chain: &signer,) { - primary_fungible_store::init_module_for_test(); - initialize_coin(chain, string::utf8(b"uinit")); - - register_user_reward_store(chain, 1); - register_user_reward_store(chain, 1); - } -} diff --git a/initia_stdlib/sources/vip/vip.move b/initia_stdlib/sources/vip/vip.move deleted file mode 100644 index c8e781e..0000000 --- a/initia_stdlib/sources/vip/vip.move +++ /dev/null @@ -1,4850 +0,0 @@ -module initia_std::vip { - use std::hash::sha3_256; - use std::error; - use std::string; - use std::signer; - use std::vector; - use std::option; - use std::event; - use std::block; - - use initia_std::object::{Object}; - use initia_std::fungible_asset::{Self, Metadata, FungibleAsset}; - use initia_std::primary_fungible_store; - use initia_std::table; - use initia_std::table_key; - use initia_std::coin; - use initia_std::decimal256::{Self, Decimal256}; - use initia_std::simple_map::{Self, SimpleMap}; - use initia_std::bcs; - use initia_std::vip_zapping; - use initia_std::vip_operator; - use initia_std::vip_vesting; - use initia_std::vip_reward; - use initia_std::vip_vault; - use initia_std::vip_tvl_manager; - - friend initia_std::vip_weight_vote; - - // - // Errors - // - - const ESTAGE_DATA_NOT_FOUND: u64 = 1; - const EINVALID_MERKLE_PROOFS: u64 = 2; - const EINVALID_PROOF_LENGTH: u64 = 3; - const EINVALID_VEST_PERIOD: u64 = 4; - const EUNAUTHORIZED: u64 = 5; - const EINVALID_MIN_ELIGIBLE_TVL: u64 = 6; - const EINVALID_MAX_TVL: u64 = 7; - const EINVALID_PROPORTION: u64 = 8; - const EINVALID_TOTAL_SHARE: u64 = 9; - const EALREADY_FUNDED: u64 = 10; - const EINVALID_FUND_STAGE: u64 = 11; - const EZAPPING_STAKELISTED_NOT_ENOUGH: u64 = 12; - const EALREADY_REGISTERED: u64 = 13; - const EBRIDGE_NOT_FOUND: u64 = 14; - const EVESTING_IN_PROGRESS: u64 = 15; - const ESNAPSHOT_ALREADY_EXISTS: u64 = 16; - const EINVALID_BATCH_ARGUMENT: u64 = 17; - const EINVALID_TOTAL_REWARD: u64 = 18; - const ESNAPSHOT_NOT_EXISTS: u64 = 19; - const EALREADY_RELEASED: u64 = 20; - const EINVALID_WEIGHT: u64 = 21; - const EINVALID_STAGE_ORDER: u64 = 22; - const EINVALID_CLAIMABLE_PERIOD: u64 = 23; - const EINVALID_CHALLENGE_PERIOD: u64 = 24; - const EINVALID_CHALLENGE_STAGE: u64 = 25; - const EPREV_STAGE_SNAPSHOT_NOT_FOUND: u64 = 26; - // - // Constants - // - - const PROOF_LENGTH: u64 = 32; - const REWARD_SYMBOL: vector = b"uinit"; - const DEFAULT_POOL_SPLIT_RATIO: vector = b"0.4"; - const DEFAULT_PROPORTION_RATIO: vector = b"0.5"; - const DEFAULT_USER_VESTING_PERIOD: u64 = 52; // 52 times - const DEFAULT_OPERATOR_VESTING_PERIOD: u64 = 52; - const DEFAULT_STAGE_PERIOD: u64 = 604800; // 1 week - const DEFAULT_MINIMUM_ELIGIBLE_TVL: u64 = 0; - const DEFAULT_MAXIMUM_TVL_RATIO: vector = b"1"; - const DEFAULT_MAXIMUM_WEIGHT_RATIO: vector = b"1"; - const DEFAULT_VIP_START_STAGE: u64 = 1; - const DEFAULT_CHALLENGE_PERIOD: u64 = 604800; // 7 days - - struct ModuleStore has key { - // current stage - stage: u64, - // governance-defined vesting period in stage unit - stage_period: u64, - // the number of times vesting is divided - user_vesting_period: u64, - operator_vesting_period: u64, - challenge_period: u64, - // agent for snapshot taker and VIP reward funder - agent_data: AgentData, - // governance-defined proportion to decrease overhead of keeping the L2 INIT balance. - // a user only need to keep the `vesting.l2_score * proportion` amount of INIT token - // to vest whole vesting rewards. - proportion: Decimal256, - // if pool_split_ratio is 0.4, - // balance pool takes 0.4 and weight pool takes 0.6 - pool_split_ratio: Decimal256, - // TVL cap of L2 INIT token to receive the reward. (% of total whitelisted l2 balance) - maximum_tvl_ratio: Decimal256, - // minimum eligible TVL of L2 INIT token to receive the reward. - minimum_eligible_tvl: u64, - // maximum weight of VIP reward - maximum_weight_ratio: Decimal256, - // a set of stage data - stage_data: table::Table /* stage */, StageData>, - // a set of bridge info - bridges: table::Table /* bridge id */, Bridge>, - challenges: table::Table, ExecutedChallenge>, - } - - struct AgentData has store, drop { - agent: address, - api_uri: string::String, - } - - struct StageData has store { - stage_period: u64, - pool_split_ratio: Decimal256, - total_operator_funded_reward: u64, - total_user_funded_reward: u64, - user_vesting_period: u64, - operator_vesting_period: u64, - user_vesting_release_time: u64, - operator_vesting_release_time: u64, - proportion: Decimal256, - snapshots: table::Table /* bridge id */, Snapshot> - } - - struct Snapshot has store, drop { - create_time: u64, - upsert_time: u64, - merkle_root: vector, - total_l2_score: u64 - } - - struct Bridge has store, drop { - init_stage: u64, // stage to start scoring and distribution reward - bridge_addr: address, - operator_addr: address, - vip_l2_score_contract: string::String, - vip_weight: Decimal256, - operator_reward_store_addr: address, - user_reward_store_addr: address, - } - - struct RewardDistribution has drop, store { - bridge_id: u64, - user_reward_store_addr: address, - operator_reward_store_addr: address, - user_reward_amount: u64, - operator_reward_amount: u64 - } - - struct ExecutedChallenge has store, drop { - challenge_id: u64, - bridge_id: u64, - stage: u64, - new_l2_total_score: u64, - title: string::String, - summary: string::String, - api_uri: string::String, - new_agent: address, - merkle_root: vector, - } - - // - // Responses - // - - struct ModuleResponse has drop { - stage: u64, - stage_period: u64, - agent_data: AgentData, - proportion: Decimal256, - pool_split_ratio: Decimal256, - user_vesting_period: u64, - operator_vesting_period: u64, - minimum_eligible_tvl: u64, - maximum_tvl_ratio: Decimal256, - challenge_period: u64, - } - - struct SnapshotResponse has drop { - create_time: u64, - upsert_time: u64, - merkle_root: vector, - total_l2_score: u64 - } - - struct StageDataResponse has drop { - stage_period: u64, - pool_split_ratio: Decimal256, - total_operator_funded_reward: u64, - total_user_funded_reward: u64, - user_vesting_period: u64, - operator_vesting_period: u64, - user_vesting_release_time: u64, - operator_vesting_release_time: u64, - proportion: Decimal256, - } - - struct BridgeResponse has drop { - init_stage: u64, - bridge_id: u64, - bridge_addr: address, - operator_addr: address, - vip_l2_score_contract: string::String, - vip_weight: Decimal256, - user_reward_store_addr: address, - operator_reward_store_addr: address, - } - - struct ExecutedChallengeResponse has drop { - title: string::String, - summary: string::String, - new_api_uri: string::String, - new_agent: address, - new_merkle_root: vector, - } - - // - // Events - // - - #[event] - struct FundEvent has drop, store { - stage: u64, - total_operator_funded_reward: u64, - total_user_funded_reward: u64, - reward_distribution: vector - } - - #[event] - struct StageAdvanceEvent has drop, store { - stage: u64, - stage_period: u64, - pool_split_ratio: Decimal256, - total_operator_funded_reward: u64, - total_user_funded_reward: u64, - user_vesting_period: u64, - operator_vesting_period: u64, - user_vesting_release_time: u64, - operator_vesting_release_time: u64, - proportion: Decimal256, - } - - #[event] - struct ReleaseTimeUpdateEvent has drop, store { - stage: u64, - user_vesting_release_time: u64, - operator_vesting_release_time: u64, - } - - #[event] - struct ExecuteChallengeEvent has drop, store { - challenge_id: u64, - bridge_id: u64, - stage: u64, - title: string::String, - summary: string::String, - api_uri: string::String, - new_agent: address, - merkle_root: vector - } - - // - // Implementations - // - - fun init_module(chain: &signer) { - move_to( - chain, - ModuleStore { - stage: DEFAULT_VIP_START_STAGE, - stage_period: DEFAULT_STAGE_PERIOD, - user_vesting_period: DEFAULT_USER_VESTING_PERIOD, - operator_vesting_period: DEFAULT_OPERATOR_VESTING_PERIOD, - challenge_period: DEFAULT_CHALLENGE_PERIOD, - proportion: decimal256::from_string( - &string::utf8(DEFAULT_PROPORTION_RATIO) - ), - pool_split_ratio: decimal256::from_string( - &string::utf8(DEFAULT_POOL_SPLIT_RATIO) - ), - agent_data: AgentData { - agent: signer::address_of(chain), - api_uri: string::utf8(b""), - }, - maximum_tvl_ratio: decimal256::from_string( - &string::utf8(DEFAULT_MAXIMUM_TVL_RATIO) - ), - minimum_eligible_tvl: DEFAULT_MINIMUM_ELIGIBLE_TVL, - maximum_weight_ratio: decimal256::from_string( - &string::utf8(DEFAULT_MAXIMUM_WEIGHT_RATIO) - ), - stage_data: table::new, StageData>(), - bridges: table::new, Bridge>(), - challenges: table::new, ExecutedChallenge>(), - }, - ); - } - - // Compare bytes and return a following result number: - // 0: equal - // 1: v1 is greator than v2 - // 2: v1 is less than v2 - fun bytes_cmp(v1: &vector, v2: &vector): u8 { - assert!( - vector::length(v1) == PROOF_LENGTH, - error::invalid_argument(EINVALID_PROOF_LENGTH), - ); - assert!( - vector::length(v2) == PROOF_LENGTH, - error::invalid_argument(EINVALID_PROOF_LENGTH), - ); - - let i = 0; - while (i < 32) { - let e1 = *vector::borrow(v1, i); - let e2 = *vector::borrow(v2, i); - if (e1 > e2) { - return 1 - } else if (e2 > e1) { - return 2 - }; - i = i + 1; - }; - - 0 - } - - fun score_hash( - bridge_id: u64, - stage: u64, - account_addr: address, - l2_score: u64, - total_l2_score: u64, - ): vector { - let target_hash = { - let score_data = vector::empty(); - vector::append( - &mut score_data, - bcs::to_bytes(&bridge_id), - ); - vector::append( - &mut score_data, - bcs::to_bytes(&stage), - ); - vector::append( - &mut score_data, - bcs::to_bytes(&account_addr), - ); - vector::append( - &mut score_data, - bcs::to_bytes(&l2_score), - ); - vector::append( - &mut score_data, - bcs::to_bytes(&total_l2_score), - ); - - sha3_256(score_data) - }; - target_hash - } - - fun assert_merkle_proofs( - merkle_proofs: vector>, - merkle_root: vector, - target_hash: vector, - ) { - // must use sorted merkle tree - let i = 0; - let len = vector::length(&merkle_proofs); - let root_seed = target_hash; - - while (i < len) { - let proof = vector::borrow(&merkle_proofs, i); - - let cmp = bytes_cmp(&root_seed, proof); - root_seed = if (cmp == 2 /* less */) { - let tmp = vector::empty(); - vector::append(&mut tmp, root_seed); - vector::append(&mut tmp, *proof); - - sha3_256(tmp) - } else /* greator or equals */ { - let tmp = vector::empty(); - vector::append(&mut tmp, *proof); - vector::append(&mut tmp, root_seed); - - sha3_256(tmp) - }; - - i = i + 1; - }; - let root_hash = root_seed; - assert!( - merkle_root == root_hash, - error::invalid_argument(EINVALID_MERKLE_PROOFS), - ); - } - - fun check_chain_permission(chain: &signer) { - assert!( - signer::address_of(chain) == @initia_std, - error::permission_denied(EUNAUTHORIZED), - ); - } - - fun check_agent_permission(agent: &signer) acquires ModuleStore { - let module_store = borrow_global(@initia_std); - assert!( - signer::address_of(agent) == module_store.agent_data.agent, - error::permission_denied(EUNAUTHORIZED), - ); - } - - // check previous stage snapshot is exist for preventing skipping stage - fun check_previous_stage_snapshot( - imut_module_store: &ModuleStore, - bridge_id: u64, - stage: u64, - ) { - // if current stage is init stage of bridge, then skip this check - let init_stage = load_bridge(&imut_module_store.bridges, bridge_id).init_stage; - if (stage != init_stage) { - let prev_stage_data = - table::borrow( - &imut_module_store.stage_data, - table_key::encode_u64(stage - 1), - ); - assert!( - table::contains( - &prev_stage_data.snapshots, - table_key::encode_u64(bridge_id), - ), - error::not_found(EPREV_STAGE_SNAPSHOT_NOT_FOUND), - ); - }; - } - - fun load_bridge( - bridges: &table::Table, Bridge>, bridge_id: u64 - ): &Bridge { - assert!( - table::contains( - bridges, - table_key::encode_u64(bridge_id), - ), - error::not_found(EBRIDGE_NOT_FOUND), - ); - table::borrow(bridges, table_key::encode_u64(bridge_id)) - } - - fun load_bridge_mut( - bridges: &mut table::Table, Bridge>, bridge_id: u64 - ): &mut Bridge { - assert!( - table::contains( - bridges, - table_key::encode_u64(bridge_id), - ), - error::not_found(EBRIDGE_NOT_FOUND), - ); - table::borrow_mut(bridges, table_key::encode_u64(bridge_id)) - } - - public fun claim_user_reward( - account: &signer, - bridge_id: u64, - stage: u64, - merkle_proofs: vector>, - l2_score: u64, - ): FungibleAsset acquires ModuleStore { - - // check claim period - check_claimable_period(bridge_id, stage); - - let account_addr = signer::address_of(account); - let module_store = borrow_global(@initia_std); - let (_, block_time) = block::get_block_info(); - - assert!( - table::contains( - &module_store.stage_data, - table_key::encode_u64(stage), - ), - error::not_found(ESTAGE_DATA_NOT_FOUND), - ); - let stage_data = - table::borrow( - &module_store.stage_data, - table_key::encode_u64(stage), - ); - let snapshot = - table::borrow( - &stage_data.snapshots, - table_key::encode_u64(bridge_id), - ); - assert!( - block_time >= stage_data.user_vesting_release_time, - error::unavailable(EVESTING_IN_PROGRESS), - ); - - let target_hash = - score_hash( - bridge_id, - stage, - account_addr, - l2_score, - snapshot.total_l2_score, - ); - - assert_merkle_proofs( - merkle_proofs, - snapshot.merkle_root, - target_hash, - ); - - let vested_reward = - vip_vesting::claim_user_reward( - account_addr, - bridge_id, - stage, - stage + stage_data.user_vesting_period, - l2_score, - snapshot.total_l2_score, - stage_data.proportion, - ); - - vested_reward - } - - fun zapping( - account: &signer, - bridge_id: u64, - lp_metadata: Object, - min_liquidity: option::Option, - validator: string::String, - stage: u64, - zapping_amount: u64, - stakelisted_amount: u64, - stakelisted_metadata: Object, - ) { - let account_addr = signer::address_of(account); - let esinit = - vip_vesting::zapping_vesting( - account_addr, - bridge_id, - stage, - zapping_amount, - ); - assert!( - primary_fungible_store::balance(account_addr, stakelisted_metadata) - >= stakelisted_amount, - error::invalid_argument(EZAPPING_STAKELISTED_NOT_ENOUGH), - ); - let stakelisted = - primary_fungible_store::withdraw( - account, - stakelisted_metadata, - stakelisted_amount, - ); - - vip_zapping::zapping( - account, - bridge_id, - lp_metadata, - min_liquidity, - validator, - stage, - esinit, - stakelisted, - ); - } - - fun extract_commission( - operator_addr: address, - bridge_id: u64, - reward: FungibleAsset, - ): (FungibleAsset, FungibleAsset) { - let commission_rate = - vip_operator::get_operator_commission(operator_addr, bridge_id); - let commission_amount = - decimal256::mul_u64( - &commission_rate, - fungible_asset::amount(&reward), - ); - let commission = fungible_asset::extract(&mut reward, commission_amount); - (commission, reward) - } - - fun split_reward( - module_store: &mut ModuleStore, - stage: u64, - balance_shares: &SimpleMap, - weight_shares: &SimpleMap, - balance_pool_reward: FungibleAsset, - weight_pool_reward: FungibleAsset, - ): (u64, u64) { - let reward_distributions = vector::empty(); - - let initial_balance_pool_reward_amount = - fungible_asset::amount(&balance_pool_reward); - let initial_weight_pool_reward_amount = - fungible_asset::amount(&weight_pool_reward); - let total_user_funded_reward = 0; - let total_operator_funded_reward = 0; - - let index = 0; - let iter = table::iter( - &module_store.bridges, - option::none(), - option::none(), - 1, - ); - loop { - if (!table::prepare, Bridge>(iter)) { break }; - - let (bridge_id_vec, bridge) = table::next, Bridge>(iter); - let bridge_id = table_key::decode_u64(bridge_id_vec); - let balance_reward = - split_reward_with_share( - balance_shares, - bridge_id, - initial_balance_pool_reward_amount, - &mut balance_pool_reward, - ); - let (balance_commission, balance_user_reward) = - extract_commission( - bridge.operator_addr, - bridge_id, - balance_reward, - ); - - let weight_reward = - split_reward_with_share( - weight_shares, - bridge_id, - initial_weight_pool_reward_amount, - &mut weight_pool_reward, - ); - let (weight_commission, weight_user_reward) = - extract_commission( - bridge.operator_addr, - bridge_id, - weight_reward, - ); - - fungible_asset::merge( - &mut balance_commission, - weight_commission, - ); - fungible_asset::merge( - &mut balance_user_reward, - weight_user_reward, - ); - - let commission_sum = balance_commission; - let user_reward_sum = balance_user_reward; - - total_operator_funded_reward = total_operator_funded_reward - + fungible_asset::amount(&commission_sum); - total_user_funded_reward = total_user_funded_reward - + fungible_asset::amount(&user_reward_sum); - - vector::push_back( - &mut reward_distributions, - RewardDistribution { - bridge_id, - user_reward_store_addr: bridge.user_reward_store_addr, - operator_reward_store_addr: bridge.operator_reward_store_addr, - user_reward_amount: fungible_asset::amount(&user_reward_sum), - operator_reward_amount: fungible_asset::amount(&commission_sum) - }, - ); - - vip_vesting::supply_reward_on_operator(bridge_id, stage, commission_sum); - - vip_vesting::supply_reward_on_user(bridge_id, stage, user_reward_sum); - - index = index + 1; - }; - - let vault_store_addr = vip_vault::get_vault_store_address(); - primary_fungible_store::deposit(vault_store_addr, balance_pool_reward); - primary_fungible_store::deposit(vault_store_addr, weight_pool_reward); - - event::emit( - FundEvent { - stage, - total_operator_funded_reward, - total_user_funded_reward, - reward_distribution: reward_distributions - }, - ); - - (total_operator_funded_reward, total_user_funded_reward) - } - - fun split_reward_with_share( - shares: &SimpleMap, - bridge_id: u64, - total_reward_amount: u64, - reward: &mut FungibleAsset, - ): FungibleAsset { - let split_amount = - split_reward_with_share_internal( - shares, - bridge_id, - total_reward_amount, - ); - fungible_asset::extract(reward, split_amount) - } - - fun split_reward_with_share_internal( - shares: &SimpleMap, - bridge_id: u64, - total_reward_amount: u64, - ): u64 { - let share_ratio = *simple_map::borrow(shares, &bridge_id); - let split_amount = decimal256::mul_u64(&share_ratio, total_reward_amount); - split_amount - } - - // fund reward to distribute to operators and users and distribute previous stage rewards - fun fund_reward( - module_store: &mut ModuleStore, stage: u64, initial_reward: FungibleAsset - ): (u64, u64) { - let initial_amount = fungible_asset::amount(&initial_reward); - - let balance_shares = simple_map::create(); - let weight_shares = simple_map::create(); - - let total_balance = calculate_balance_share(module_store, &mut balance_shares); - assert!( - total_balance > 0, - error::invalid_state(EINVALID_TOTAL_SHARE), - ); - calculate_weight_share(module_store, &mut weight_shares); - let balance_pool_reward_amount = - decimal256::mul_u64( - &module_store.pool_split_ratio, - initial_amount, - ); - let balance_pool_reward = - fungible_asset::extract( - &mut initial_reward, - balance_pool_reward_amount, - ); - let weight_pool_reward = initial_reward; - - let (total_operator_funded_reward, total_user_funded_reward) = - split_reward( - module_store, - stage, - &balance_shares, - &weight_shares, - balance_pool_reward, - weight_pool_reward, - ); - - (total_operator_funded_reward, total_user_funded_reward) - } - - // calculate balance share and return total balance - fun calculate_balance_share( - module_store: &ModuleStore, balance_shares: &mut SimpleMap - ): u64 { - let bridge_balances: SimpleMap = simple_map::create(); - let total_balance = 0; - - let iter = table::iter( - &module_store.bridges, - option::none(), - option::none(), - 1, - ); - // calculate total balance and bridge balance - loop { - if (!table::prepare, Bridge>(iter)) { break }; - let (bridge_id_vec, _) = table::next, Bridge>(iter); - // bridge balance from tvl manager - let bridge_balance = - vip_tvl_manager::calculate_average_tvl( - table_key::encode_u64(module_store.stage), - bridge_id_vec, - ); - total_balance = total_balance + bridge_balance; - simple_map::add( - &mut bridge_balances, - table_key::decode_u64(bridge_id_vec), - bridge_balance, - ); - }; - - let max_effective_balance = - decimal256::mul_u64( - &module_store.maximum_tvl_ratio, - total_balance, - ); - - iter = table::iter( - &module_store.bridges, - option::none(), - option::none(), - 1, - ); - // calculate balance share - loop { - if (!table::prepare, Bridge>(iter)) { break }; - let (bridge_id_vec, _) = table::next, Bridge>(iter); - let bridge_balance = - simple_map::borrow( - &bridge_balances, - &table_key::decode_u64(bridge_id_vec), - ); - - let effective_bridge_balance = - if (*bridge_balance > max_effective_balance) { - max_effective_balance - } else if (*bridge_balance < module_store.minimum_eligible_tvl) { 0 } - else { - *bridge_balance - }; - - let share = - decimal256::from_ratio_u64( - effective_bridge_balance, - total_balance, - ); - simple_map::add( - balance_shares, - table_key::decode_u64(bridge_id_vec), - share, - ); - }; - - (total_balance) - } - - fun calculate_weight_share( - module_store: &ModuleStore, weight_shares: &mut SimpleMap - ) { - let iter = table::iter( - &module_store.bridges, - option::none(), - option::none(), - 1, - ); - loop { - if (!table::prepare, Bridge>(iter)) { break }; - let (bridge_id_vec, bridge) = table::next, Bridge>(iter); - let bridge_id = table_key::decode_u64(bridge_id_vec); - - let weight = - if (decimal256::val(&bridge.vip_weight) - > decimal256::val(&module_store.maximum_weight_ratio)) { - module_store.maximum_weight_ratio - } else { - bridge.vip_weight - }; - - simple_map::add(weight_shares, bridge_id, weight); - } - } - - public fun claim_operator_reward( - operator: &signer, - bridge_id: u64, - stage: u64, - ): FungibleAsset acquires ModuleStore { - // check claim period - check_claimable_period(bridge_id, stage); - - let operator_addr = signer::address_of(operator); - let module_store = borrow_global(@initia_std); - let (_, block_time) = block::get_block_info(); - - // assert claimable conditions - assert!( - table::contains( - &module_store.stage_data, - table_key::encode_u64(stage), - ), - error::not_found(ESTAGE_DATA_NOT_FOUND), - ); - let stage_data = - table::borrow( - &module_store.stage_data, - table_key::encode_u64(stage), - ); - assert!( - block_time >= stage_data.operator_vesting_release_time, - error::unavailable(EVESTING_IN_PROGRESS), - ); - - let vested_reward = - vip_vesting::claim_operator_reward( - operator_addr, - bridge_id, - stage, - stage + stage_data.operator_vesting_period, - ); - - vested_reward - } - - fun validate_vip_weights(module_store: &ModuleStore) { - let total_weight = decimal256::zero(); - - let iter = table::iter( - &module_store.bridges, - option::none(), - option::none(), - 1, - ); - loop { - if (!table::prepare, Bridge>(iter)) { break }; - let (_, bridge) = table::next, Bridge>(iter); - total_weight = decimal256::add(&total_weight, &bridge.vip_weight); - }; - - assert!( - decimal256::val(&total_weight) <= decimal256::val(&decimal256::one()), - error::invalid_argument(EINVALID_WEIGHT), - ); - } - - public fun is_registered(bridge_id: u64): bool acquires ModuleStore { - let module_store = borrow_global(@initia_std); - table::contains( - &module_store.bridges, - table_key::encode_u64(bridge_id), - ) - } - - public(friend) fun update_vip_weights_for_friend( - bridge_ids: vector, weights: vector, - ) acquires ModuleStore { - let module_store = borrow_global_mut(@initia_std); - - assert!( - vector::length(&bridge_ids) == vector::length(&weights), - error::invalid_argument(EINVALID_BATCH_ARGUMENT), - ); - - vector::enumerate_ref( - &bridge_ids, - |i, id| { - let bridge = load_bridge_mut(&mut module_store.bridges, *id); - bridge.vip_weight = *vector::borrow(&weights, i); - }, - ); - - validate_vip_weights(module_store); - } - - // - // Entry Functions - // - public entry fun execute_challenge( - chain: &signer, - bridge_id: u64, - challenge_stage: u64, - challenge_id: u64, - title: string::String, - summary: string::String, - new_api_uri: string::String, - new_agent: address, - new_merkle_root: vector, - new_l2_total_score: u64 - ) acquires ModuleStore { - check_chain_permission(chain); - let module_store = borrow_global_mut(@initia_std); - assert!( - module_store.stage > challenge_stage, - error::permission_denied(EINVALID_CHALLENGE_STAGE), - ); - let (_, execution_time) = block::get_block_info(); - //check challenge period - let stage_data = - table::borrow_mut( - &mut module_store.stage_data, - table_key::encode_u64(challenge_stage), - ); - let snapshot = - table::borrow_mut( - &mut stage_data.snapshots, - table_key::encode_u64(bridge_id), - ); - assert!( - snapshot.create_time + module_store.challenge_period > execution_time, - error::permission_denied(EINVALID_CHALLENGE_PERIOD), - ); - - // make key of executed_challenge - let key = table_key::encode_u64(challenge_id); - // add executed_challenge - table::add( - &mut module_store.challenges, - key, - ExecutedChallenge { - challenge_id, - bridge_id, - stage: challenge_stage, - new_l2_total_score, - title, - summary, - api_uri: new_api_uri, - new_agent, - merkle_root: new_merkle_root, - }, - ); - // replace agent - module_store.agent_data = AgentData { agent: new_agent, api_uri: new_api_uri, }; - - // update snapshot data - snapshot.upsert_time = execution_time; - snapshot.merkle_root = new_merkle_root; - snapshot.total_l2_score = new_l2_total_score; - - event::emit( - ExecuteChallengeEvent { - challenge_id, - bridge_id, - stage: challenge_stage, - title, - summary, - api_uri: new_api_uri, - new_agent, - merkle_root: new_merkle_root, - }, - ); - - } - - // register L2 by gov - public entry fun register( - chain: &signer, - operator: address, - bridge_id: u64, - bridge_address: address, - init_stage: u64, - vip_l2_score_contract: string::String, - operator_commission_max_rate: Decimal256, - operator_commission_max_change_rate: Decimal256, - operator_commission_rate: Decimal256, - ) acquires ModuleStore { - check_chain_permission(chain); - - let module_store = borrow_global_mut(signer::address_of(chain)); - assert!( - !table::contains( - &module_store.bridges, - table_key::encode_u64(bridge_id), - ), - error::already_exists(EALREADY_REGISTERED), - ); - - // register chain stores - if (!vip_operator::is_operator_store_registered(operator, bridge_id)) { - vip_operator::register_operator_store( - chain, - operator, - bridge_id, - module_store.stage, - operator_commission_max_rate, - operator_commission_max_change_rate, - operator_commission_rate, - ); - }; - if (!vip_vesting::is_operator_reward_store_registered(bridge_id)) { - vip_vesting::register_operator_reward_store(chain, bridge_id); - }; - if (!vip_vesting::is_user_reward_store_registered(bridge_id)) { - vip_vesting::register_user_reward_store(chain, bridge_id); - }; - - // add bridge info - table::add( - &mut module_store.bridges, - table_key::encode_u64(bridge_id), - Bridge { - init_stage: init_stage, - bridge_addr: bridge_address, - operator_addr: operator, - vip_l2_score_contract, - vip_weight: decimal256::zero(), - user_reward_store_addr: vip_vesting::get_user_reward_store_address( - bridge_id - ), - operator_reward_store_addr: vip_vesting::get_operator_reward_store_address( - bridge_id - ), - }, - ); - } - - public entry fun deregister(chain: &signer, bridge_id: u64,) acquires ModuleStore { - check_chain_permission(chain); - let module_store = borrow_global_mut(signer::address_of(chain)); - assert!( - table::contains( - &module_store.bridges, - table_key::encode_u64(bridge_id), - ), - error::not_found(EBRIDGE_NOT_FOUND), - ); - - table::remove( - &mut module_store.bridges, - table_key::encode_u64(bridge_id), - ); - } - - public entry fun update_agent( - old_agent: &signer, new_agent: address, new_api_uri: string::String - ) acquires ModuleStore { - check_agent_permission(old_agent); - let module_store = borrow_global_mut(@initia_std); - module_store.agent_data = AgentData { agent: new_agent, api_uri: new_api_uri, }; - } - - public entry fun update_agent_by_chain( - chain: &signer, new_agent: address, new_api_uri: string::String - ) acquires ModuleStore { - check_chain_permission(chain); - let module_store = borrow_global_mut(@initia_std); - module_store.agent_data = AgentData { agent: new_agent, api_uri: new_api_uri, }; - } - - public entry fun update_release_time( - agent: &signer, - stage: u64, - user_vesting_release_time: u64, - operator_vesting_release_time: u64, - ) acquires ModuleStore { - check_agent_permission(agent); - - let module_store = borrow_global_mut(@initia_std); - assert!( - table::contains( - &mut module_store.stage_data, - table_key::encode_u64(stage), - ), - error::not_found(ESTAGE_DATA_NOT_FOUND), - ); - let stage_data = - table::borrow_mut( - &mut module_store.stage_data, - table_key::encode_u64(stage), - ); - stage_data.user_vesting_release_time = user_vesting_release_time; - stage_data.operator_vesting_release_time = operator_vesting_release_time; - - event::emit( - ReleaseTimeUpdateEvent { - stage, - user_vesting_release_time, - operator_vesting_release_time, - }, - ); - } - - // add tvl snapshot of all bridges on this stage - public entry fun add_tvl_snapshot(agent: &signer,) acquires ModuleStore { - check_agent_permission(agent); - let module_store = borrow_global(@initia_std); - add_tvl_snapshot_internal(module_store); - } - - fun add_tvl_snapshot_internal(module_store: &ModuleStore) { - let bridges = &module_store.bridges; - let current_stage = module_store.stage; - let iter = table::iter( - bridges, - option::none(), - option::none(), - 1, - ); - loop { - if (!table::prepare, Bridge>(iter)) { break }; - let (bridge_id_vec, bridge) = table::next, Bridge>(iter); - let bridge_id = table_key::decode_u64(bridge_id_vec); - - let bridge_balance = - primary_fungible_store::balance( - bridge.bridge_addr, - vip_reward::reward_metadata(), - ); - vip_tvl_manager::add_snapshot( - current_stage, - bridge_id, - bridge_balance, - ); - }; - - } - - public entry fun fund_reward_script( - agent: &signer, - stage: u64, - user_vesting_release_time: u64, - operator_vesting_release_time: u64, - ) acquires ModuleStore { - check_agent_permission(agent); - - let module_store = borrow_global_mut(@initia_std); - assert!( - !table::contains( - &mut module_store.stage_data, - table_key::encode_u64(stage), - ), - error::already_exists(EALREADY_FUNDED), - ); - assert!( - stage == module_store.stage, - error::invalid_argument(EINVALID_FUND_STAGE), - ); - // add tvl snapshot for this stage before fund reward to final snapshot - add_tvl_snapshot_internal(module_store); - - let total_reward = vip_vault::claim(stage); - let (total_operator_funded_reward, total_user_funded_reward) = - fund_reward(module_store, stage, total_reward); - - // set stage data - let module_store = borrow_global_mut(@initia_std); - table::add( - &mut module_store.stage_data, - table_key::encode_u64(stage), - StageData { - stage_period: module_store.stage_period, - pool_split_ratio: module_store.pool_split_ratio, - total_operator_funded_reward, - total_user_funded_reward, - user_vesting_period: module_store.user_vesting_period, - operator_vesting_period: module_store.operator_vesting_period, - user_vesting_release_time: user_vesting_release_time, - operator_vesting_release_time: operator_vesting_release_time, - proportion: module_store.proportion, - snapshots: table::new, Snapshot>(), - }, - ); - - event::emit( - StageAdvanceEvent { - stage, - stage_period: module_store.stage_period, - pool_split_ratio: module_store.pool_split_ratio, - total_operator_funded_reward, - total_user_funded_reward, - user_vesting_period: module_store.user_vesting_period, - operator_vesting_period: module_store.operator_vesting_period, - user_vesting_release_time, - operator_vesting_release_time, - proportion: module_store.proportion, - }, - ); - - module_store.stage = stage + 1; - - // add tvl snapshot for next stage for minimum snapshot number( > 2) - add_tvl_snapshot_internal(module_store); - - } - - public entry fun submit_snapshot( - agent: &signer, - bridge_id: u64, - stage: u64, - merkle_root: vector, - total_l2_score: u64, - ) acquires ModuleStore { - check_agent_permission(agent); - let module_store = borrow_global_mut(@initia_std); - - assert!( - table::contains( - &module_store.stage_data, - table_key::encode_u64(stage), - ), - error::not_found(ESTAGE_DATA_NOT_FOUND), - ); - - // check previous stage snapshot is exist for preventing skipping stage - check_previous_stage_snapshot(module_store, bridge_id, stage); - - let stage_data = - table::borrow_mut( - &mut module_store.stage_data, - table_key::encode_u64(stage), - ); - - assert!( - !table::contains( - &stage_data.snapshots, - table_key::encode_u64(bridge_id), - ), - error::already_exists(ESNAPSHOT_ALREADY_EXISTS), - ); - - let (_, create_time) = block::get_block_info(); - table::add( - &mut stage_data.snapshots, - table_key::encode_u64(bridge_id), - Snapshot { - create_time, - upsert_time: create_time, - merkle_root, - total_l2_score - }, - ); - } - - public entry fun update_snapshot( - agent: &signer, - bridge_id: u64, - stage: u64, - merkle_root: vector, - total_l2_score: u64, - ) acquires ModuleStore { - check_agent_permission(agent); - let module_store = borrow_global_mut(@initia_std); - assert!( - table::contains( - &module_store.stage_data, - table_key::encode_u64(stage), - ), - error::not_found(ESTAGE_DATA_NOT_FOUND), - ); - let stage_data = - table::borrow_mut( - &mut module_store.stage_data, - table_key::encode_u64(stage), - ); - - let (_, block_time) = block::get_block_info(); - assert!( - block_time < stage_data.user_vesting_release_time, - error::unavailable(EALREADY_RELEASED), - ); - assert!( - block_time < stage_data.operator_vesting_release_time, - error::unavailable(EALREADY_RELEASED), - ); - assert!( - table::contains( - &stage_data.snapshots, - table_key::encode_u64(bridge_id), - ), - error::not_found(ESNAPSHOT_NOT_EXISTS), - ); - - let snapshot = - table::borrow_mut( - &mut stage_data.snapshots, - table_key::encode_u64(bridge_id), - ); - snapshot.merkle_root = merkle_root; - snapshot.total_l2_score = total_l2_score; - } - - fun check_claimable_period(bridge_id: u64, stage: u64) acquires ModuleStore { - - let (_, curr_time) = block::get_block_info(); - let module_store = borrow_global(@initia_std); - let stage_data = - table::borrow( - &module_store.stage_data, - table_key::encode_u64(stage), - ); - let snapshot_create_time = - table::borrow( - &stage_data.snapshots, - table_key::encode_u64(bridge_id), - ).create_time; - - assert!( - curr_time > snapshot_create_time + module_store.challenge_period, - error::permission_denied(EINVALID_CLAIMABLE_PERIOD), - ); - } - - public entry fun claim_operator_reward_script( - operator: &signer, - bridge_id: u64, - stage: u64, - ) acquires ModuleStore { - if (!vip_vesting::is_operator_vesting_store_registered( - signer::address_of(operator), - bridge_id, - )) { - vip_vesting::register_operator_vesting_store(operator, bridge_id); - }; - - let vested_reward = claim_operator_reward(operator, bridge_id, stage); - - coin::deposit(signer::address_of(operator), vested_reward); - } - - public entry fun claim_user_reward_script( - account: &signer, - bridge_id: u64, - stage: u64, - merkle_proofs: vector>, - l2_score: u64, - ) acquires ModuleStore { - if (!vip_vesting::is_user_vesting_store_registered( - signer::address_of(account), - bridge_id, - )) { - vip_vesting::register_user_vesting_store(account, bridge_id); - }; - - let vested_reward = - claim_user_reward( - account, - bridge_id, - stage, - merkle_proofs, - l2_score, - ); - - coin::deposit(signer::address_of(account), vested_reward); - } - - public entry fun batch_claim_operator_reward_script( - operator: &signer, - bridge_id: u64, - stage: vector, - ) acquires ModuleStore { - let prev_stage = 0; - vector::enumerate_ref( - &stage, - |_i, s| { - assert!( - *s > prev_stage, - error::invalid_argument(EINVALID_STAGE_ORDER), - ); - prev_stage = *s; - claim_operator_reward_script(operator, bridge_id, *s); - }, - ); - } - - public entry fun batch_claim_user_reward_script( - account: &signer, - bridge_id: u64, - stage: vector, - merkle_proofs: vector>>, - l2_score: vector, - ) acquires ModuleStore { - assert!( - vector::length(&stage) == vector::length(&merkle_proofs) - && vector::length(&merkle_proofs) == vector::length(&l2_score), - error::invalid_argument(EINVALID_BATCH_ARGUMENT), - ); - - let prev_stage = 0; - vector::enumerate_ref( - &stage, - |i, s| { - assert!( - *s > prev_stage, - error::invalid_argument(EINVALID_STAGE_ORDER), - ); - prev_stage = *s; - claim_user_reward_script( - account, - bridge_id, - *s, - *vector::borrow(&merkle_proofs, i), - *vector::borrow(&l2_score, i), - ); - }, - ); - } - - public entry fun update_vip_weights( - chain: &signer, - bridge_ids: vector, - weights: vector, - ) acquires ModuleStore { - check_chain_permission(chain); - update_vip_weights_for_friend(bridge_ids, weights) - } - - public entry fun update_vip_weight( - chain: &signer, - bridge_id: u64, - weight: Decimal256, - ) acquires ModuleStore { - check_chain_permission(chain); - let module_store = borrow_global_mut(@initia_std); - let bridge = load_bridge_mut(&mut module_store.bridges, bridge_id); - bridge.vip_weight = weight; - - validate_vip_weights(module_store); - } - - public entry fun update_stage_period( - chain: &signer, stage_period: u64, - ) acquires ModuleStore { - check_chain_permission(chain); - let module_store = borrow_global_mut(signer::address_of(chain)); - assert!( - stage_period > 0, - error::invalid_argument(EINVALID_VEST_PERIOD), - ); - module_store.stage_period = stage_period; - } - - public entry fun update_vesting_period( - chain: &signer, - user_vesting_period: u64, - operator_vesting_period: u64, - ) acquires ModuleStore { - check_chain_permission(chain); - let module_store = borrow_global_mut(signer::address_of(chain)); - assert!( - user_vesting_period > 0 && operator_vesting_period > 0, - error::invalid_argument(EINVALID_VEST_PERIOD), - ); - module_store.user_vesting_period = user_vesting_period; - module_store.operator_vesting_period = operator_vesting_period; - } - - public entry fun update_minimum_eligible_tvl( - chain: &signer, minimum_eligible_tvl: u64, - ) acquires ModuleStore { - check_chain_permission(chain); - let module_store = borrow_global_mut(signer::address_of(chain)); - module_store.minimum_eligible_tvl = minimum_eligible_tvl; - } - - public entry fun update_maximum_tvl_ratio( - chain: &signer, maximum_tvl_ratio: Decimal256, - ) acquires ModuleStore { - check_chain_permission(chain); - let module_store = borrow_global_mut(signer::address_of(chain)); - assert!( - decimal256::val(&maximum_tvl_ratio) <= decimal256::val(&decimal256::one()), - error::invalid_argument(EINVALID_MAX_TVL), - ); - module_store.maximum_tvl_ratio = maximum_tvl_ratio; - } - - public entry fun update_proportion( - chain: &signer, proportion: Decimal256, - ) acquires ModuleStore { - check_chain_permission(chain); - let module_store = borrow_global_mut(signer::address_of(chain)); - module_store.proportion = proportion; - } - - public entry fun update_pool_split_ratio( - chain: &signer, pool_split_ratio: Decimal256, - ) acquires ModuleStore { - check_chain_permission(chain); - let module_store = borrow_global_mut(signer::address_of(chain)); - assert!( - decimal256::val(&pool_split_ratio) <= decimal256::val(&decimal256::one()), - error::invalid_argument(EINVALID_PROPORTION), - ); - - module_store.pool_split_ratio = pool_split_ratio; - } - - public entry fun update_l2_score_contract( - chain: &signer, - bridge_id: u64, - new_vip_l2_score_contract: string::String, - ) acquires ModuleStore { - check_chain_permission(chain); - let module_store = borrow_global_mut(signer::address_of(chain)); - let bridge = load_bridge_mut(&mut module_store.bridges, bridge_id); - bridge.vip_l2_score_contract = new_vip_l2_score_contract; - } - - public entry fun zapping_script( - account: &signer, - bridge_id: u64, - lp_metadata: Object, - min_liquidity: option::Option, - validator: string::String, - stage: u64, - zapping_amount: u64, - stakelisted_amount: u64, - stakelisted_metadata: Object, - ) { - zapping( - account, - bridge_id, - lp_metadata, - min_liquidity, - validator, - stage, - zapping_amount, - stakelisted_amount, - stakelisted_metadata, - ); - } - - public entry fun batch_zapping_script( - account: &signer, - bridge_id: u64, - lp_metadata: vector>, - min_liquidity: vector>, - validator: vector, - stage: vector, - zapping_amount: vector, - stakelisted_amount: vector, - stakelisted_metadata: vector>, - ) { - let batch_length = vector::length(&stage); - assert!( - vector::length(&lp_metadata) == batch_length, - error::invalid_argument(EINVALID_BATCH_ARGUMENT), - ); - assert!( - vector::length(&min_liquidity) == batch_length, - error::invalid_argument(EINVALID_BATCH_ARGUMENT), - ); - assert!( - vector::length(&validator) == batch_length, - error::invalid_argument(EINVALID_BATCH_ARGUMENT), - ); - assert!( - vector::length(&zapping_amount) == batch_length, - error::invalid_argument(EINVALID_BATCH_ARGUMENT), - ); - assert!( - vector::length(&stakelisted_amount) == batch_length, - error::invalid_argument(EINVALID_BATCH_ARGUMENT), - ); - assert!( - vector::length(&stakelisted_metadata) == batch_length, - error::invalid_argument(EINVALID_BATCH_ARGUMENT), - ); - - vector::enumerate_ref( - &stage, - |i, s| { - zapping( - account, - bridge_id, - *vector::borrow(&lp_metadata, i), - *vector::borrow(&min_liquidity, i), - *vector::borrow(&validator, i), - *s, - *vector::borrow(&zapping_amount, i), - *vector::borrow(&stakelisted_amount, i), - *vector::borrow(&stakelisted_metadata, i), - ); - }, - ); - } - - public entry fun update_operator_commission( - operator: &signer, bridge_id: u64, commission_rate: Decimal256 - ) acquires ModuleStore { - let module_store = borrow_global(@initia_std); - vip_operator::update_operator_commission( - operator, - bridge_id, - module_store.stage, - commission_rate, - ); - } - - entry public fun update_challenge_period( - chain: &signer, challenge_period: u64, - ) acquires ModuleStore { - check_chain_permission(chain); - let module_store = borrow_global_mut(signer::address_of(chain)); - module_store.challenge_period = challenge_period; - } - - // - // View Functions - // - - #[view] - public fun get_snapshot(bridge_id: u64, stage: u64): SnapshotResponse acquires ModuleStore { - let module_store = borrow_global(@initia_std); - - assert!( - table::contains( - &module_store.stage_data, - table_key::encode_u64(stage), - ), - error::not_found(ESTAGE_DATA_NOT_FOUND), - ); - let snapshots = - table::borrow( - &module_store.stage_data, - table_key::encode_u64(stage), - ); - assert!( - table::contains( - &snapshots.snapshots, - table_key::encode_u64(bridge_id), - ), - error::not_found(ESNAPSHOT_NOT_EXISTS), - ); - let snapshot = - table::borrow( - &snapshots.snapshots, - table_key::encode_u64(bridge_id), - ); - - SnapshotResponse { - create_time: snapshot.create_time, - upsert_time: snapshot.upsert_time, - merkle_root: snapshot.merkle_root, - total_l2_score: snapshot.total_l2_score, - } - } - - #[view] - public fun get_expected_reward( - bridge_id: u64, fund_reward_amount: u64 - ): u64 acquires ModuleStore { - let module_store = borrow_global(@initia_std); - let balance_shares = simple_map::create(); - let weight_shares = simple_map::create(); - - let total_balance = calculate_balance_share(module_store, &mut balance_shares); - calculate_weight_share(module_store, &mut weight_shares); - assert!( - fund_reward_amount > 0, - error::invalid_argument(EINVALID_TOTAL_REWARD), - ); - assert!( - total_balance > 0, - error::invalid_state(EINVALID_TOTAL_SHARE), - ); - - let weight_ratio = - decimal256::sub( - &decimal256::one(), - &module_store.pool_split_ratio, - ); - let balance_pool_reward_amount = - decimal256::mul_u64( - &module_store.pool_split_ratio, - fund_reward_amount, - ); - let weight_pool_reward_amount = - decimal256::mul_u64(&weight_ratio, fund_reward_amount); - let balance_split_amount = - split_reward_with_share_internal( - &balance_shares, - bridge_id, - balance_pool_reward_amount, - ); - let weight_split_amount = - split_reward_with_share_internal( - &weight_shares, - bridge_id, - weight_pool_reward_amount, - ); - balance_split_amount + weight_split_amount - } - - #[view] - public fun get_stage_data(stage: u64): StageDataResponse acquires ModuleStore { - let module_store = borrow_global(@initia_std); - let stage_data = - table::borrow( - &module_store.stage_data, - table_key::encode_u64(stage), - ); - - StageDataResponse { - stage_period: stage_data.stage_period, - pool_split_ratio: stage_data.pool_split_ratio, - total_operator_funded_reward: stage_data.total_operator_funded_reward, - total_user_funded_reward: stage_data.total_user_funded_reward, - user_vesting_period: stage_data.user_vesting_period, - operator_vesting_period: stage_data.operator_vesting_period, - user_vesting_release_time: stage_data.user_vesting_release_time, - operator_vesting_release_time: stage_data.operator_vesting_release_time, - proportion: stage_data.proportion, - } - } - - #[view] - public fun get_bridge_info(bridge_id: u64): BridgeResponse acquires ModuleStore { - let module_store = borrow_global(@initia_std); - let bridge = load_bridge(&module_store.bridges, bridge_id); - - BridgeResponse { - init_stage: bridge.init_stage, - bridge_id: bridge_id, - bridge_addr: bridge.bridge_addr, - operator_addr: bridge.operator_addr, - vip_l2_score_contract: bridge.vip_l2_score_contract, - vip_weight: bridge.vip_weight, - user_reward_store_addr: bridge.user_reward_store_addr, - operator_reward_store_addr: bridge.operator_reward_store_addr, - } - } - - #[view] - public fun get_executed_challenge(challenge_id: u64,): ExecutedChallengeResponse acquires ModuleStore { - let module_store = borrow_global(@initia_std); - let key = table_key::encode_u64(challenge_id); - let executed_challenge = table::borrow(&module_store.challenges, key); - - ExecutedChallengeResponse { - title: executed_challenge.title, - summary: executed_challenge.summary, - new_api_uri: executed_challenge.api_uri, - new_agent: executed_challenge.new_agent, - new_merkle_root: executed_challenge.merkle_root, - } - } - - #[view] - public fun get_bridge_infos(): vector acquires ModuleStore { - let module_store = borrow_global(@initia_std); - let iter = table::iter( - &module_store.bridges, - option::none(), - option::none(), - 1, - ); - - let bridge_infos = vector::empty(); - loop { - if (!table::prepare, Bridge>(iter)) { break }; - let (bridge_id_vec, bridge) = table::next, Bridge>(iter); - vector::push_back( - &mut bridge_infos, - BridgeResponse { - init_stage: bridge.init_stage, - bridge_id: table_key::decode_u64(bridge_id_vec), - bridge_addr: bridge.bridge_addr, - operator_addr: bridge.operator_addr, - vip_l2_score_contract: bridge.vip_l2_score_contract, - vip_weight: bridge.vip_weight, - user_reward_store_addr: bridge.user_reward_store_addr, - operator_reward_store_addr: bridge.operator_reward_store_addr, - }, - ); - }; - - bridge_infos - } - - #[view] - public fun get_whitelisted_bridge_ids(): vector acquires ModuleStore { - let module_store = borrow_global(@initia_std); - let bridge_ids = vector::empty(); - - let iter = table::iter( - &module_store.bridges, - option::none(), - option::none(), - 1, - ); - loop { - if (!table::prepare, Bridge>(iter)) { break }; - let (key, _) = table::next, Bridge>(iter); - vector::push_back( - &mut bridge_ids, - table_key::decode_u64(key), - ); - }; - bridge_ids - } - - #[view] - public fun get_next_stage(bridge_id: u64): u64 acquires ModuleStore { - let module_store = borrow_global(@initia_std); - - let iter = table::iter( - &module_store.stage_data, - option::none(), - option::none(), - 2, - ); - loop { - if (!table::prepare, StageData>(iter)) { break }; - - let (key, value) = table::next, StageData>(iter); - if (table::contains( - &value.snapshots, - table_key::encode_u64(bridge_id), - )) { - return table_key::decode_u64(key) + 1 - }; - }; - - module_store.stage - } - - #[view] - public fun get_module_store(): ModuleResponse acquires ModuleStore { - let module_store = borrow_global_mut(@initia_std); - - ModuleResponse { - stage: module_store.stage, - stage_period: module_store.stage_period, - agent_data: AgentData { - agent: module_store.agent_data.agent, - api_uri: module_store.agent_data.api_uri - }, - proportion: module_store.proportion, - pool_split_ratio: module_store.pool_split_ratio, - user_vesting_period: module_store.user_vesting_period, - operator_vesting_period: module_store.operator_vesting_period, - minimum_eligible_tvl: module_store.minimum_eligible_tvl, - maximum_tvl_ratio: module_store.maximum_tvl_ratio, - challenge_period: module_store.challenge_period, - } - } - - #[view] - public fun batch_simulate_user_claim_reward( - initial_reward: vector, - minimum_score: vector, - vesting_period: vector, - l2_scores: vector> - ): (vector, vector) { - let batch_length = vector::length(&initial_reward); - assert!( - vector::length(&minimum_score) == batch_length, - error::invalid_argument(EINVALID_BATCH_ARGUMENT), - ); - assert!( - vector::length(&vesting_period) == batch_length, - error::invalid_argument(EINVALID_BATCH_ARGUMENT), - ); - assert!( - vector::length(&l2_scores) == batch_length, - error::invalid_argument(EINVALID_BATCH_ARGUMENT), - ); - assert!( - batch_length > 0, - error::invalid_argument(EINVALID_BATCH_ARGUMENT), - ); - - let claimable_list = vector::empty(); - let remaining_list = vector::empty(); - vector::enumerate_ref( - &initial_reward, - |i, reward| { - let (claimed_reward, remaining_reward) = - simulate_user_claim_reward( - *reward, - *vector::borrow(&minimum_score, i), - *vector::borrow(&vesting_period, i), - *vector::borrow(&l2_scores, i), - ); - vector::push_back(&mut claimable_list, claimed_reward); - vector::push_back( - &mut remaining_list, - remaining_reward, - ); - }, - ); - - (claimable_list, remaining_list) - } - - #[view] - public fun simulate_user_claim_reward( - initial_reward: u64, - minimum_score: u64, - vesting_period: u64, - l2_scores: vector - ): (u64, u64) { - let total_claimed_reward = 0; - let remaining_reward = initial_reward; - vector::enumerate_ref( - &l2_scores, - |_i, l2_score| { - let score_ratio = - if (*l2_score >= minimum_score) { - decimal256::one() - } else { - decimal256::from_ratio_u64(*l2_score, minimum_score) - }; - - let max_ratio = decimal256::div_u64(&decimal256::one(), vesting_period); - let vest_ratio = decimal256::mul(&max_ratio, &score_ratio); - let vest_amount = decimal256::mul_u64(&vest_ratio, initial_reward); - - if (vest_amount > remaining_reward) { - vest_amount = remaining_reward; - }; - remaining_reward = remaining_reward - vest_amount; - total_claimed_reward = total_claimed_reward + vest_amount; - }, - ); - (total_claimed_reward, remaining_reward) - } - - // Test Functions - // - - #[test_only] - use initia_std::coin::{BurnCapability, FreezeCapability, MintCapability}; - - #[test_only] - use initia_std::dex; - - #[test_only] - use initia_std::staking; - - #[test_only] - use initia_std::decimal128; - - #[test_only] - struct TestCapability has key { - burn_cap: BurnCapability, - freeze_cap: FreezeCapability, - mint_cap: MintCapability, - } - - #[test_only] - const DEFAULT_VIP_WEIGHT_RATIO_FOR_TEST: vector = b"1"; - - #[test_only] - const DEFAULT_PROPORTION_RATIO_FOR_TEST: vector = b"1"; - - #[test_only] - const DEFAULT_COMMISSION_MAX_RATE_FOR_TEST: vector = b"0.5"; - - #[test_only] - const DEFAULT_POOL_SPLIT_RATIO_FOR_TEST: vector = b"0.4"; - - #[test_only] - const DEFAULT_COMMISSION_MAX_CHANGE_RATE_FOR_TEST: vector = b"0.5"; - - #[test_only] - const DEFAULT_COMMISSION_RATE_FOR_TEST: vector = b"0"; - - #[test_only] - const DEFAULT_USER_VESTING_PERIOD_FOR_TEST: u64 = 52; - - #[test_only] - const DEFAULT_OPERATOR_VESTING_PERIOD_FOR_TEST: u64 = 52; - - #[test_only] - const DEFAULT_REWARD_PER_STAGE_FOR_TEST: u64 = 100_000_000_000; - - #[test_only] - const DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST: u64 = 604801; - - #[test_only] - const DEFAULT_NEW_CHALLENGE_PERIOD: u64 = 604800; - #[test_only] - const DEFAULT_API_URI_FOR_TEST: vector = b"test"; - - #[test_only] - const NEW_API_URI_FOR_TEST: vector = b"new"; - - #[test_only] - const BRIDGE_ID_FOR_TEST: u64 = 1; - - #[test_only] - const STAGE_FOR_TEST: u64 = 1; - - #[test_only] - const DEFAULT_VIP_L2_CONTRACT_FOR_TEST: vector = (b"vip_l2_contract"); - - #[test_only] - const CHALLENGE_ID_FOR_TEST: u64 = 1; - - #[test_only] - const NEW_L2_TOTAL_SCORE_FOR_TEST: u64 = 1000; - - #[test_only] - fun skip_period(period: u64) { - let (height, curr_time) = block::get_block_info(); - block::set_block_info(height, curr_time + period); - } - - #[test_only] - public fun init_module_for_test() acquires ModuleStore { - let chain = &initia_std::account::create_signer_for_test(@initia_std); - vip_vault::init_module_for_test(); - vip_vault::update_reward_per_stage(chain, DEFAULT_REWARD_PER_STAGE_FOR_TEST); - init_module(chain); - update_agent_by_chain( - chain, - signer::address_of(chain), - string::utf8(DEFAULT_API_URI_FOR_TEST), - ); - } - - #[test_only] - fun initialize_coin(account: &signer, symbol: string::String,) - : ( - coin::BurnCapability, - coin::FreezeCapability, - coin::MintCapability, - Object - ) { - let (mint_cap, burn_cap, freeze_cap) = - coin::initialize( - account, - option::none(), - string::utf8(b""), - symbol, - 6, - string::utf8(b""), - string::utf8(b""), - ); - let metadata = coin::metadata(signer::address_of(account), symbol); - - (burn_cap, freeze_cap, mint_cap, metadata) - } - - #[test_only] - fun test_register_bridge( - chain: &signer, - operator: &signer, - bridge_id: u64, - bridge_address: address, - init_stage: u64, - vip_l2_score_contract: string::String, - mint_amount: u64, - commission_max_rate: Decimal256, - commission_max_change_rate: Decimal256, - commission_rate: Decimal256, - mint_cap: &coin::MintCapability, - ): u64 acquires ModuleStore { - coin::mint_to( - mint_cap, - signer::address_of(chain), - mint_amount, - ); - coin::mint_to( - mint_cap, - signer::address_of(operator), - mint_amount, - ); - coin::mint_to( - mint_cap, - bridge_address, - mint_amount, - ); - vip_vault::deposit(chain, mint_amount); - - register( - chain, - signer::address_of(operator), - bridge_id, - bridge_address, - init_stage, - vip_l2_score_contract, - commission_max_rate, - commission_max_change_rate, - commission_rate, - ); - - bridge_id - } - - #[test_only] - public fun test_setup( - chain: &signer, - operator: &signer, - bridge_id: u64, - bridge_address: address, - vip_l2_score_contract: string::String, - mint_amount: u64, - ): u64 acquires ModuleStore { - primary_fungible_store::init_module_for_test(); - vip_tvl_manager::init_module_for_test(); - let (burn_cap, freeze_cap, mint_cap, _) = - initialize_coin(chain, string::utf8(b"uinit")); - init_module_for_test(); - - test_register_bridge( - chain, - operator, - bridge_id, - bridge_address, - 1, - vip_l2_score_contract, - mint_amount, - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_RATE_FOR_TEST) - ), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_CHANGE_RATE_FOR_TEST) - ), - decimal256::from_string(&string::utf8(DEFAULT_COMMISSION_RATE_FOR_TEST)), - &mint_cap, - ); - - update_proportion( - chain, - decimal256::from_string(&string::utf8(DEFAULT_PROPORTION_RATIO_FOR_TEST)), - ); - - update_vip_weight( - chain, - bridge_id, - decimal256::from_string(&string::utf8(DEFAULT_VIP_WEIGHT_RATIO_FOR_TEST)), - ); - - move_to( - chain, - TestCapability { burn_cap, freeze_cap, mint_cap, }, - ); - - bridge_id - } - - #[test_only] - public fun merkle_root_and_proof_scene1() - : ( - SimpleMap>, - SimpleMap>>, - SimpleMap, - SimpleMap - ) { - - let root_map = simple_map::create>(); - let proofs_map = simple_map::create>>(); - let score_map = simple_map::create(); - let total_score_map = simple_map::create(); - - simple_map::add( - &mut root_map, - 1, - x"fb9eab6b9b5f195d0927c8a7301682b1475425249bb6b8bb31afd0dbb2dd4d09", - ); - simple_map::add( - &mut root_map, - 2, - x"0ac37a58eb526e4577e78f59c46e70b3d0fd54b78c06905345bd7e14e75da42b", - ); - simple_map::add( - &mut root_map, - 3, - x"42c600b41e6ff29ee44e1d61d460f6c78db862c0f3abe42d14df858649a1eea9", - ); - simple_map::add( - &mut root_map, - 4, - x"dda4a2cd3385326bb304d1a6a62c35d39bb28d5acef58b5552e73b3c968e0c79", - ); - simple_map::add( - &mut root_map, - 5, - x"469bdc31f3b0fbc1fb1f2ab9337af4ecf1643d6173cdecee95b235c9ca232017", - ); - simple_map::add( - &mut root_map, - 6, - x"d2197ca826f0ee6084555f86fdd185a16788d68d8c512b025cb5829770682bd7", - ); - simple_map::add( - &mut root_map, - 7, - x"998d5df26676a108e6581d1bc6dab1c7fab86fbdbcc5f1b8e4847ebe74f29341", - ); - simple_map::add( - &mut root_map, - 8, - x"c41ff3aa918e489fc64a62d07915dab0c04b205e05dc6c9e4a8b7997091fdbdc", - ); - simple_map::add( - &mut root_map, - 9, - x"c363c5b4393942032b841d5d0f68213d475e285b2fd7e31a4128c97b91cef97a", - ); - simple_map::add( - &mut root_map, - 10, - x"2c4cc1daece91ee14d55d35595d17b8cc0bd6741b967ff82f73f6330c8b25b8a", - ); - - simple_map::add( - &mut proofs_map, - 1, - vector[ - x"0bb9c560686ab3b4e1ac1a41bbc74ccd4d348634985a1a312590346900a6c93e"], - ); - simple_map::add( - &mut proofs_map, - 2, - vector[ - x"66ffc3bb14e3bc65e022401feed6e2644082ccf69ccb40d1842fc6ca2d4c24fd"], - ); - simple_map::add( - &mut proofs_map, - 3, - vector[ - x"70ed0c868798b88361b42895df358f64c4b4dd074f0af7146ef8898a675fee4e"], - ); - simple_map::add( - &mut proofs_map, - 4, - vector[ - x"3e304abd07a33f4fab39537a4ac75c8886a89be9d8aaa96035675775a784b23e"], - ); - simple_map::add( - &mut proofs_map, - 5, - vector[ - x"2911095fa7f35a563471cfff4135031f5d648372cc384b6288a19d8216baa3fa"], - ); - simple_map::add( - &mut proofs_map, - 6, - vector[ - x"25a20d529493d2aef8beef43221b00231a0e8d07990e3d43b93fbf9cfd54de73"], - ); - simple_map::add( - &mut proofs_map, - 7, - vector[ - x"61a55e6aac46c32a47c96b0dc4fd5de1f705e7400460957acb10457904a4a990"], - ); - simple_map::add( - &mut proofs_map, - 8, - vector[ - x"96187ed75a9b83537e045912573bf3efee0a6369a663f1cb4d4ec7798c9f6299"], - ); - simple_map::add( - &mut proofs_map, - 9, - vector[ - x"759ac8ad2821f2dbeb253e0872c07ffc6ccd3f69b80d19b04f0e49d6a0ea8da7"], - ); - simple_map::add( - &mut proofs_map, - 10, - vector[ - x"98b1fed6531d027c0efb53d54941c83f8ceb9694b9ec199ee07278200c943eb1"], - ); - - simple_map::add(&mut score_map, 1, 800_000); - simple_map::add(&mut score_map, 2, 800_000); - simple_map::add(&mut score_map, 3, 400_000); - simple_map::add(&mut score_map, 4, 400_000); - simple_map::add(&mut score_map, 5, 800_000); - simple_map::add(&mut score_map, 6, 800_000); - simple_map::add(&mut score_map, 7, 800_000); - simple_map::add(&mut score_map, 8, 800_000); - simple_map::add(&mut score_map, 9, 800_000); - simple_map::add(&mut score_map, 10, 800_000); - - simple_map::add(&mut total_score_map, 1, 8_000_000); - simple_map::add(&mut total_score_map, 2, 8_000_000); - simple_map::add(&mut total_score_map, 3, 4_000_000); - simple_map::add(&mut total_score_map, 4, 4_000_000); - simple_map::add(&mut total_score_map, 5, 8_000_000); - simple_map::add(&mut total_score_map, 6, 8_000_000); - simple_map::add(&mut total_score_map, 7, 8_000_000); - simple_map::add(&mut total_score_map, 8, 8_000_000); - simple_map::add(&mut total_score_map, 9, 8_000_000); - simple_map::add(&mut total_score_map, 10, 8_000_000); - - (root_map, proofs_map, score_map, total_score_map) - } - - #[test_only] - public fun merkle_root_and_proof_scene2() - : ( - SimpleMap>, - SimpleMap>>, - SimpleMap, - SimpleMap - ) { - let root_map = simple_map::create>(); - let proofs_map = simple_map::create>>(); - let total_score_map = simple_map::create(); - - simple_map::add( - &mut root_map, - 1, - x"da8a26abe037981b46c77de776621601ea78ae2e9e4d095f4f6887d7b8fb4229", - ); - simple_map::add( - &mut root_map, - 2, - x"edbea69a471f721622e7c64d086b901a52b6edb058b97c8a776cd7f3180e1659", - ); - simple_map::add( - &mut root_map, - 3, - x"ecd24a0e9fe1ec83999cbdc0641f15cda95d40589073a6e8cc3234fde9357e65", - ); - simple_map::add( - &mut root_map, - 4, - x"5725135c9c856f4241a05027c815a64fe687525f496dcdc6c57f23a87d5e4ac1", - ); - simple_map::add( - &mut root_map, - 5, - x"183e88a1ca56d8a51d9390d8460621fe651997d63bf26392912e29e7323b08b0", - ); - simple_map::add( - &mut root_map, - 6, - x"9de1fd227b37e6ad88c1eae0f4fd97f8436900befa9c80f4f66735e9e8646f54", - ); - - simple_map::add(&mut proofs_map, 1, vector[]); - simple_map::add(&mut proofs_map, 2, vector[]); - simple_map::add(&mut proofs_map, 3, vector[]); - simple_map::add(&mut proofs_map, 4, vector[]); - simple_map::add(&mut proofs_map, 5, vector[]); - simple_map::add(&mut proofs_map, 6, vector[]); - - simple_map::add(&mut total_score_map, 1, 1_000); - simple_map::add(&mut total_score_map, 2, 1_000); - simple_map::add(&mut total_score_map, 3, 500); - simple_map::add(&mut total_score_map, 4, 500); - simple_map::add(&mut total_score_map, 5, 100); - simple_map::add(&mut total_score_map, 6, 100); - - (root_map, proofs_map, total_score_map, total_score_map) - } - - #[test_only] - public fun test_setup_scene1( - agent: &signer, - bridge_id: u64, - release_time: u64, - ) acquires ModuleStore { - let idx = 1; - let (merkle_root_map, _, _, total_score_map) = merkle_root_and_proof_scene1(); - - while (idx <= simple_map::length(&merkle_root_map)) { - let total_l2_score = *simple_map::borrow(&total_score_map, &idx); - let merkle_root = *simple_map::borrow(&merkle_root_map, &idx); - - fund_reward_script( - agent, - idx, - release_time, - release_time, - ); - submit_snapshot( - agent, - bridge_id, - idx, - merkle_root, - total_l2_score, - ); - idx = idx + 1; - }; - } - - #[test_only] - public fun test_setup_scene2( - agent: &signer, - bridge_id: u64, - release_time: u64, - ) acquires ModuleStore { - let idx = 1; - let (merkle_root_map, _, _, total_score_map) = merkle_root_and_proof_scene2(); - - while (idx <= simple_map::length(&merkle_root_map)) { - let total_l2_score = *simple_map::borrow(&total_score_map, &idx); - let merkle_root = *simple_map::borrow(&merkle_root_map, &idx); - - fund_reward_script( - agent, - idx, - release_time, - release_time, - ); - submit_snapshot( - agent, - bridge_id, - idx, - merkle_root, - total_l2_score, - ); - idx = idx + 1; - }; - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573)] - fun test_update_vip_weight(chain: &signer, operator: &signer,) acquires ModuleStore { - let init_stage = 1; - let mint_amount = 1_000_000_000; - primary_fungible_store::init_module_for_test(); - let (_, _, mint_cap, _) = initialize_coin(chain, string::utf8(b"uinit")); - init_module_for_test(); - - coin::mint_to( - &mint_cap, - signer::address_of(chain), - mint_amount, - ); - - // initialize vip_reward - register( - chain, - signer::address_of(operator), - 1, - @0x90, - init_stage, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_RATE_FOR_TEST) - ), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_CHANGE_RATE_FOR_TEST) - ), - decimal256::from_string(&string::utf8(DEFAULT_COMMISSION_RATE_FOR_TEST)), - ); - - let new_weight = decimal256::from_string(&string::utf8(b"0.7")); - update_vip_weight(chain, 1, new_weight); - - let bridge_info = get_bridge_info(1); - assert!( - decimal256::is_same( - &bridge_info.vip_weight, - &new_weight, - ), - 3, - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - fun test_update_proportion( - chain: &signer, operator: &signer, receiver: &signer - ) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - let release_time = 0; - - let (merkle_root_map, merkle_proof_map, score_map, total_score_map) = - merkle_root_and_proof_scene1(); - - fund_reward_script(chain, 1, release_time, release_time); - fund_reward_script(chain, 2, release_time, release_time); - submit_snapshot( - chain, - bridge_id, - 1, - *simple_map::borrow(&merkle_root_map, &1), - *simple_map::borrow(&total_score_map, &1), - ); - submit_snapshot( - chain, - bridge_id, - 2, - *simple_map::borrow(&merkle_root_map, &2), - *simple_map::borrow(&total_score_map, &2), - ); - - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - claim_user_reward_script( - receiver, - bridge_id, - 1, - *simple_map::borrow(&merkle_proof_map, &1), - *simple_map::borrow(&score_map, &1), - ); - claim_user_reward_script( - receiver, - bridge_id, - 2, - *simple_map::borrow(&merkle_proof_map, &2), - *simple_map::borrow(&score_map, &2), - ); - assert!( - vip_vesting::get_user_vesting_minimum_score( - signer::address_of(receiver), - bridge_id, - 1, - ) == *simple_map::borrow(&score_map, &1), - 1, - ); - assert!( - vip_vesting::get_user_vesting_minimum_score( - signer::address_of(receiver), - bridge_id, - 2, - ) == *simple_map::borrow(&score_map, &2), - 2, - ); - - update_proportion( - chain, - decimal256::from_string(&string::utf8(b"10")), - ); - - fund_reward_script(chain, 3, release_time, release_time); - submit_snapshot( - chain, - bridge_id, - 3, - *simple_map::borrow(&merkle_root_map, &3), - *simple_map::borrow(&total_score_map, &3), - ); - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - claim_user_reward_script( - receiver, - bridge_id, - 3, - *simple_map::borrow(&merkle_proof_map, &3), - *simple_map::borrow(&score_map, &3), - ); - assert!( - vip_vesting::get_user_vesting_minimum_score( - signer::address_of(receiver), - bridge_id, - 3, - ) == 4_000_000, - 3, - ); - - update_proportion( - chain, - decimal256::from_string(&string::utf8(b"0.5")), - ); - - fund_reward_script(chain, 4, release_time, release_time); - submit_snapshot( - chain, - bridge_id, - 4, - *simple_map::borrow(&merkle_root_map, &4), - *simple_map::borrow(&total_score_map, &4), - ); - - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - claim_user_reward_script( - receiver, - bridge_id, - 4, - *simple_map::borrow(&merkle_proof_map, &4), - *simple_map::borrow(&score_map, &3), - ); - - assert!( - vip_vesting::get_user_vesting_minimum_score( - signer::address_of(receiver), - bridge_id, - 4, - ) == 200_000, - 4, - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - fun test_update_l2_score_contract(chain: &signer, operator: &signer) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - let new_vip_l2_score_contract = string::utf8(b"new_vip_l2_score_contract"); - update_l2_score_contract( - chain, - bridge_id, - new_vip_l2_score_contract, - ); - - let bridge_info = get_bridge_info(bridge_id); - assert!( - bridge_info.vip_l2_score_contract == new_vip_l2_score_contract, - 0, - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - fun test_get_last_claimed_stages( - chain: &signer, operator: &signer, receiver: &signer - ) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - let (_, merkle_proof_map, score_map, _) = merkle_root_and_proof_scene1(); - test_setup_scene1(chain, bridge_id, 0); - - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - claim_user_reward_script( - receiver, - bridge_id, - 1, - *simple_map::borrow(&merkle_proof_map, &1), - *simple_map::borrow(&score_map, &1), - ); - assert!( - vip_vesting::get_user_last_claimed_stage( - signer::address_of(receiver), - bridge_id, - ) == 1, - 1, - ); - - claim_user_reward_script( - receiver, - bridge_id, - 2, - *simple_map::borrow(&merkle_proof_map, &2), - *simple_map::borrow(&score_map, &2), - ); - assert!( - vip_vesting::get_user_last_claimed_stage( - signer::address_of(receiver), - bridge_id, - ) == 2, - 2, - ); - - claim_user_reward_script( - receiver, - bridge_id, - 3, - *simple_map::borrow(&merkle_proof_map, &3), - *simple_map::borrow(&score_map, &3), - ); - assert!( - vip_vesting::get_user_last_claimed_stage( - signer::address_of(receiver), - bridge_id, - ) == 3, - 3, - ); - - claim_user_reward_script( - receiver, - bridge_id, - 4, - *simple_map::borrow(&merkle_proof_map, &4), - *simple_map::borrow(&score_map, &4), - ); - assert!( - vip_vesting::get_user_last_claimed_stage( - signer::address_of(receiver), - bridge_id, - ) == 4, - 4, - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - fun test_update_vesting_period( - chain: &signer, operator: &signer, receiver: &signer - ) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - let total_reward_per_stage = 100_000_000_000; - assert!( - vip_vault::reward_per_stage() == total_reward_per_stage, - 0, - ); - let portion = 10; - let reward_per_stage = total_reward_per_stage / portion; - let vesting_period = 10; - update_vesting_period( - chain, - vesting_period, - vesting_period, - ); - - let (_, merkle_proof_map, score_map, _) = merkle_root_and_proof_scene1(); - test_setup_scene1(chain, bridge_id, 0); - - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - claim_user_reward_script( - receiver, - bridge_id, - 1, - *simple_map::borrow(&merkle_proof_map, &1), - *simple_map::borrow(&score_map, &1), - ); - claim_user_reward_script( - receiver, - bridge_id, - 2, - *simple_map::borrow(&merkle_proof_map, &2), - *simple_map::borrow(&score_map, &2), - ); - claim_user_reward_script( - receiver, - bridge_id, - 3, - *simple_map::borrow(&merkle_proof_map, &3), - *simple_map::borrow(&score_map, &3), - ); - claim_user_reward_script( - receiver, - bridge_id, - 4, - *simple_map::borrow(&merkle_proof_map, &4), - *simple_map::borrow(&score_map, &4), - ); - claim_user_reward_script( - receiver, - bridge_id, - 5, - *simple_map::borrow(&merkle_proof_map, &5), - *simple_map::borrow(&score_map, &5), - ); - - assert!( - get_stage_data(1).user_vesting_period == vesting_period, - 1, - ); - - let expected_reward = - ( - reward_per_stage / vesting_period + reward_per_stage / (vesting_period * 2) - + reward_per_stage / (vesting_period * 2) - + reward_per_stage / vesting_period // stage 1 - + reward_per_stage / (vesting_period * 2) - + reward_per_stage / (vesting_period * 2) - + reward_per_stage / vesting_period // stage 2 - + reward_per_stage / vesting_period + reward_per_stage / vesting_period // stage 3 - + reward_per_stage / vesting_period // stage 4 - ); - - assert!( - coin::balance( - signer::address_of(receiver), - vip_reward::reward_metadata(), - ) == expected_reward, - 2, - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - fun test_finalized_vesting( - chain: &signer, operator: &signer, receiver: &signer - ) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - let vesting_period = 2; - update_vesting_period( - chain, - vesting_period, - vesting_period, - ); - - let (_, merkle_proof_map, score_map, _) = merkle_root_and_proof_scene1(); - test_setup_scene1(chain, bridge_id, 0); - - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - claim_user_reward_script( - receiver, - bridge_id, - 1, - *simple_map::borrow(&merkle_proof_map, &1), - *simple_map::borrow(&score_map, &1), // vesting 1 created - ); - claim_user_reward_script( - receiver, - bridge_id, - 2, - *simple_map::borrow(&merkle_proof_map, &2), - *simple_map::borrow(&score_map, &2), // vesting 2 created - ); - - vip_vesting::get_user_vesting( - signer::address_of(receiver), - bridge_id, - 1, - ); - vip_vesting::get_user_vesting( - signer::address_of(receiver), - bridge_id, - 2, - ); - - claim_user_reward_script( - receiver, - bridge_id, - 3, - *simple_map::borrow(&merkle_proof_map, &3), - *simple_map::borrow(&score_map, &3), - ); - claim_user_reward_script( - receiver, - bridge_id, - 4, - *simple_map::borrow(&merkle_proof_map, &4), - *simple_map::borrow(&score_map, &4), // vesting 1 finalized - ); - claim_user_reward_script( - receiver, - bridge_id, - 5, - *simple_map::borrow(&merkle_proof_map, &5), - *simple_map::borrow(&score_map, &5), // vesting 2 finalized - ); - - vip_vesting::get_user_vesting_finalized( - signer::address_of(receiver), - bridge_id, - 1, - ); - vip_vesting::get_user_vesting_finalized( - signer::address_of(receiver), - bridge_id, - 2, - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573)] - fun test_update_minimum_eligible_tvl( - chain: &signer, operator: &signer - ) acquires ModuleStore { - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - let module_response = get_module_store(); - assert!(module_response.minimum_eligible_tvl == 0, 0); - - update_minimum_eligible_tvl(chain, 1_000_000_000_000); - - let module_response = get_module_store(); - assert!( - module_response.minimum_eligible_tvl == 1_000_000_000_000, - 0, - ); - - update_minimum_eligible_tvl(chain, 500_000_000_000); - - let module_response = get_module_store(); - assert!( - module_response.minimum_eligible_tvl == 500_000_000_000, - 0, - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, new_agent = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - fun test_execute_challenge( - chain: &signer, - operator: &signer, - new_agent: address, - ) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - test_setup_scene1(chain, bridge_id, 0); - let (_, create_time) = block::get_block_info(); - let title: string::String = string::utf8(NEW_API_URI_FOR_TEST); - let summary: string::String = string::utf8(NEW_API_URI_FOR_TEST); - let new_api_uri: string::String = string::utf8(NEW_API_URI_FOR_TEST); - let (new_merkle_root, _, _, _) = merkle_root_and_proof_scene2(); - skip_period(10); - execute_challenge( - chain, - BRIDGE_ID_FOR_TEST, - STAGE_FOR_TEST, - CHALLENGE_ID_FOR_TEST, - title, - summary, - new_api_uri, - new_agent, - *simple_map::borrow( - &new_merkle_root, - &BRIDGE_ID_FOR_TEST, - ), - NEW_L2_TOTAL_SCORE_FOR_TEST, - ); - - let SnapshotResponse { - create_time: expected_create_time, - upsert_time: expected_upsert_time, - merkle_root: expected_merkle_root, - total_l2_score: _, - } = get_snapshot(BRIDGE_ID_FOR_TEST, STAGE_FOR_TEST); - - assert!(create_time == expected_create_time, 0); - assert!(expected_upsert_time > create_time, 0); - assert!( - expected_merkle_root - == *simple_map::borrow( - &new_merkle_root, - &BRIDGE_ID_FOR_TEST, - ), - 0, - ); - - let ExecutedChallengeResponse { - title: expected_title, - summary: expected_summary, - new_api_uri: expected_new_api_uri, - new_agent: expected_agent, - new_merkle_root: expected_new_merkle_root, - } = get_executed_challenge(CHALLENGE_ID_FOR_TEST); - - assert!(expected_title == title, 0); - assert!(expected_summary == summary, 0); - assert!(expected_new_api_uri == new_api_uri, 0); - assert!(expected_agent == new_agent, 0); - assert!( - expected_new_merkle_root - == *simple_map::borrow( - &new_merkle_root, - &BRIDGE_ID_FOR_TEST, - ), - 0, - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - #[expected_failure(abort_code = 0x10006, location = initia_std::vip_vesting)] - fun failed_claim_already_claimed( - chain: &signer, operator: &signer, receiver: &signer - ) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - let (_, merkle_proof_map, score_map, _) = merkle_root_and_proof_scene1(); - test_setup_scene1(chain, bridge_id, 0); - - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - claim_user_reward_script( - receiver, - bridge_id, - 1, - *simple_map::borrow(&merkle_proof_map, &1), - *simple_map::borrow(&score_map, &1), - ); - claim_user_reward_script( - receiver, - bridge_id, - 1, - *simple_map::borrow(&merkle_proof_map, &1), - *simple_map::borrow(&score_map, &1), - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - #[expected_failure(abort_code = 0x50017, location = Self)] - fun failed_user_claim_invalid_period( - chain: &signer, operator: &signer, receiver: &signer - ) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - let (_, merkle_proof_map, score_map, _) = merkle_root_and_proof_scene1(); - - test_setup_scene1(chain, bridge_id, 0); - - claim_user_reward_script( - receiver, - bridge_id, - 1, - *simple_map::borrow(&merkle_proof_map, &1), - *simple_map::borrow(&score_map, &1), - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573)] - #[expected_failure(abort_code = 0x50017, location = Self)] - fun failed_operator_claim_invalid_period( - chain: &signer, operator: &signer, - ) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - test_setup_scene1(chain, bridge_id, 0); - - claim_operator_reward_script(operator, bridge_id, 1); - - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - fun test_user_claim_valid_period( - chain: &signer, operator: &signer, receiver: &signer - ) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - let (_, merkle_proof_map, score_map, _) = merkle_root_and_proof_scene1(); - - test_setup_scene1(chain, bridge_id, 0); - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - claim_user_reward_script( - receiver, - bridge_id, - 1, - *simple_map::borrow(&merkle_proof_map, &1), - *simple_map::borrow(&score_map, &1), - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573)] - fun operator_claim_valid_period(chain: &signer, operator: &signer,) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - test_setup_scene1(chain, bridge_id, 0); - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - claim_operator_reward_script(operator, bridge_id, 1); - - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, new_agent = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - #[expected_failure(abort_code = 0x50018, location = Self)] - fun failed_execute_challenge( - chain: &signer, - operator: &signer, - new_agent: address, - ) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - test_setup_scene1(chain, bridge_id, 0); - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - let title: string::String = string::utf8(NEW_API_URI_FOR_TEST); - let summary: string::String = string::utf8(NEW_API_URI_FOR_TEST); - let new_api_uri: string::String = string::utf8(NEW_API_URI_FOR_TEST); - let (new_merkle_root, _, _, _) = merkle_root_and_proof_scene2(); - - execute_challenge( - chain, - BRIDGE_ID_FOR_TEST, - STAGE_FOR_TEST, - CHALLENGE_ID_FOR_TEST, - title, - summary, - new_api_uri, - new_agent, - *simple_map::borrow( - &new_merkle_root, - &BRIDGE_ID_FOR_TEST, - ), - NEW_L2_TOTAL_SCORE_FOR_TEST, - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - #[expected_failure(abort_code = 0xD000F, location = Self)] - fun failed_vesting_in_progress( - chain: &signer, operator: &signer, receiver: &signer - ) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - let release_time = 700000; - let (merkle_root_map, merkle_proof_map, score_map, total_score_map) = - merkle_root_and_proof_scene1(); - - fund_reward_script(chain, 1, release_time, release_time); - - submit_snapshot( - chain, - bridge_id, - 1, - *simple_map::borrow(&merkle_root_map, &1), - *simple_map::borrow(&total_score_map, &1), - ); - - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - claim_user_reward_script( - receiver, - bridge_id, - 1, - *simple_map::borrow(&merkle_proof_map, &1), - *simple_map::borrow(&score_map, &1), - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - fun test_batch_claim( - chain: &signer, operator: &signer, receiver: &signer - ) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - let (_, merkle_proof_map, _, _) = merkle_root_and_proof_scene2(); - test_setup_scene2(chain, bridge_id, 0); - - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - batch_claim_user_reward_script( - receiver, - bridge_id, - vector[1, 2, 3, 4, 5, 6], - vector[ - *simple_map::borrow(&merkle_proof_map, &1), *simple_map::borrow( - &merkle_proof_map, &2 - ), *simple_map::borrow(&merkle_proof_map, &3), *simple_map::borrow( - &merkle_proof_map, &4 - ), *simple_map::borrow(&merkle_proof_map, &5), *simple_map::borrow( - &merkle_proof_map, &6 - ),], - vector[1_000, 1_000, 500, 500, 100, 100], - ); - - batch_claim_operator_reward_script( - receiver, - bridge_id, - vector[1, 2, 3, 4, 5, 6], - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - fun test_shrink_reward( - chain: &signer, operator: &signer, receiver: &signer - ) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - let vesting_period = 5; - let total_reward_per_stage = DEFAULT_REWARD_PER_STAGE_FOR_TEST; - let reward_per_stage = total_reward_per_stage; - - update_proportion( - chain, - decimal256::from_string(&string::utf8(b"0.3")), - ); - update_vesting_period( - chain, - vesting_period, - vesting_period, - ); - - let (_, merkle_proof_map, score_map, _) = merkle_root_and_proof_scene2(); - test_setup_scene2(chain, bridge_id, 0); - - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - claim_user_reward_script( - receiver, - bridge_id, - 1, - *simple_map::borrow(&merkle_proof_map, &1), - *simple_map::borrow(&score_map, &1), - ); - claim_user_reward_script( - receiver, - bridge_id, - 2, - *simple_map::borrow(&merkle_proof_map, &2), - *simple_map::borrow(&score_map, &2), - ); - claim_user_reward_script( - receiver, - bridge_id, - 3, - *simple_map::borrow(&merkle_proof_map, &3), - *simple_map::borrow(&score_map, &3), - ); - claim_user_reward_script( - receiver, - bridge_id, - 4, - *simple_map::borrow(&merkle_proof_map, &4), - *simple_map::borrow(&score_map, &4), - ); - claim_user_reward_script( - receiver, - bridge_id, - 5, - *simple_map::borrow(&merkle_proof_map, &5), - *simple_map::borrow(&score_map, &5), - ); - claim_user_reward_script( - receiver, - bridge_id, - 6, - *simple_map::borrow(&merkle_proof_map, &6), - *simple_map::borrow(&score_map, &6), - ); - - let initia_reward_amount = - vip_vesting::get_user_vesting_initial_reward( - signer::address_of(receiver), - bridge_id, - 1, - ); - - let remaining_reward_amount = - vip_vesting::get_user_vesting_remaining_reward( - signer::address_of(receiver), - bridge_id, - 1, - ); - - let reward_by_stage_1 = initia_reward_amount - remaining_reward_amount; - let max_reward_per_claim = reward_per_stage / vesting_period; - - // score_ratio = l2_score > minimum_score ? 1 : l2_score / minimum_score - assert!( - reward_by_stage_1 - == max_reward_per_claim // score_ratio = 1 - + (max_reward_per_claim + max_reward_per_claim) // score_ratio = 1 - + (max_reward_per_claim / 3 + max_reward_per_claim / 3) // score_ratio = 1/3 - , - 1, - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - fun test_claim_jump_stage( - chain: &signer, operator: &signer, receiver: &signer - ) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - let total_reward_per_stage = DEFAULT_REWARD_PER_STAGE_FOR_TEST; - let reward_per_stage = total_reward_per_stage / 10; - - let vesting_period = DEFAULT_USER_VESTING_PERIOD; - - let (_, merkle_proof_map, score_map, _) = merkle_root_and_proof_scene1(); - test_setup_scene1(chain, bridge_id, 0); - - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - claim_user_reward_script( - receiver, - bridge_id, - 1, - *simple_map::borrow(&merkle_proof_map, &1), - *simple_map::borrow(&score_map, &1), - ); - claim_user_reward_script( - receiver, - bridge_id, - 3, - *simple_map::borrow(&merkle_proof_map, &3), - *simple_map::borrow(&score_map, &3), - ); - - assert!( - coin::balance( - signer::address_of(receiver), - vip_reward::reward_metadata(), - ) == (reward_per_stage / (vesting_period * 2)), - 1, - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573)] - fun test_fund_reward_script(chain: &signer, operator: &signer,) acquires ModuleStore { - let init_stage = 1; - let mint_amount = 100_000_000_000_000; - primary_fungible_store::init_module_for_test(); - vip_tvl_manager::init_module_for_test(); - let (_, _, mint_cap, _) = initialize_coin(chain, string::utf8(b"uinit")); - init_module_for_test(); - - coin::mint_to( - &mint_cap, - signer::address_of(chain), - mint_amount, - ); - vip_vault::deposit(chain, mint_amount); - coin::mint_to(&mint_cap, @0x90, mint_amount / 2); - coin::mint_to(&mint_cap, @0x91, mint_amount / 4); - coin::mint_to(&mint_cap, @0x92, mint_amount / 4); - let operator_addr = signer::address_of(operator); - let release_time = 0; - - // initialize vip_reward - register( - chain, - operator_addr, - 1, - @0x90, - init_stage, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_RATE_FOR_TEST) - ), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_CHANGE_RATE_FOR_TEST) - ), - decimal256::from_string(&string::utf8(DEFAULT_COMMISSION_RATE_FOR_TEST)), - ); - - register( - chain, - operator_addr, - 2, - @0x91, - init_stage, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_RATE_FOR_TEST) - ), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_CHANGE_RATE_FOR_TEST) - ), - decimal256::from_string(&string::utf8(DEFAULT_COMMISSION_RATE_FOR_TEST)), - ); - - register( - chain, - operator_addr, - 3, - @0x92, - init_stage, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_RATE_FOR_TEST) - ), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_CHANGE_RATE_FOR_TEST) - ), - decimal256::from_string(&string::utf8(DEFAULT_COMMISSION_RATE_FOR_TEST)), - ); - - let whitelisted_bridge_ids = get_whitelisted_bridge_ids(); - assert!(whitelisted_bridge_ids == vector[1, 2, 3], 0); - update_pool_split_ratio( - chain, - decimal256::from_string(&string::utf8(b"0.7")), - ); - add_tvl_snapshot(chain); - fund_reward_script(chain, 1, release_time, release_time); - assert!( - get_expected_reward( - 1, - DEFAULT_REWARD_PER_STAGE_FOR_TEST, - ) == 35_000_000_000, - 0, - ); // 0.7 * DEFAULT_REWARD_PER_STAGE_FOR_TEST * (2/4) + 0.3 * DEFAULT_REWARD_PER_STAGE_FOR_TEST * 0 - assert!( - get_expected_reward( - 2, - DEFAULT_REWARD_PER_STAGE_FOR_TEST, - ) == 17_500_000_000, - 0, - ); // 0.7 * DEFAULT_REWARD_PER_STAGE_FOR_TEST * (1/4) + 0.3 * DEFAULT_REWARD_PER_STAGE_FOR_TEST * 0 - assert!( - get_expected_reward( - 3, - DEFAULT_REWARD_PER_STAGE_FOR_TEST, - ) == 17_500_000_000, - 0, - ); // 0.7 * DEFAULT_REWARD_PER_STAGE_FOR_TEST * (1/4) + 0.3 * DEFAULT_REWARD_PER_STAGE_FOR_TEST * 0 - - assert!( - vip_reward::balance(vip_vesting::get_user_reward_store_address(1)) - == get_expected_reward(1, DEFAULT_REWARD_PER_STAGE_FOR_TEST), - 0, - ); - assert!( - vip_reward::balance(vip_vesting::get_user_reward_store_address(2)) - == get_expected_reward(2, DEFAULT_REWARD_PER_STAGE_FOR_TEST), - 0, - ); - assert!( - vip_reward::balance(vip_vesting::get_user_reward_store_address(3)) - == get_expected_reward(3, DEFAULT_REWARD_PER_STAGE_FOR_TEST), - 0, - ); - add_tvl_snapshot(chain); - fund_reward_script(chain, 2, release_time, release_time); - assert!( - vip_reward::balance(vip_vesting::get_operator_reward_store_address(1)) == 0, - 0, - ); - assert!( - vip_reward::balance(vip_vesting::get_operator_reward_store_address(2)) == 0, - 0, - ); - assert!( - vip_reward::balance(vip_vesting::get_operator_reward_store_address(3)) == 0, - 0, - ); - - update_operator_commission( - operator, - 1, - decimal256::from_string(&string::utf8(b"0.5")), - ); - update_operator_commission( - operator, - 2, - decimal256::from_string(&string::utf8(b"0.5")), - ); - add_tvl_snapshot(chain); - fund_reward_script(chain, 3, release_time, release_time); - assert!( - vip_reward::balance(vip_vesting::get_operator_reward_store_address(1)) - == get_expected_reward(1, DEFAULT_REWARD_PER_STAGE_FOR_TEST) / 2, - 0, - ); - assert!( - vip_reward::balance(vip_vesting::get_operator_reward_store_address(2)) - == get_expected_reward(2, DEFAULT_REWARD_PER_STAGE_FOR_TEST) / 2, - 0, - ); - assert!( - vip_reward::balance(vip_vesting::get_operator_reward_store_address(3)) == 0, - 0, - ); - - } - - #[test(chain = @0x1, agent = @0x2, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - fun test_deregistered_bridge( - chain: &signer, - agent: &signer, - operator: &signer, - receiver: &signer - ) acquires ModuleStore, TestCapability { - let init_stage = 1; - primary_fungible_store::init_module_for_test(); - vip_tvl_manager::init_module_for_test(); - let (burn_cap, freeze_cap, mint_cap, _) = - initialize_coin(chain, string::utf8(b"uinit")); - init_module_for_test(); - - move_to( - chain, - TestCapability { burn_cap, freeze_cap, mint_cap, }, - ); - - let cap = borrow_global(signer::address_of(chain)); - let operator_addr = signer::address_of(operator); - let (bridge_id1, bridge_id2) = (1, 2); - let (bridge_address1, bridge_address2) = (@0x999, @0x1000); - let mint_amount = 1_000_000_000_000; - let release_time = 0; - - coin::mint_to( - &cap.mint_cap, - signer::address_of(chain), - mint_amount, - ); - vip_vault::deposit(chain, mint_amount); - coin::mint_to( - &cap.mint_cap, - signer::address_of(operator), - mint_amount, - ); - coin::mint_to( - &cap.mint_cap, - bridge_address1, - mint_amount, - ); - coin::mint_to( - &cap.mint_cap, - bridge_address2, - mint_amount, - ); - - register( - chain, - operator_addr, - bridge_id1, - bridge_address1, - init_stage, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_RATE_FOR_TEST) - ), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_CHANGE_RATE_FOR_TEST) - ), - decimal256::from_string(&string::utf8(DEFAULT_COMMISSION_RATE_FOR_TEST)), - ); - - // need other L2 to increase stage - register( - chain, - operator_addr, - bridge_id2, - bridge_address2, - init_stage, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_RATE_FOR_TEST) - ), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_CHANGE_RATE_FOR_TEST) - ), - decimal256::from_string(&string::utf8(DEFAULT_COMMISSION_RATE_FOR_TEST)), - ); - - let (merkle_root_map, merkle_proof_map, score_map, total_score_map) = - merkle_root_and_proof_scene1(); - - update_agent( - chain, - signer::address_of(agent), - string::utf8(b""), - ); - update_vip_weights( - chain, - vector[1, 2], - vector[ - decimal256::from_string(&string::utf8(b"0.5")), - decimal256::from_string(&string::utf8(b"0.5"))], - ); - fund_reward_script(agent, 1, release_time, release_time); - fund_reward_script(agent, 2, release_time, release_time); - - deregister(chain, bridge_id1); - - fund_reward_script(agent, 3, release_time, release_time); - fund_reward_script(agent, 4, release_time, release_time); - - register( - chain, - operator_addr, - bridge_id1, - @0x999, - init_stage, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_RATE_FOR_TEST) - ), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_CHANGE_RATE_FOR_TEST) - ), - decimal256::from_string(&string::utf8(DEFAULT_COMMISSION_RATE_FOR_TEST)), - ); - - fund_reward_script(agent, 5, release_time, release_time); - - submit_snapshot( - agent, - bridge_id1, - 1, - *simple_map::borrow(&merkle_root_map, &1), - *simple_map::borrow(&total_score_map, &1), - ); - submit_snapshot( - agent, - bridge_id1, - 2, - *simple_map::borrow(&merkle_root_map, &2), - *simple_map::borrow(&total_score_map, &2), - ); - submit_snapshot( - agent, - bridge_id1, - 3, - *simple_map::borrow(&merkle_root_map, &3), - *simple_map::borrow(&total_score_map, &3), - ); - submit_snapshot( - agent, - bridge_id1, - 4, - *simple_map::borrow(&merkle_root_map, &4), - *simple_map::borrow(&total_score_map, &4), - ); - submit_snapshot( - agent, - bridge_id1, - 5, - *simple_map::borrow(&merkle_root_map, &5), - *simple_map::borrow(&total_score_map, &5), - ); - - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - claim_user_reward_script( - receiver, - bridge_id1, - 1, - *simple_map::borrow(&merkle_proof_map, &1), - *simple_map::borrow(&score_map, &1), - ); - claim_user_reward_script( - receiver, - bridge_id1, - 2, - *simple_map::borrow(&merkle_proof_map, &2), - *simple_map::borrow(&score_map, &2), - ); - claim_user_reward_script( - receiver, - bridge_id1, - 5, - *simple_map::borrow(&merkle_proof_map, &5), - *simple_map::borrow(&score_map, &5), - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - fun test_e2e_scene1( - chain: &signer, operator: &signer, receiver: &signer - ) acquires ModuleStore { - let operator_addr = signer::address_of(operator); - let vesting_period = DEFAULT_USER_VESTING_PERIOD_FOR_TEST; - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - let total_reward_per_stage = DEFAULT_REWARD_PER_STAGE_FOR_TEST; - let reward_per_stage = total_reward_per_stage / 10; - - let (_, merkle_proof_map, score_map, _) = merkle_root_and_proof_scene1(); - test_setup_scene1(chain, bridge_id, 0); - - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - claim_user_reward_script( - receiver, - bridge_id, - 1, - *simple_map::borrow(&merkle_proof_map, &1), - *simple_map::borrow(&score_map, &1), - ); - assert!( - coin::balance( - signer::address_of(receiver), - vip_reward::reward_metadata(), - ) == 0, - 1, - ); - - claim_user_reward_script( - receiver, - bridge_id, - 2, - *simple_map::borrow(&merkle_proof_map, &2), - *simple_map::borrow(&score_map, &2), - ); - assert!( - coin::balance( - signer::address_of(receiver), - vip_reward::reward_metadata(), - ) == (reward_per_stage / vesting_period), - 3, - ); - - // half score - claim_user_reward_script( - receiver, - bridge_id, - 3, - *simple_map::borrow(&merkle_proof_map, &3), - *simple_map::borrow(&score_map, &3), - ); - assert!( - coin::balance( - signer::address_of(receiver), - vip_reward::reward_metadata(), - ) == ( - reward_per_stage / vesting_period + reward_per_stage / (vesting_period * 2) - + reward_per_stage / (vesting_period * 2) - ), - 4, - ); - - claim_user_reward_script( - receiver, - bridge_id, - 4, - *simple_map::borrow(&merkle_proof_map, &4), - *simple_map::borrow(&score_map, &4), - ); - assert!( - coin::balance( - signer::address_of(receiver), - vip_reward::reward_metadata(), - ) == ( - reward_per_stage / vesting_period + reward_per_stage / (vesting_period * 2) - + reward_per_stage / (vesting_period * 2) // stage 1 - + reward_per_stage / (vesting_period * 2) - + reward_per_stage / (vesting_period * 2) // stage 2 - + reward_per_stage / vesting_period // stage 3 - ), - 5, - ); - - claim_user_reward_script( - receiver, - bridge_id, - 5, - *simple_map::borrow(&merkle_proof_map, &5), - *simple_map::borrow(&score_map, &5), - ); - assert!( - coin::balance( - signer::address_of(receiver), - vip_reward::reward_metadata(), - ) == ( - reward_per_stage / vesting_period + reward_per_stage / (vesting_period * 2) - + reward_per_stage / (vesting_period * 2) - + reward_per_stage / vesting_period // stage 1 - + reward_per_stage / (vesting_period * 2) - + reward_per_stage / (vesting_period * 2) - + reward_per_stage / vesting_period // stage 2 - + reward_per_stage / vesting_period + reward_per_stage / vesting_period // stage 3 - + reward_per_stage / vesting_period // stage 4 - ), - 6, - ); - - let proportion = - decimal256::from_string(&string::utf8(DEFAULT_PROPORTION_RATIO_FOR_TEST)); - let (claimable_list, _) = - batch_simulate_user_claim_reward( - vector[reward_per_stage, reward_per_stage], - vector[ - decimal256::mul_u64( - &proportion, - *simple_map::borrow(&score_map, &1), - ), - decimal256::mul_u64( - &proportion, - *simple_map::borrow(&score_map, &2), - ),], - vector[vesting_period, vesting_period], - vector[ - vector[ - *simple_map::borrow(&score_map, &2), - *simple_map::borrow(&score_map, &3), - *simple_map::borrow(&score_map, &4), - *simple_map::borrow(&score_map, &5)], - vector[ - *simple_map::borrow(&score_map, &3), - *simple_map::borrow(&score_map, &4), - *simple_map::borrow(&score_map, &5)],], - ); - - let claimable_v1 = *vector::borrow(&claimable_list, 0); - let claimable_v2 = *vector::borrow(&claimable_list, 1); - assert!( - claimable_v1 - == ( - reward_per_stage / vesting_period - + reward_per_stage / (vesting_period * 2) - + reward_per_stage / (vesting_period * 2) - + reward_per_stage / vesting_period - ), - 0, - ); - assert!( - claimable_v2 - == ( - reward_per_stage / (vesting_period * 2) - + reward_per_stage / (vesting_period * 2) - + reward_per_stage / vesting_period - ), - 0, - ); - - let user_reward_store_addr = - vip_vesting::get_user_reward_store_address(bridge_id); - let operator_reward_store_addr = - vip_vesting::get_operator_reward_store_address(bridge_id); - let bridge_info = get_bridge_info(bridge_id); - assert!( - bridge_info.user_reward_store_addr == user_reward_store_addr - && bridge_info.operator_reward_store_addr == operator_reward_store_addr - && bridge_info.operator_addr == operator_addr - && bridge_info.bridge_addr == @0x99 - && decimal256::is_same( - &bridge_info.vip_weight, - &decimal256::from_string( - &string::utf8(DEFAULT_VIP_WEIGHT_RATIO_FOR_TEST) - ), - ), - 7, - ); - assert!( - vip_reward::get_stage_reward(user_reward_store_addr, 1) == total_reward_per_stage, - 8, - ); - assert!( - vip_reward::get_stage_reward(user_reward_store_addr, 100) == 0, - 9, - ); // not exists - } - - #[test(chain = @0x1, agent = @0x2, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - fun test_e2e_scene2( - chain: &signer, - agent: &signer, - operator: &signer, - receiver: &signer - ) acquires ModuleStore { - let vesting_period = DEFAULT_USER_VESTING_PERIOD_FOR_TEST; - let operator_vesting_period = DEFAULT_OPERATOR_VESTING_PERIOD_FOR_TEST; - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x99, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 1_000_000_000_000, - ); - - update_proportion( - chain, - decimal256::from_string(&string::utf8(b"0.5")), - ); - let share_portion = 10; - let total_reward_per_stage = DEFAULT_REWARD_PER_STAGE_FOR_TEST; - let reward_per_stage = DEFAULT_REWARD_PER_STAGE_FOR_TEST / share_portion; - let reward_per_stage_by_vesting = reward_per_stage / vesting_period; - let release_time = 0; - - let (merkle_root_map, merkle_proof_map, score_map, total_score_map) = - merkle_root_and_proof_scene1(); - - update_agent( - chain, - signer::address_of(agent), - string::utf8(b""), - ); - - fund_reward_script(agent, 1, release_time, release_time); - - vip_vault::update_reward_per_stage(chain, total_reward_per_stage / 2); - fund_reward_script(agent, 2, release_time, release_time); - - vip_vault::update_reward_per_stage(chain, total_reward_per_stage); - fund_reward_script(agent, 3, release_time, release_time); - - // set commission from stage 4 - let commission_rate = decimal256::from_string(&string::utf8(b"0.03")); - update_operator_commission(operator, bridge_id, commission_rate); - fund_reward_script(agent, 4, release_time, release_time); - fund_reward_script(agent, 5, release_time, release_time); - - submit_snapshot( - agent, - bridge_id, - 1, - *simple_map::borrow(&merkle_root_map, &1), - *simple_map::borrow(&total_score_map, &1), - ); - submit_snapshot( - agent, - bridge_id, - 2, - *simple_map::borrow(&merkle_root_map, &2), - *simple_map::borrow(&total_score_map, &2), - ); - submit_snapshot( - agent, - bridge_id, - 3, - *simple_map::borrow(&merkle_root_map, &3), - *simple_map::borrow(&total_score_map, &3), - ); - submit_snapshot( - agent, - bridge_id, - 4, - *simple_map::borrow(&merkle_root_map, &4), - *simple_map::borrow(&total_score_map, &4), - ); - submit_snapshot( - agent, - bridge_id, - 5, - *simple_map::borrow(&merkle_root_map, &5), - *simple_map::borrow(&total_score_map, &5), - ); - - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - claim_user_reward_script( - receiver, - bridge_id, - 1, - *simple_map::borrow(&merkle_proof_map, &1), - *simple_map::borrow(&score_map, &1), - ); - assert!( - vip_vesting::get_user_locked_reward( - signer::address_of(receiver), - bridge_id, - 1, - ) == reward_per_stage, - 0, - ); - assert!( - vip_vesting::get_user_unlocked_reward( - signer::address_of(receiver), - bridge_id, - 1, - *simple_map::borrow(&score_map, &1), - ) == 0, - 0, - ); - - claim_user_reward_script( - receiver, - bridge_id, - 2, - *simple_map::borrow(&merkle_proof_map, &2), - *simple_map::borrow(&score_map, &2), - ); - assert!( - vip_vesting::get_user_unlocked_reward( - signer::address_of(receiver), - bridge_id, - 2, - *simple_map::borrow(&score_map, &2), - ) == (reward_per_stage_by_vesting), - 0, - ); - - claim_user_reward_script( - receiver, - bridge_id, - 3, - *simple_map::borrow(&merkle_proof_map, &3), - *simple_map::borrow(&score_map, &3), - ); - assert!( - vip_vesting::get_user_unlocked_reward( - signer::address_of(receiver), - bridge_id, - 3, - *simple_map::borrow(&score_map, &3), - ) == (reward_per_stage_by_vesting + (reward_per_stage_by_vesting / 2)), - 0, - ); - - claim_user_reward_script( - receiver, - bridge_id, - 4, - *simple_map::borrow(&merkle_proof_map, &4), - *simple_map::borrow(&score_map, &4), - ); - claim_operator_reward_script(operator, bridge_id, 4); - assert!( - vip_vesting::get_user_unlocked_reward( - signer::address_of(receiver), - bridge_id, - 4, - *simple_map::borrow(&score_map, &4), - ) == ( - reward_per_stage_by_vesting + (reward_per_stage_by_vesting / 2) - + reward_per_stage_by_vesting - ), - 0, - ); - assert!( - vip_vesting::get_user_vesting_initial_reward( - signer::address_of(receiver), - bridge_id, - 4, - ) == ( - reward_per_stage - decimal256::mul_u64(&commission_rate, reward_per_stage) - ), - 0, - ); - assert!( - vip_vesting::get_operator_unlocked_reward( - signer::address_of(operator), - bridge_id, - 4, - ) == 0, - 0, - ); - assert!( - vip_vesting::get_operator_vesting_initial_reward( - signer::address_of(operator), - bridge_id, - 4, - ) == (decimal256::mul_u64( - &commission_rate, - total_reward_per_stage, - )), - 0, - ); - - claim_user_reward_script( - receiver, - bridge_id, - 5, - *simple_map::borrow(&merkle_proof_map, &5), - *simple_map::borrow(&score_map, &5), - ); - claim_operator_reward_script(operator, bridge_id, 5); - assert!( - vip_vesting::get_user_unlocked_reward( - signer::address_of(receiver), - bridge_id, - 5, - *simple_map::borrow(&score_map, &5), - ) == ( - reward_per_stage_by_vesting + (reward_per_stage_by_vesting / 2) - + reward_per_stage_by_vesting - + decimal256::mul_u64( - &decimal256::from_string(&string::utf8(b"0.97")), - reward_per_stage_by_vesting, - ) - ), - 0, - ); - assert!( - vip_vesting::get_operator_unlocked_reward( - signer::address_of(operator), - bridge_id, - 5, - ) == ( - decimal256::mul_u64( - &commission_rate, - total_reward_per_stage / operator_vesting_period, - ) - ), - 0, - ); - - let user_claimed_stages = - vip_vesting::get_user_claimed_stages( - signer::address_of(receiver), bridge_id - ); - let operator_claimed_stages = - vip_vesting::get_operator_claimed_stages( - signer::address_of(operator), bridge_id - ); - - assert!( - user_claimed_stages == vector[1, 2, 3, 4, 5], - 0, - ); - assert!(operator_claimed_stages == vector[4, 5], 0); - } - - #[test(chain = @0x1, operator = @0x111)] - fun test_update_challenge_period(chain: &signer) acquires ModuleStore { - init_module_for_test(); - update_challenge_period(chain, DEFAULT_NEW_CHALLENGE_PERIOD); - assert!( - get_module_store().challenge_period == DEFAULT_NEW_CHALLENGE_PERIOD, - 0, - ) - - } - - #[test(chain = @0x1, operator = @0x111)] - fun test_update_snapshot(chain: &signer, operator: &signer) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x1111, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 10000000000000000, - ); - let release_time = 1000; - fund_reward_script(chain, 1, release_time, release_time); - submit_snapshot( - chain, - bridge_id, - 1, - x"8888888888888888888888888888888888888888888888888888888888888888", - 0, - ); - let snapshot = get_snapshot(bridge_id, 1); - assert!( - snapshot.merkle_root - == x"8888888888888888888888888888888888888888888888888888888888888888", - 0, - ); - assert!(snapshot.total_l2_score == 0, 0); - - update_snapshot( - chain, - bridge_id, - 1, - x"7777777777777777777777777777777777777777777777777777777777777777", - 100, - ); - let snapshot = get_snapshot(bridge_id, 1); - assert!( - snapshot.merkle_root - == x"7777777777777777777777777777777777777777777777777777777777777777", - 100, - ); - assert!(snapshot.total_l2_score == 100, 0); - } - - #[test(chain = @0x1, operator = @0x111)] - #[expected_failure(abort_code = 0xD0014, location = Self)] - fun failed_update_snapshot(chain: &signer, operator: &signer) acquires ModuleStore { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x1111, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 10000000000000000, - ); - let release_time = 0; - fund_reward_script(chain, 1, release_time, release_time); - submit_snapshot( - chain, - bridge_id, - 1, - x"8888888888888888888888888888888888888888888888888888888888888888", - 0, - ); - update_snapshot( - chain, - bridge_id, - 1, - x"7777777777777777777777777777777777777777777777777777777777777777", - 100, - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573)] - #[expected_failure(abort_code = 0x10015, location = Self)] - fun failed_update_vip_weights(chain: &signer, operator: &signer) acquires ModuleStore { - let init_stage = 1; - primary_fungible_store::init_module_for_test(); - let (burn_cap, freeze_cap, mint_cap, _) = - initialize_coin(chain, string::utf8(b"uinit")); - init_module_for_test(); - - move_to( - chain, - TestCapability { burn_cap, freeze_cap, mint_cap, }, - ); - - let operator_addr = signer::address_of(operator); - let (bridge_id1, bridge_id2) = (1, 2); - let (bridge_address1, bridge_address2) = (@0x999, @0x1000); - - register( - chain, - operator_addr, - bridge_id1, - bridge_address1, - init_stage, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_RATE_FOR_TEST) - ), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_CHANGE_RATE_FOR_TEST) - ), - decimal256::from_string(&string::utf8(DEFAULT_COMMISSION_RATE_FOR_TEST)), - ); - - // need other L2 to increase stage - register( - chain, - operator_addr, - bridge_id2, - bridge_address2, - init_stage, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_RATE_FOR_TEST) - ), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_CHANGE_RATE_FOR_TEST) - ), - decimal256::from_string(&string::utf8(DEFAULT_COMMISSION_RATE_FOR_TEST)), - ); - - update_vip_weights( - chain, - vector[1, 2], - vector[ - decimal256::from_string(&string::utf8(b"0.5")), - decimal256::from_string(&string::utf8(b"0.7"))], - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573)] - #[expected_failure(abort_code = 0x10015, location = Self)] - fun failed_update_vip_weight(chain: &signer, operator: &signer) acquires ModuleStore { - let init_stage = 1; - primary_fungible_store::init_module_for_test(); - let (burn_cap, freeze_cap, mint_cap, _) = - initialize_coin(chain, string::utf8(b"uinit")); - init_module_for_test(); - - move_to( - chain, - TestCapability { burn_cap, freeze_cap, mint_cap, }, - ); - - let operator_addr = signer::address_of(operator); - let (bridge_id1, bridge_id2) = (1, 2); - let (bridge_address1, bridge_address2) = (@0x999, @0x1000); - - register( - chain, - operator_addr, - bridge_id1, - bridge_address1, - init_stage, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_RATE_FOR_TEST) - ), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_CHANGE_RATE_FOR_TEST) - ), - decimal256::from_string(&string::utf8(DEFAULT_COMMISSION_RATE_FOR_TEST)), - ); - - // need other L2 to increase stage - register( - chain, - operator_addr, - bridge_id2, - bridge_address2, - init_stage, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_RATE_FOR_TEST) - ), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_CHANGE_RATE_FOR_TEST) - ), - decimal256::from_string(&string::utf8(DEFAULT_COMMISSION_RATE_FOR_TEST)), - ); - - update_vip_weights( - chain, - vector[1, 2], - vector[ - decimal256::from_string(&string::utf8(b"0.5")), - decimal256::from_string(&string::utf8(b"0.4"))], - ); - update_vip_weight( - chain, - 1, - decimal256::from_string(&string::utf8(b"0.7")), - ); - } - - #[test(chain = @0x1, operator = @0x111, operator2 = @0x222)] - fun test_get_next_stage( - chain: &signer, operator: &signer, operator2: &signer - ) acquires ModuleStore, TestCapability { - let bridge_id = - test_setup( - chain, - operator, - BRIDGE_ID_FOR_TEST, - @0x1111, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 10000000000000000, - ); - let release_time = 0; - assert!(get_module_store().stage == 1, 1); - assert!(get_next_stage(bridge_id) == 1, 2); - - // increase stage - fund_reward_script(chain, 1, release_time, release_time); - submit_snapshot( - chain, - bridge_id, - 1, - x"8888888888888888888888888888888888888888888888888888888888888888", - 0, - ); - - assert!(get_next_stage(bridge_id) == 2, 2); - assert!(get_module_store().stage == 2, 3); - - // increase stage - fund_reward_script(chain, 2, release_time, release_time); - submit_snapshot( - chain, - bridge_id, - 2, - x"8888888888888888888888888888888888888888888888888888888888888888", - 0, - ); - - let cap = borrow_global(signer::address_of(chain)); - let bridge_id2 = 2; - - // new bridge registered - test_register_bridge( - chain, - operator2, - bridge_id2, - @0x1000, - 3, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - 10000000000000000, - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_RATE_FOR_TEST) - ), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_CHANGE_RATE_FOR_TEST) - ), - decimal256::from_string(&string::utf8(DEFAULT_COMMISSION_RATE_FOR_TEST)), - &cap.mint_cap, - ); - assert!(get_next_stage(bridge_id2) == 3, 4); - - // increase stage - fund_reward_script(chain, 3, release_time, release_time); - submit_snapshot( - chain, - bridge_id, - 3, - x"8888888888888888888888888888888888888888888888888888888888888888", - 0, - ); - submit_snapshot( - chain, - bridge_id2, - 3, - x"8888888888888888888888888888888888888888888888888888888888888888", - 0, - ); - assert!(get_next_stage(bridge_id) == 4, 5); - assert!(get_next_stage(bridge_id2) == 4, 6); - } - - #[test_only] - public fun test_setup_for_zapping( - chain: &signer, - operator: &signer, - account: &signer, - bridge_id: u64, - bridge_address: address, - mint_amount: u64, - ): (u64, Object, Object, Object, string::String) acquires ModuleStore { - let init_stage = 1; - dex::init_module_for_test(); - staking::init_module_for_test(); - primary_fungible_store::init_module_for_test(); - vip_zapping::init_module_for_test(); - vip_tvl_manager::init_module_for_test(); - init_module_for_test(); - - let (_burn_cap, _freeze_cap, mint_cap, _) = - initialize_coin(chain, string::utf8(b"uinit")); - - let reward_metadata = vip_reward::reward_metadata(); - coin::mint_to( - &mint_cap, - bridge_address, - mint_amount, - ); - coin::mint_to( - &mint_cap, - signer::address_of(operator), - mint_amount, - ); - coin::mint_to( - &mint_cap, - signer::address_of(account), - mint_amount, - ); - coin::mint_to( - &mint_cap, - signer::address_of(chain), - mint_amount, - ); - vip_vault::deposit(chain, mint_amount); - - coin::mint_to( - &mint_cap, - signer::address_of(chain), - mint_amount, - ); // for pair creation - coin::mint_to( - &mint_cap, - signer::address_of(chain), - mint_amount, - ); // for staking reward - - let validator = string::utf8(b"val"); - - register( - chain, - signer::address_of(operator), - bridge_id, - bridge_address, - init_stage, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_RATE_FOR_TEST) - ), - decimal256::from_string( - &string::utf8(DEFAULT_COMMISSION_MAX_CHANGE_RATE_FOR_TEST) - ), - decimal256::from_string(&string::utf8(DEFAULT_COMMISSION_RATE_FOR_TEST)), - ); - - let (_burn_cap, _freeze_cap, mint_cap, stakelisted_metadata) = - initialize_coin(chain, string::utf8(b"USDC")); - coin::mint_to( - &mint_cap, - signer::address_of(chain), - mint_amount, - ); - coin::mint_to( - &mint_cap, - signer::address_of(account), - mint_amount, - ); - - dex::create_pair_script( - chain, - string::utf8(b"pair"), - string::utf8(b"INIT-USDC"), - decimal128::from_ratio(3, 1000), - decimal128::from_ratio(5, 10), - decimal128::from_ratio(5, 10), - reward_metadata, - stakelisted_metadata, - mint_amount, - mint_amount, - ); - - let lp_metadata = - coin::metadata( - signer::address_of(chain), - string::utf8(b"INIT-USDC"), - ); - staking::initialize_for_chain(chain, lp_metadata); - staking::set_staking_share_ratio( - *string::bytes(&validator), - &lp_metadata, - 1, - 1, - ); - - (bridge_id, reward_metadata, stakelisted_metadata, lp_metadata, validator) - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37, relayer = @0x3d18d54532fc42e567090852db6eb21fa528f952)] - fun test_zapping( - chain: &signer, - operator: &signer, - receiver: &signer, - relayer: &signer, - ) acquires ModuleStore { - let mint_amount = 10_000_000_000_000; - let (bridge_id, reward_metadata, stakelisted_metadata, lp_metadata, validator) = - test_setup_for_zapping( - chain, - operator, - receiver, - 1, - @0x99, - mint_amount, - ); - - let (_, merkle_proof_map, score_map, _) = merkle_root_and_proof_scene1(); - test_setup_scene1(chain, bridge_id, 0); - - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - claim_user_reward_script( - receiver, - bridge_id, - 1, - *simple_map::borrow(&merkle_proof_map, &1), - *simple_map::borrow(&score_map, &1), - ); - - let stage = 1; - let start_time = 100; - let lock_period = 60 * 60 * 24; // 1 day - let release_time = start_time + lock_period; - let val = string::utf8(b"val"); - - block::set_block_info(1, start_time); - vip_zapping::update_lock_period_script(chain, lock_period); - let zapping_amount = - vip_vesting::get_user_locked_reward( - signer::address_of(receiver), - bridge_id, - stage, - ); - - // zap vesting in stage 1 - zapping_script( - receiver, - bridge_id, - lp_metadata, - option::none(), - validator, - stage, - zapping_amount, - zapping_amount, - stakelisted_metadata, - ); - - block::set_block_info(2, release_time + 1); - - // distribute staking reward - let staking_reward_amount = 100_000_000; - staking::fund_reward_coin( - chain, - signer::address_of(relayer), - staking_reward_amount, - ); - staking::deposit_reward_for_chain( - chain, - lp_metadata, - vector[val], - vector[staking_reward_amount], - ); - - let before_balance = - primary_fungible_store::balance( - signer::address_of(receiver), - reward_metadata, - ); - vip_zapping::claim_reward_script(receiver, 0); - let after_balance = - primary_fungible_store::balance( - signer::address_of(receiver), - reward_metadata, - ); - - assert!( - after_balance - before_balance == staking_reward_amount, - 0, - ); - vip_zapping::claim_zapping_script(receiver, 0); - staking::get_delegation( - signer::address_of(receiver), - lp_metadata, - validator, - ); - } - - #[test(chain = @0x1, operator = @0x56ccf33c45b99546cd1da172cf6849395bbf8573, receiver = @0x19c9b6007d21a996737ea527f46b160b0a057c37)] - fun test_full_vesting_zapping( - chain: &signer, - operator: &signer, - receiver: &signer, - ) acquires ModuleStore { - let vesting_period = 10; - let (bridge_id, _reward_metadata, stakelisted_metadata, lp_metadata, validator) = - test_setup_for_zapping( - chain, - operator, - receiver, - 1, - @0x99, - 1_000_000_000_000, - ); - let idx = 1; - let zapping_amount = 100_000_000; - let release_time = 0; - - let batch_lp_metadata = vector::empty>(); - let batch_min_liquidity = vector::empty>(); - let batch_validator = vector::empty(); - let batch_stage = vector::empty(); - let batch_zapping_amount = vector::empty(); - let batch_stakelisted_amount = vector::empty(); - let batch_stakelisted_metadata = vector::empty>(); - let (merkle_root_map, merkle_proof_map, score_map, total_score_map) = - merkle_root_and_proof_scene1(); - - while (idx <= vesting_period) { - fund_reward_script( - chain, - idx, - release_time, - release_time, - ); - submit_snapshot( - chain, - bridge_id, - idx, - *simple_map::borrow(&merkle_root_map, &idx), - *simple_map::borrow(&total_score_map, &idx), - ); - - skip_period(DEFAULT_SKIPPED_CHALLENGE_PERIOD_FOR_TEST); - - claim_user_reward_script( - receiver, - bridge_id, - idx, - *simple_map::borrow(&merkle_proof_map, &idx), - *simple_map::borrow(&score_map, &idx), - ); - - vector::push_back(&mut batch_lp_metadata, lp_metadata); - vector::push_back( - &mut batch_min_liquidity, - option::none(), - ); - vector::push_back(&mut batch_validator, validator); - vector::push_back(&mut batch_stage, idx); - vector::push_back( - &mut batch_zapping_amount, - zapping_amount, - ); - vector::push_back( - &mut batch_stakelisted_amount, - zapping_amount, - ); - vector::push_back( - &mut batch_stakelisted_metadata, - stakelisted_metadata, - ); - - idx = idx + 1; - }; - - batch_zapping_script( - receiver, - bridge_id, - batch_lp_metadata, - batch_min_liquidity, - batch_validator, - batch_stage, - batch_zapping_amount, - batch_stakelisted_amount, - batch_stakelisted_metadata, - ); - } -} diff --git a/initia_stdlib/sources/vip/weight_vote.move b/initia_stdlib/sources/vip/weight_vote.move deleted file mode 100644 index 5f9c532..0000000 --- a/initia_stdlib/sources/vip/weight_vote.move +++ /dev/null @@ -1,1672 +0,0 @@ -module initia_std::vip_weight_vote { - use std::bcs; - use std::error; - use std::signer; - use std::hash::sha3_256; - use std::vector; - use std::string::String; - use std::option::{Self, Option}; - - use initia_std::block::get_block_info; - use initia_std::cosmos; - use initia_std::decimal128::{Self, Decimal128}; - use initia_std::decimal256::{Self, Decimal256}; - use initia_std::event; - use initia_std::primary_fungible_store; - use initia_std::object::{Self}; - use initia_std::table::{Self, Table}; - use initia_std::table_key; - - use initia_std::vip; - use initia_std::vip_reward; - - // - // Errors - // - - const EMODULE_STORE_ALREADY_EXISTS: u64 = 1; - const EINVALID_MERKLE_PROOFS: u64 = 2; - const EINVALID_PROOF_LENGTH: u64 = 3; - const ESTAGE_NOT_FOUND: u64 = 4; - const EVECTOR_LENGTH: u64 = 5; - const EVOTING_END: u64 = 6; - const ESTAGE_NOT_END: u64 = 7; - const EUNAUTHORIZED: u64 = 8; - const ECANNOT_CREATE_CHALLENGE_PROPOSAL: u64 = 9; - const EVOTE_NOT_FOUND: u64 = 10; - const EPROPOSAL_IN_PROGRESS: u64 = 11; - const EPROPOSAL_ALREADY_EXECUTED: u64 = 12; - const EBRIDGE_NOT_FOUND: u64 = 13; - const ECHALLENGE_NOT_FOUND: u64 = 14; - const ECHALLENGE_IN_PROGRESS: u64 = 15; - const ECHALLENGE_ALREADY_EXECUTED: u64 = 16; - const EINVALID_PARAMETER: u64 = 17; - - // - // Constants - // - - const PROOF_LENGTH: u64 = 32; - - const VOTE_YES: u64 = 1; - const VOTE_NO: u64 = 0; - - struct ModuleStore has key { - // current epoch - current_epoch: u64, - // current epoch start timestamp - epoch_start_timestamp: u64, - // current epoch start timestamp - epoch_end_timestamp: u64, - // change bridge weights proposals - proposals: Table /* epoch */, Proposal>, - // challenges - challenges: Table /* challenge_id */, Challenge>, - // init store for challenge deposit - challenge_deposit_store: object::ExtendRef, - - // params - - // epoch interval - epoch_interval: u64, - // grace time for voting power snapshot - // - // If submitter do not submit merkle root after grace period, - // anyone can do challenge. - snapshot_grace_period: u64, - // voting period - voting_period: u64, - // merkle root submitter - submitter: address, - // minimum voting period for challenge - min_voting_period: u64, - // quorum = quorum_ratio * total_tally - quorum_ratio: Decimal128, - // uinit deposit amount to create challenge - // - // If total tally doesn't reach quorum, transfer deposit to community pool. - challenge_deposit_amount: u64 - } - - struct Proposal has store { - merkle_root: vector, - votes: Table, - total_tally: u64, - tally: Table /* bridge id */, u64 /* tally */>, - snapshot_height: u64, - voting_end_time: u64, - api_uri: String, // api uri to serve merkle proofs - executed: bool, - } - - struct WeightVote has store { - voting_power: u64, - weights: vector - } - - struct Weight has copy, drop, store { - bridge_id: u64, - weight: Decimal128, - } - - struct Vote has store { - vote_option: bool, - voting_power: u64, - } - - struct Challenge has store { - title: String, - summary: String, - api_uri: String, - epoch: u64, - challenger: address, - voting_power_epoch: u64, - new_submitter: address, - merkle_root: vector, - snapshot_height: u64, - votes: Table, - yes_tally: u64, - no_tally: u64, - quorum: u64, - voting_end_time: u64, - min_voting_end_time: u64, - deposit_amount: u64, - is_executed: bool, - } - - struct DroppedProposal has key { - proposal: Proposal - } - - // - // responses - // - - struct ModuleResponse has drop { - current_epoch: u64, - epoch_start_timestamp: u64, - epoch_end_timestamp: u64, - epoch_interval: u64, - snapshot_grace_period: u64, - voting_period: u64, - submitter: address, - min_voting_period: u64, - quorum_ratio: Decimal128, - challenge_deposit_amount: u64, - } - - struct ChallengeResponse has drop { - title: String, - summary: String, - api_uri: String, - epoch: u64, - challenger: address, - voting_power_epoch: u64, - new_submitter: address, - merkle_root: vector, - snapshot_height: u64, - yes_tally: u64, - no_tally: u64, - quorum: u64, - voting_end_time: u64, - min_voting_end_time: u64, - deposit_amount: u64, - is_executed: bool, - } - - struct ProposalResponse has drop { - merkle_root: vector, - total_tally: u64, - snapshot_height: u64, - voting_end_time: u64, - api_uri: String, - executed: bool, - } - - struct WeightVoteResponse has drop { - voting_power: u64, - weights: vector, - } - - // events - - #[event] - struct SubmitMerkleRootEvent has drop, store { - epoch: u64, - merkle_root: vector, - api_uri: String, - snapshot_height: u64, - voting_end_time: u64, - } - - #[event] - struct VoteEvent has drop, store { - account: address, - epoch: u64, - voting_power: u64, - weights: vector, - } - - #[event] - struct ExecuteEvent has drop, store { - epoch: u64, - bridge_ids: vector, - weights: vector, - } - - #[event] - struct CreateChallengeEvent has drop, store { - challenger: address, - challenge_id: u64, - title: String, - summary: String, - new_submitter: address, - merkle_root: vector, - api_uri: String, - snapshot_height: u64, - } - - #[event] - struct VoteChallengeEvent has drop, store { - account: address, - challenge_id: u64, - voting_power: u64, - vote_option: bool, - } - - #[event] - struct ExecuteChallengeEvent has drop, store { - challenge_id: u64, - success: bool, - } - - // initialize function - - public entry fun initialize( - chain: &signer, - epoch_start_timestamp: u64, - epoch_interval: u64, - snapshot_grace_period: u64, - voting_period: u64, - submitter: address, - min_voting_period: u64, - quorum_ratio: Decimal128, - challenge_deposit_amount: u64, - ) { - assert!( - signer::address_of(chain) == @initia_std, - error::permission_denied(EUNAUTHORIZED), - ); - assert!( - !exists(@initia_std), - error::already_exists(EMODULE_STORE_ALREADY_EXISTS), - ); - - let object = object::create_named_object(chain, b"vip_proposal"); - let extend_ref = object::generate_extend_ref(&object); - - move_to( - chain, - ModuleStore { - current_epoch: 0, - epoch_start_timestamp, - epoch_end_timestamp: epoch_start_timestamp, - proposals: table::new(), - challenges: table::new(), - challenge_deposit_store: extend_ref, - epoch_interval, - snapshot_grace_period, - voting_period, - submitter, - min_voting_period, - quorum_ratio, - challenge_deposit_amount, - }, - ) - } - - public entry fun update_params( - chain: &signer, - epoch_interval: Option, - snapshot_grace_period: Option, - voting_period: Option, - submitter: Option
, - min_voting_period: Option, - quorum_ratio: Option, - proposal_deposit_amount: Option, - ) acquires ModuleStore { - assert!( - signer::address_of(chain) == @initia_std, - error::permission_denied(EUNAUTHORIZED), - ); - let module_store = borrow_global_mut(@initia_std); - - if (option::is_some(&epoch_interval)) { - module_store.epoch_interval = option::extract(&mut epoch_interval); - }; - - if (option::is_some(&snapshot_grace_period)) { - module_store.snapshot_grace_period = option::extract( - &mut snapshot_grace_period - ); - }; - - if (option::is_some(&voting_period)) { - module_store.voting_period = option::extract(&mut voting_period); - }; - - if (option::is_some(&submitter)) { - module_store.submitter = option::extract(&mut submitter); - }; - - if (option::is_some(&min_voting_period)) { - module_store.min_voting_period = option::extract(&mut min_voting_period); - }; - - if (option::is_some(&quorum_ratio)) { - module_store.quorum_ratio = option::extract(&mut quorum_ratio); - }; - - if (option::is_some(&proposal_deposit_amount)) { - module_store.challenge_deposit_amount = option::extract( - &mut proposal_deposit_amount - ); - }; - - // voting period must be less than epoch interval - assert!( - module_store.voting_period < module_store.epoch_interval, - error::invalid_argument(EINVALID_PARAMETER), - ); - } - - // - // entry functions - // - - // weight vote - - public entry fun submit_snapshot( - submitter: &signer, - merkle_root: vector, - api_uri: String, - snapshot_height: u64, - ) acquires ModuleStore { - let module_store = borrow_global_mut(@initia_std); - let (_, timestamp) = get_block_info(); - - assert!( - signer::address_of(submitter) == module_store.submitter, - error::permission_denied(EUNAUTHORIZED), - ); - assert!( - module_store.epoch_end_timestamp < timestamp, - error::invalid_state(ESTAGE_NOT_END), - ); - - let voting_end_time = calculate_voting_end_time(timestamp, module_store); - submit_snapshot_internal( - module_store, - merkle_root, - api_uri, - snapshot_height, - voting_end_time, - ); - } - - public entry fun vote( - account: &signer, - epoch: u64, - merkle_proofs: vector>, - max_voting_power: u64, - bridge_ids: vector, - weights: vector, - ) acquires ModuleStore { - let addr = signer::address_of(account); - let module_store = borrow_global_mut(@initia_std); - let (_, timestamp) = get_block_info(); - - let weight_sum = decimal128::new(0); - vector::for_each_ref( - &weights, - |weight| { - weight_sum = decimal128::add(&weight_sum, weight); - }, - ); - assert!( - decimal128::val(&weight_sum) <= decimal128::val(&decimal128::one()), - error::invalid_argument(EINVALID_PARAMETER), - ); - let voting_power_used = decimal128::mul_u64(&weight_sum, max_voting_power); - // check vote condition - let epoch_key = table_key::encode_u64(epoch); - assert!( - table::contains(&module_store.proposals, epoch_key), - error::not_found(ESTAGE_NOT_FOUND), - ); - let proposal = table::borrow_mut(&mut module_store.proposals, epoch_key); - assert!( - timestamp < proposal.voting_end_time, - error::invalid_state(EVOTING_END), - ); - - // remove former vote - if (table::contains(&proposal.votes, addr)) { - let WeightVote { voting_power, weights } = - table::remove(&mut proposal.votes, addr); - apply_vote(proposal, voting_power, weights, true); - }; - - // verify merkle proof - let target_hash = voting_power_hash(epoch, addr, max_voting_power); - assert_merkle_proofs( - merkle_proofs, - proposal.merkle_root, - target_hash, - ); - - // normalize weights to 1 - let n_weights: vector = normalize_weights(bridge_ids, weights); - - // apply vote - apply_vote( - proposal, - voting_power_used, - n_weights, - false, - ); - - // store user votes - table::add( - &mut proposal.votes, - addr, - WeightVote { voting_power: voting_power_used, weights: n_weights }, - ); - - // emit event - event::emit( - VoteEvent { - account: addr, - epoch, - voting_power: voting_power_used, - weights: n_weights, - }, - ) - } - - public entry fun execute_proposal() acquires ModuleStore { - let module_store = borrow_global_mut(@initia_std); - let (_, timestamp) = get_block_info(); - - // check vote state - let proposal = - table::borrow_mut( - &mut module_store.proposals, - table_key::encode_u64(module_store.current_epoch), - ); - assert!( - proposal.voting_end_time < timestamp, - error::invalid_state(EPROPOSAL_IN_PROGRESS), - ); - assert!( - !proposal.executed, - error::invalid_state(EPROPOSAL_ALREADY_EXECUTED), - ); - - // update vip weights - let bridge_ids = vip::get_whitelisted_bridge_ids(); - - let index = 0; - let len = vector::length(&bridge_ids); - let weights: vector = vector[]; - while (index < len) { - let bridge_id = *vector::borrow(&bridge_ids, index); - let tally = - table::borrow_with_default( - &proposal.tally, - table_key::encode_u64(bridge_id), - &0, - ); - let weight = - decimal256::from_ratio( - (*tally as u256), - (proposal.total_tally as u256), - ); - vector::push_back(&mut weights, weight); - index = index + 1; - }; - - vip::update_vip_weights_for_friend(bridge_ids, weights); - - // emit event - event::emit( - ExecuteEvent { epoch: module_store.current_epoch, bridge_ids, weights, }, - ); - - // update proposal state - proposal.executed = true; - } - - // challenge - - public entry fun create_challenge( - account: &signer, - title: String, - summary: String, - merkle_root: vector, - api_uri: String, - snapshot_height: u64, - ) acquires ModuleStore { - let (_, timestamp) = get_block_info(); - let challenger = signer::address_of(account); - let module_store = borrow_global_mut(@initia_std); - let (epoch, proposal) = last_finalized_proposal(module_store, timestamp); - - // transfer deposit - primary_fungible_store::transfer( - account, - vip_reward::reward_metadata(), - object::address_from_extend_ref(&module_store.challenge_deposit_store), - module_store.challenge_deposit_amount, - ); - - // set challenge configs - let voting_power_epoch = epoch; - let voting_end_time = timestamp + module_store.voting_period; - let min_voting_end_time = timestamp + module_store.min_voting_period; - let quorum = - decimal128::mul_u64( - &module_store.quorum_ratio, - proposal.total_tally, - ); - - // check challenge condition - let current_proposal = - table::borrow( - &module_store.proposals, - table_key::encode_u64(module_store.current_epoch), - ); - let epoch_to_challenge = - if (current_proposal.voting_end_time > timestamp) { - // challenge can be created when voting is in progress - module_store.current_epoch - } else if (module_store.epoch_end_timestamp - + module_store.snapshot_grace_period < timestamp) { - // or when grace period is over - module_store.current_epoch + 1 - } else { - abort error::invalid_state(ECANNOT_CREATE_CHALLENGE_PROPOSAL) - }; - - let challenge = Challenge { - challenger, - voting_power_epoch, - title, - summary, - epoch: epoch_to_challenge, - new_submitter: challenger, - merkle_root, - api_uri, - snapshot_height, - votes: table::new(), - yes_tally: 0, - no_tally: 0, - quorum, - voting_end_time, - min_voting_end_time, - deposit_amount: module_store.challenge_deposit_amount, - is_executed: false, - }; - - // get next challenge id - let challenge_id = next_challenge_id(module_store); - - // add challenge - table::add( - &mut module_store.challenges, - table_key::encode_u64(challenge_id), - challenge, - ); - - // emit event - event::emit( - CreateChallengeEvent { - challenger, - challenge_id, - title, - summary, - new_submitter: challenger, - merkle_root, - api_uri, - snapshot_height, - }, - ) - } - - public entry fun vote_challenge( - account: &signer, - challenge_id: u64, - vote_option: bool, - ) acquires ModuleStore { - let (_, timestamp) = get_block_info(); - let addr = signer::address_of(account); - - // check challenge state - let module_store = borrow_global_mut(@initia_std); - let challenge_key = table_key::encode_u64(challenge_id); - assert!( - table::contains( - &module_store.challenges, - challenge_key, - ), - error::not_found(ECHALLENGE_NOT_FOUND), - ); - let challenge = table::borrow_mut(&mut module_store.challenges, challenge_key); - assert!( - timestamp < challenge.voting_end_time, - error::invalid_state(EVOTING_END), - ); - - // retreive user voting power from the proposal of the voting power epoch - let vp_epoch_key = table_key::encode_u64(challenge.voting_power_epoch); - let proposal = table::borrow_mut(&mut module_store.proposals, vp_epoch_key); - assert!( - table::contains(&proposal.votes, addr), - error::not_found(EVOTE_NOT_FOUND), - ); - let vote = table::borrow(&proposal.votes, addr); - - // if user already voted, remove former vote - if (table::contains(&challenge.votes, addr)) { - let Vote { voting_power, vote_option } = - table::remove(&mut challenge.votes, addr); - apply_challenge_vote( - challenge, - vote_option, - voting_power, - true, - ); - }; - - // adjust vote - let voting_power = vote.voting_power; - table::add( - &mut challenge.votes, - addr, - Vote { voting_power, vote_option, }, - ); - - apply_challenge_vote( - challenge, - vote_option, - voting_power, - false, - ); - - // emit event - event::emit( - VoteChallengeEvent { account: addr, challenge_id, voting_power, vote_option, }, - ) - } - - public entry fun execute_challenge(challenge_id: u64,) acquires ModuleStore { - // execute challenge and get result - let success = execute_challenge_internal(challenge_id); - - // emit event - event::emit(ExecuteChallengeEvent { challenge_id, success }) - } - - // helper functions - - fun next_challenge_id(module_store: &ModuleStore): u64 { - let iter = table::iter( - &module_store.challenges, - option::none(), - option::none(), - 2, - ); - if (!table::prepare, Challenge>(iter)) { 1 } - else { - let (challenge_id, _) = table::next, Challenge>(iter); - table_key::decode_u64(challenge_id) + 1 - } - } - - fun last_finalized_proposal( - module_store: &ModuleStore, timestamp: u64 - ): (u64, &Proposal) { - let iter = table::iter( - &module_store.proposals, - option::none(), - option::none(), - 2, - ); - assert!( - table::prepare, Proposal>(iter), - error::not_found(ESTAGE_NOT_FOUND), - ); - let (epoch_key, proposal) = table::next, Proposal>(iter); - - // if last proposal is in progress, use former proposal - if (proposal.voting_end_time > timestamp) { - assert!( - table::prepare, Proposal>(iter), - error::not_found(ESTAGE_NOT_FOUND), - ); - (epoch_key, proposal) = table::next, Proposal>(iter); - }; - - (table_key::decode_u64(epoch_key), proposal) - } - - fun execute_challenge_internal(challenge_id: u64): bool acquires ModuleStore { - let (_, timestamp) = get_block_info(); - let module_store = borrow_global_mut(@initia_std); - - // get challenge - let challenge_key = table_key::encode_u64(challenge_id); - assert!( - table::contains( - &module_store.challenges, - challenge_key, - ), - error::not_found(ECHALLENGE_NOT_FOUND), - ); - - let challenge = table::borrow_mut(&mut module_store.challenges, challenge_key); - let yes_count = challenge.yes_tally; - let no_count = challenge.no_tally; - let total_tally = yes_count + no_count; - - // check challenge execute condition - assert!( - !challenge.is_executed, - error::invalid_state(ECHALLENGE_ALREADY_EXECUTED), - ); - assert!( - challenge.voting_end_time < timestamp - || ( - challenge.quorum <= total_tally - && challenge.min_voting_end_time <= timestamp - ), - error::invalid_state(ECHALLENGE_IN_PROGRESS), - ); - - // condition passed, so flag challenge as executed - challenge.is_executed = true; - - let object_signer = - object::generate_signer_for_extending( - &module_store.challenge_deposit_store - ); - - // if total tally doesn't reach quorum, transfer deposit to community pool and return false - if (total_tally < challenge.quorum) { - cosmos::fund_community_pool( - &object_signer, - vip_reward::reward_metadata(), - challenge.deposit_amount, - ); - return false - }; - - // return deposit to challenger - primary_fungible_store::transfer( - &object_signer, - vip_reward::reward_metadata(), - challenge.challenger, - challenge.deposit_amount, - ); - - if (no_count > yes_count) { - return false - }; - - return apply_challenge( - module_store, - challenge.epoch, - challenge.new_submitter, - challenge.merkle_root, - challenge.api_uri, - challenge.snapshot_height, - ) - } - - fun apply_challenge( - module_store: &mut ModuleStore, - epoch: u64, - new_submitter: address, - merkle_root: vector, - api_uri: String, - snapshot_height: u64, - ): bool { - let (_, timestamp) = get_block_info(); - - let epoch_key = table_key::encode_u64(epoch); - - // remove current epoch proposal if exists - if (table::contains(&module_store.proposals, epoch_key)) { - let former_proposal = table::remove( - &mut module_store.proposals, - epoch_key, - ); - - // check voting is not ended - if (former_proposal.voting_end_time <= timestamp) { - table::add( - &mut module_store.proposals, - epoch_key, - former_proposal, - ); - - return false - }; - - // remove exists epoch - let constructor_ref = object::create_object(@initia_std, true); - let object_signer = object::generate_signer(&constructor_ref); - move_to( - &object_signer, - DroppedProposal { proposal: former_proposal }, - ); - - // revert module store state - module_store.current_epoch = module_store.current_epoch - 1; - }; - - // update submitter and submit merkle root - module_store.submitter = new_submitter; - let voting_end_time = timestamp + module_store.voting_period; - submit_snapshot_internal( - module_store, - merkle_root, - api_uri, - snapshot_height, - voting_end_time, - ); - return true - } - - // weight vote - - fun submit_snapshot_internal( - module_store: &mut ModuleStore, - merkle_root: vector, - api_uri: String, - snapshot_height: u64, - voting_end_time: u64 - ) { - - // update epoch - module_store.current_epoch = module_store.current_epoch + 1; - - // To handle case that submitter doesn't submit merkle root more than one epoch period - // set epoch start time to former epoch end time + skipped epoch count * epoch interval - if (voting_end_time > module_store.epoch_end_timestamp) { - let skipped_epoch_count = - (voting_end_time - module_store.epoch_end_timestamp) - / module_store.epoch_interval; - module_store.epoch_start_timestamp = module_store.epoch_end_timestamp - + skipped_epoch_count * module_store.epoch_interval; - }; - - // set epoch end time - module_store.epoch_end_timestamp = module_store.epoch_start_timestamp - + module_store.epoch_interval; - - // initiate weight vote - table::add( - &mut module_store.proposals, - table_key::encode_u64(module_store.current_epoch), - Proposal { - merkle_root, - votes: table::new(), - total_tally: 0, - tally: table::new(), - api_uri, - snapshot_height, - voting_end_time, - executed: false, - }, - ); - - // emit event - event::emit( - SubmitMerkleRootEvent { - epoch: module_store.current_epoch, - merkle_root, - api_uri, - snapshot_height, - voting_end_time, - }, - ) - } - - fun apply_vote( - proposal: &mut Proposal, - voting_power: u64, - weights: vector, - remove: bool - ) { - let len = vector::length(&weights); - - let i = 0; - let remain = voting_power; - while (i < len) { - let w = vector::borrow(&weights, i); - let bridge_vp = - if (i == len - 1) { remain } - else { - decimal128::mul_u64(&w.weight, voting_power) - }; - - remain = remain - bridge_vp; - let tally = - table::borrow_mut_with_default( - &mut proposal.tally, - table_key::encode_u64(w.bridge_id), - 0, - ); - *tally = if (remove) { - *tally - (bridge_vp as u64) - } else { - *tally + (bridge_vp as u64) - }; - i = i + 1; - }; - - proposal.total_tally = if (remove) { - proposal.total_tally - voting_power - } else { - proposal.total_tally + voting_power - }; - } - - fun apply_challenge_vote( - challenge: &mut Challenge, - vote_option: bool, - voting_power: u64, - remove: bool - ) { - let tally = if (vote_option) { - &mut challenge.yes_tally - } else { - &mut challenge.no_tally - }; - - *tally = if (remove) { - *tally - (voting_power as u64) - } else { - *tally + (voting_power as u64) - }; - } - - fun voting_power_hash( - epoch: u64, - account_addr: address, - voting_power: u64, - ): vector { - let data = vector::empty(); - // add epoch to prevent replay attack - vector::append(&mut data, bcs::to_bytes(&epoch)); - vector::append(&mut data, bcs::to_bytes(&account_addr)); - vector::append(&mut data, bcs::to_bytes(&voting_power)); - sha3_256(data) - } - - fun assert_merkle_proofs( - merkle_proofs: vector>, - merkle_root: vector, - target_hash: vector, - ) { - // must use sorted merkle tree - let i = 0; - let len = vector::length(&merkle_proofs); - let root_seed = target_hash; - - while (i < len) { - let proof = vector::borrow(&merkle_proofs, i); - - let cmp = bytes_cmp(&root_seed, proof); - root_seed = if (cmp == 2 /* less */) { - let tmp = vector::empty(); - vector::append(&mut tmp, root_seed); - vector::append(&mut tmp, *proof); - - sha3_256(tmp) - } else /* greator or equals */ { - let tmp = vector::empty(); - vector::append(&mut tmp, *proof); - vector::append(&mut tmp, root_seed); - - sha3_256(tmp) - }; - - i = i + 1; - }; - let root_hash = root_seed; - assert!( - merkle_root == root_hash, - error::invalid_argument(EINVALID_MERKLE_PROOFS), - ); - } - - // Compare bytes and return a following result number: - // 0: equal - // 1: v1 is greator than v2 - // 2: v1 is less than v2 - fun bytes_cmp(v1: &vector, v2: &vector): u8 { - assert!( - vector::length(v1) == PROOF_LENGTH, - error::invalid_argument(EINVALID_PROOF_LENGTH), - ); - assert!( - vector::length(v2) == PROOF_LENGTH, - error::invalid_argument(EINVALID_PROOF_LENGTH), - ); - - let i = 0; - while (i < PROOF_LENGTH) { - let e1 = *vector::borrow(v1, i); - let e2 = *vector::borrow(v2, i); - if (e1 > e2) { - return 1 - } else if (e2 > e1) { - return 2 - }; - i = i + 1; - }; - - 0 - } - - fun normalize_weights( - bridge_ids: vector, weights: vector - ): vector { - let len = vector::length(&bridge_ids); - assert!( - len == vector::length(&weights), - error::invalid_argument(EVECTOR_LENGTH), - ); - - let weight_sum = 0; - vector::for_each_ref( - &weights, - |weight| { - weight_sum = weight_sum + decimal128::val(weight); - }, - ); - - let n_weights = vector[]; - vector::zip_reverse( - bridge_ids, - weights, - |bridge_id, weight| { - vector::push_back( - &mut n_weights, - Weight { - bridge_id: bridge_id, - weight: decimal128::from_ratio( - decimal128::val(&weight), - weight_sum, - ), - }, - ); - }, - ); - - n_weights - } - - // if submitter submit merkle root after grace period, set voting end time to current timestamp + voting period - // else set it to former epoch end time + grace period + voting period - fun calculate_voting_end_time( - timestamp: u64, module_store: &ModuleStore, - ): u64 { - if (timestamp - > module_store.epoch_end_timestamp + module_store.snapshot_grace_period) { - return timestamp + module_store.voting_period - } else { - return module_store.epoch_end_timestamp + module_store.snapshot_grace_period - + module_store.voting_period - } - } - - // - // views - // - - #[view] - public fun get_module_store(): ModuleResponse acquires ModuleStore { - let module_store = borrow_global(@initia_std); - - ModuleResponse { - current_epoch: module_store.current_epoch, - epoch_start_timestamp: module_store.epoch_start_timestamp, - epoch_end_timestamp: module_store.epoch_end_timestamp, - epoch_interval: module_store.epoch_interval, - snapshot_grace_period: module_store.snapshot_grace_period, - voting_period: module_store.voting_period, - submitter: module_store.submitter, - min_voting_period: module_store.min_voting_period, - quorum_ratio: module_store.quorum_ratio, - challenge_deposit_amount: module_store.challenge_deposit_amount, - } - } - - #[view] - public fun get_total_tally(epoch: u64): u64 acquires ModuleStore { - let module_store = borrow_global(@initia_std); - let epoch_key = table_key::encode_u64(epoch); - assert!( - table::contains(&module_store.proposals, epoch_key), - error::not_found(ESTAGE_NOT_FOUND), - ); - let proposal = table::borrow(&module_store.proposals, epoch_key); - proposal.total_tally - } - - #[view] - public fun get_tally(epoch: u64, bridge_id: u64): u64 acquires ModuleStore { - let module_store = borrow_global(@initia_std); - let epoch_key = table_key::encode_u64(epoch); - assert!( - table::contains(&module_store.proposals, epoch_key), - error::not_found(ESTAGE_NOT_FOUND), - ); - let proposal = table::borrow(&module_store.proposals, epoch_key); - *table::borrow_with_default( - &proposal.tally, - table_key::encode_u64(bridge_id), - &0, - ) - } - - #[view] - public fun get_challenge(challenge_id: u64): ChallengeResponse acquires ModuleStore { - let module_store = borrow_global(@initia_std); - let challenge_key = table_key::encode_u64(challenge_id); - assert!( - table::contains( - &module_store.challenges, - challenge_key, - ), - error::not_found(ECHALLENGE_NOT_FOUND), - ); - let challenge = table::borrow(&module_store.challenges, challenge_key); - - ChallengeResponse { - title: challenge.title, - summary: challenge.summary, - api_uri: challenge.api_uri, - epoch: challenge.epoch, - challenger: challenge.challenger, - voting_power_epoch: challenge.voting_power_epoch, - new_submitter: challenge.new_submitter, - merkle_root: challenge.merkle_root, - snapshot_height: challenge.snapshot_height, - yes_tally: challenge.yes_tally, - no_tally: challenge.no_tally, - quorum: challenge.quorum, - voting_end_time: challenge.voting_end_time, - min_voting_end_time: challenge.min_voting_end_time, - deposit_amount: challenge.deposit_amount, - is_executed: challenge.is_executed, - } - } - - #[view] - public fun get_challenge_by_epoch(epoch: u64): vector acquires ModuleStore { - let module_store = borrow_global(@initia_std); - let iter = table::iter( - &module_store.challenges, - option::none(), - option::none(), - 1, - ); - - let challenge_responses = vector::empty(); - loop { - if (!table::prepare, Challenge>(iter)) { break }; - let (_, challenge) = table::next, Challenge>(iter); - if (challenge.epoch == epoch) { - vector::push_back( - &mut challenge_responses, - ChallengeResponse { - title: challenge.title, - summary: challenge.summary, - api_uri: challenge.api_uri, - epoch: challenge.epoch, - challenger: challenge.challenger, - voting_power_epoch: challenge.voting_power_epoch, - new_submitter: challenge.new_submitter, - merkle_root: challenge.merkle_root, - snapshot_height: challenge.snapshot_height, - yes_tally: challenge.yes_tally, - no_tally: challenge.no_tally, - quorum: challenge.quorum, - voting_end_time: challenge.voting_end_time, - min_voting_end_time: challenge.min_voting_end_time, - deposit_amount: challenge.deposit_amount, - is_executed: challenge.is_executed, - }, - ); - }; - }; - - challenge_responses - } - - #[view] - public fun get_proposal(epoch: u64): ProposalResponse acquires ModuleStore { - let module_store = borrow_global(@initia_std); - let epoch_key = table_key::encode_u64(epoch); - assert!( - table::contains(&module_store.proposals, epoch_key), - error::not_found(ESTAGE_NOT_FOUND), - ); - let proposal = table::borrow(&module_store.proposals, epoch_key); - - ProposalResponse { - merkle_root: proposal.merkle_root, - total_tally: proposal.total_tally, - snapshot_height: proposal.snapshot_height, - voting_end_time: proposal.voting_end_time, - api_uri: proposal.api_uri, - executed: proposal.executed, - } - } - - #[view] - public fun get_weight_vote(epoch: u64, user: address): WeightVoteResponse acquires ModuleStore { - let module_store = borrow_global(@initia_std); - let epoch_key = table_key::encode_u64(epoch); - assert!( - table::contains(&module_store.proposals, epoch_key), - error::not_found(ESTAGE_NOT_FOUND), - ); - let proposal = table::borrow(&module_store.proposals, epoch_key); - let vote = table::borrow(&proposal.votes, user); - - WeightVoteResponse { voting_power: vote.voting_power, weights: vote.weights, } - } - - #[test_only] - use initia_std::block::set_block_info; - - #[test_only] - use initia_std::coin; - - #[test_only] - use initia_std::string; - - #[test_only] - const DEFAULT_VIP_L2_CONTRACT_FOR_TEST: vector = (b"vip_l2_contract"); - #[test_only] - fun init_test(chain: &signer): coin::MintCapability { - let init_stage = 1; - initialize( - chain, - 100, - 100, - 10, - 50, - @0x2, - 1, - decimal128::from_ratio(3, 10), - 100, - ); - set_block_info(100, 101); - primary_fungible_store::init_module_for_test(); - let (mint_cap, _, _) = - coin::initialize( - chain, - option::none(), - string::utf8(b"uinit"), - string::utf8(b"uinit"), - 6, - string::utf8(b""), - string::utf8(b""), - ); - vip::init_module_for_test(); - vip::register( - chain, - @0x2, - 1, - @0x12, - init_stage, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - decimal256::zero(), - decimal256::zero(), - decimal256::zero(), - ); - vip::register( - chain, - @0x2, - 2, - @0x12, - init_stage, - string::utf8(DEFAULT_VIP_L2_CONTRACT_FOR_TEST), - decimal256::zero(), - decimal256::zero(), - decimal256::zero(), - ); - mint_cap - } - - #[test_only] - fun create_merkle_tree( - epoch: u64, addresses: vector
, voting_powers: vector - ): vector>> { - let leaf_count = 2; - let len = vector::length(&addresses); - let empty_leaf = voting_power_hash(epoch, @0x0, 0); - while (leaf_count <= len) { leaf_count = leaf_count << 1 }; - - let tree = vector[]; - let leaves = vector[]; - let empty_leaf_count = leaf_count - len; - let i = 0; - while (i < len) { - let addr = *vector::borrow(&addresses, i); - let vp = *vector::borrow(&voting_powers, i); - vector::push_back( - &mut leaves, - voting_power_hash(epoch, addr, vp), - ); - i = i + 1; - }; - - while (i < empty_leaf_count) { - vector::push_back(&mut leaves, empty_leaf); - i = i + 1; - }; - - vector::push_back(&mut tree, leaves); - - while (vector::length(&leaves) > 1) { - let new_leaves = vector[]; - let len = vector::length(&leaves); - let i = 0; - - while (i < len) { - let tmp = vector::empty(); - let left = *vector::borrow(&leaves, i); - let right = *vector::borrow(&leaves, i + 1); - let cmp = bytes_cmp(&left, &right); - if (cmp != 2) { - let t = left; - left = right; - right = t; - }; - - vector::append(&mut tmp, left); - vector::append(&mut tmp, right); - let leaf = sha3_256(tmp); - vector::push_back(&mut new_leaves, leaf); - - i = i + 2; - }; - - vector::push_back(&mut tree, new_leaves); - leaves = new_leaves; - }; - - return tree - } - - #[test_only] - fun get_merkle_root(tree: vector>>): vector { - let len = vector::length(&tree); - *vector::borrow(vector::borrow(&tree, len - 1), 0) - } - - #[test_only] - fun get_proofs(tree: vector>>, idx: u64): vector> { - let len = vector::length(&tree); - let i = 0; - let proofs = vector[]; - while (i < len - 1) { - let leaves = vector::borrow(&tree, i); - let leaf = - if (idx % 2 == 1) { - *vector::borrow(leaves, idx - 1) - } else { - *vector::borrow(leaves, idx + 1) - }; - vector::push_back(&mut proofs, leaf); - idx = idx / 2; - i = i + 1; - }; - - proofs - } - - #[test(chain = @0x1, submitter = @0x2, u1 = @0x101, u2 = @0x102, u3 = @0x103, u4 = @0x104)] - fun proposal_end_to_end( - chain: &signer, - submitter: &signer, - u1: &signer, - u2: &signer, - u3: &signer, - u4: &signer, - ) acquires ModuleStore { - init_test(chain); - let addresses = vector[ - signer::address_of(u1), - signer::address_of(u2), - signer::address_of(u3), - signer::address_of(u4),]; - let voting_powers = vector[10, 20, 30, 40]; - let epoch = 1; - let tree = create_merkle_tree(epoch, addresses, voting_powers); - let merkle_root = get_merkle_root(tree); - - submit_snapshot( - submitter, - merkle_root, - string::utf8(b"https://abc.com"), - 100, - ); - vote( - u1, - epoch, - get_proofs(tree, 0), - 10, - vector[1, 2], - vector[decimal128::from_ratio(1, 5), decimal128::from_ratio(4, 5)], // 2, 8 - ); - - vote( - u2, - epoch, - get_proofs(tree, 1), - 20, - vector[1, 2], - vector[decimal128::from_ratio(2, 5), decimal128::from_ratio(3, 5)], // 8, 12 - ); - - vote( - u3, - epoch, - get_proofs(tree, 2), - 30, - vector[1, 2], - vector[decimal128::from_ratio(2, 5), decimal128::from_ratio(2, 5)], // 12, 12 - ); - - vote( - u4, - epoch, - get_proofs(tree, 3), - 40, - vector[1, 2], - vector[decimal128::from_ratio(3, 5), decimal128::from_ratio(1, 5)], // 24, 8 // user can vote with - ); - - let proposal = get_proposal(1); - assert!(proposal.total_tally == 86, 0); - - let vote1 = get_tally(1, 1); - let vote2 = get_tally(1, 2); - let total_tally = get_total_tally(1); - assert!(vote1 == 46, 1); - assert!(vote2 == 40, 2); - assert!(total_tally == 86, 3); - - let weight_vote = get_weight_vote(1, signer::address_of(u1)); - assert!(weight_vote.voting_power == 10, 4); - assert!(vector::length(&weight_vote.weights) == 2, 5); - // update vote of u4 - vote( - u4, - epoch, - get_proofs(tree, 3), - 40, - vector[1, 2], - vector[decimal128::from_ratio(4, 5), decimal128::from_ratio(1, 5)], // 32, 8 // user can vote with - ); - vote1 = get_tally(1, 1); - vote2 = get_tally(1, 2); - total_tally = get_total_tally(1); - assert!(vote1 == 54, 6); - assert!(vote2 == 40, 7); - assert!(total_tally == 94, 8); - - let weight_vote = get_weight_vote(1, signer::address_of(u1)); - assert!(weight_vote.voting_power == 10, 9); - assert!(vector::length(&weight_vote.weights) == 2, 10); - set_block_info(100, 201); - execute_proposal(); - } - - #[test(chain = @0x1, submitter = @0x2, u1 = @0x101, u2 = @0x102, u3 = @0x103, u4 = @0x104)] - fun challenge_end_to_end( - chain: &signer, - submitter: &signer, - u1: &signer, - u2: &signer, - u3: &signer, - u4: &signer, - ) acquires ModuleStore { - // fund - let mint_cap = init_test(chain); - coin::mint_to( - &mint_cap, - signer::address_of(u1), - 100, - ); - coin::mint_to( - &mint_cap, - signer::address_of(u2), - 100, - ); - - // submit root - let epoch = 1; - let addresses = vector[ - signer::address_of(u1), - signer::address_of(u2), - signer::address_of(u3), - signer::address_of(u4),]; - let voting_powers = vector[10, 20, 30, 40]; - let tree = create_merkle_tree(epoch, addresses, voting_powers); - let merkle_root = get_merkle_root(tree); - submit_snapshot( - submitter, - merkle_root, - string::utf8(b"https://abc.com"), - 100, - ); - - // votes - vote( - u1, - epoch, - get_proofs(tree, 0), - 10, - vector[1, 2], - vector[decimal128::from_ratio(1, 5), decimal128::from_ratio(4, 5)], // 2, 8 - ); - - vote( - u2, - epoch, - get_proofs(tree, 1), - 20, - vector[1, 2], - vector[decimal128::from_ratio(2, 5), decimal128::from_ratio(3, 5)], // 8, 12 - ); - - // execute - set_block_info(100, 161); - execute_proposal(); - - let module_store = borrow_global(@initia_std); - assert!(module_store.epoch_start_timestamp == 100, 0); - assert!(module_store.epoch_end_timestamp == 200, 1); - - // after grace period - set_block_info(100, 211); - - // create challenge - let voting_powers = vector[15, 25, 35, 45]; - let tree = create_merkle_tree(epoch, addresses, voting_powers); - create_challenge( - u1, - string::utf8(b"challenge"), - string::utf8(b"challenge"), - get_merkle_root(tree), - string::utf8(b"https://abc2.com"), - 100u64, - ); - - // vote proposal - vote_challenge(u1, 1, true); - - // after min_voting_period - set_block_info(100, 212); - - // execute challenge - execute_challenge(1); - - let module_response = get_module_store(); - let vote = get_proposal(2); - assert!( - module_response.epoch_start_timestamp == 200, - 2, - ); - assert!(module_response.epoch_end_timestamp == 300, 3); - assert!(module_response.current_epoch == 2, 4); - assert!( - module_response.submitter == signer::address_of(u1), - 5, - ); - assert!(vote.merkle_root == get_merkle_root(tree), 6); - assert!( - vote.api_uri == string::utf8(b"https://abc2.com"), - 6, - ); - - set_block_info(100, 251); - - // create challenge - let voting_powers = vector[10, 25, 35, 45]; - let tree = create_merkle_tree(epoch, addresses, voting_powers); - create_challenge( - u2, - string::utf8(b"challenge"), - string::utf8(b"challenge"), - get_merkle_root(tree), - string::utf8(b"https://abc3.com"), - 100u64, - ); - - // vote proposal - vote_challenge(u2, 2, true); - - // after min_voting_period - set_block_info(100, 252); - - // execute proposal - execute_challenge(2); - - module_response = get_module_store(); - vote = get_proposal(2); - assert!( - module_response.epoch_start_timestamp == 300, - 7, - ); - assert!(module_response.epoch_end_timestamp == 400, 8); - assert!(module_response.current_epoch == 2, 9); - assert!( - module_response.submitter == signer::address_of(u2), - 10, - ); - assert!(vote.merkle_root == get_merkle_root(tree), 11); - assert!( - vote.api_uri == string::utf8(b"https://abc3.com"), - 12, - ); - - let challenge = get_challenge(2); - assert!( - challenge.title == string::utf8(b"challenge"), - 13, - ); - assert!( - challenge.summary == string::utf8(b"challenge"), - 14, - ); - assert!( - challenge.api_uri == string::utf8(b"https://abc3.com"), - 15, - ); - assert!(challenge.epoch == 2, 16); - assert!(challenge.yes_tally == 20, 17); - assert!(challenge.no_tally == 0, 18); - assert!(challenge.quorum == 9, 19); - assert!(challenge.is_executed == true, 20); - } -} diff --git a/initia_stdlib/sources/vip/zapping.move b/initia_stdlib/sources/vip/zapping.move deleted file mode 100644 index bf26b85..0000000 --- a/initia_stdlib/sources/vip/zapping.move +++ /dev/null @@ -1,1109 +0,0 @@ -module initia_std::vip_zapping { - use std::error; - use std::signer; - use std::option::Option; - use std::event; - use std::string::String; - use std::table; - use std::block; - use std::vector; - - use initia_std::staking::{Self, Delegation, DelegationResponse}; - use initia_std::coin; - use initia_std::dex; - use initia_std::primary_fungible_store; - use initia_std::object::{Self, ExtendRef, Object}; - use initia_std::simple_map::{Self, SimpleMap}; - use initia_std::fungible_asset::{Self, FungibleAsset, Metadata}; - - friend initia_std::vip; - - // - // Errors - // - - const ELOCK_STAKING_END: u64 = 1; - const ELOCK_STAKING_IN_PROGRESS: u64 = 2; - const ELS_STORE_NOT_FOUND: u64 = 3; - const ELS_STORE_ALREADY_EXISTS: u64 = 4; - const EUNAUTHORIZED: u64 = 5; - const EZAPPING_NOT_EXIST: u64 = 6; - const EZAPPING_ALREADY_EXIST: u64 = 7; - const EINVALID_ZAPPING_AMOUNT: u64 = 8; - - // - // Constants - // - - const DEFAULT_LOCK_PERIOD: u64 = 60 * 60 * 24 * 7 * 26; // 26 weeks - - // - // Resources - // - - struct ModuleStore has key { - extend_ref: ExtendRef, - // lock period for zapping (in seconds) - lock_period: u64, - zappings: table::Table, - zid: u64, - } - - struct Zapping has store { - bridge_id: u64, - zapper: address, - validator: String, - stage: u64, // vesting start stage - lock_period: u64, // lock period - release_time: u64, - esinit_metadata: Object, - stakelisted_metadata: Object, - delegation: Delegation, - share: u64, - } - - struct DelegationInfo has drop, store { - validator: String, - share: u64, - unclaimed_reward: u64, - } - - struct LSStore has key { - entries: SimpleMap, - } - - // - // Responses - // - - struct ZappingResponse has drop { - bridge_id: u64, - zapper: address, - validator: String, - stage: u64, - lock_period: u64, - release_time: u64, - esinit_metadata: Object, - stakelisted_metadata: Object, - delegation: DelegationResponse, - share: u64, - } - - struct LSEntryResponse has drop { - delegation: DelegationResponse, - release_time: u64, - share: u64, - } - - // - // Events - // - - #[event] - struct LockEvent has drop, store { - coin_metadata: address, - bond_amount: u64, - release_time: u64, - share: u64, - } - - #[event] - struct ZappingClaimEvent has drop, store { - zid: u64, - coin_metadata: address, - reward_amount: u64, - delegation_reward_amount: u64, - share: u64 - } - - #[event] - struct RewardClaimEvent has drop, store { - zid: u64, - coin_metadata: address, - reward_amount: u64, - } - - #[event] - struct DepositEvent has drop, store { - zid: u64, - addr: address, - delegation: DelegationInfo, - release_time: u64, - share: u64 - } - - #[event] - struct WithdrawEvent has drop, store { - zid: u64, - addr: address, - delegation: DelegationInfo, - release_time: u64, - share: u64 - } - - #[event] - struct ZappingEvent has drop, store { - zid: u64, - account: address, - bridge_id: u64, - stage: u64, - lp_metadata: Object, - validator: String, - zapping_amount: u64, - stakelisted_amount: u64, - stakelisted_metadata: Object, - release_time: u64, - } - - // - // Helper Functions - // - - fun check_chain_permission(chain: &signer) { - assert!( - signer::address_of(chain) == @initia_std, - error::permission_denied(EUNAUTHORIZED), - ); - } - - fun init_module(chain: &signer) { - let constructor_ref = object::create_object(@initia_std, false); - let extend_ref = object::generate_extend_ref(&constructor_ref); - - move_to( - chain, - ModuleStore { - extend_ref, - lock_period: DEFAULT_LOCK_PERIOD, - zappings: table::new(), - zid: 0, - }, - ); - } - - // - // Entry Functions - // - - public entry fun batch_claim_zapping_script( - account: &signer, zids: vector, - ) acquires ModuleStore, LSStore { - vector::enumerate_ref( - &zids, - |_i, zid| { - claim_zapping_script(account, *zid); - }, - ); - } - - public entry fun batch_claim_reward_script( - account: &signer, zids: vector, - ) acquires ModuleStore, LSStore { - vector::enumerate_ref( - &zids, - |_i, zid| { - claim_reward_script(account, *zid); - }, - ); - } - - // deposit zapping delegation to user's staking - public entry fun claim_zapping_script(account: &signer, zid: u64,) acquires ModuleStore, LSStore { - let account_addr = signer::address_of(account); - let zapping = withdraw_zapping(account, zid); - - // claim delegation with lock staking rewards - let (delegation, reward) = claim(zapping, zid); - - // deposit delegation to user address - let d_reward = staking::deposit_delegation(account_addr, delegation); - - // merge delegation rewards with lock staking rewards - fungible_asset::merge(&mut reward, d_reward); - - // deposit rewards to account coin store - primary_fungible_store::deposit(account_addr, reward); - } - - public entry fun claim_reward_script(account: &signer, zid: u64) acquires ModuleStore, LSStore { - let account_addr = signer::address_of(account); - - assert!( - exists(account_addr), - error::not_found(ELS_STORE_NOT_FOUND), - ); - - let ls_store = borrow_global_mut(account_addr); - assert!( - simple_map::contains_key(&ls_store.entries, &zid), - error::not_found(EZAPPING_NOT_EXIST), - ); - - let module_store = borrow_global_mut(@initia_std); - let zapping = table::borrow_mut(&mut module_store.zappings, zid); - let reward = staking::claim_reward(&mut zapping.delegation); - - event::emit( - RewardClaimEvent { - zid, - coin_metadata: object::object_address( - &fungible_asset::asset_metadata(&reward) - ), - reward_amount: fungible_asset::amount(&reward) - }, - ); - - coin::deposit(account_addr, reward); - } - - public entry fun update_lock_period_script( - chain: &signer, lock_period: u64, - ) acquires ModuleStore { - check_chain_permission(chain); - let module_store = borrow_global_mut(@initia_std); - module_store.lock_period = lock_period; - } - - // - // Friend Functions - // - - public(friend) fun zapping( - account: &signer, - bridge_id: u64, - lp_metadata: Object, - min_liquidity: Option, - validator: String, - stage: u64, - esinit: FungibleAsset, - stakelisted: FungibleAsset, - ) acquires ModuleStore, LSStore { - assert!( - fungible_asset::amount(&esinit) > 0 && fungible_asset::amount(&stakelisted) > - 0, - error::invalid_argument(EINVALID_ZAPPING_AMOUNT), - ); - - let pair = object::convert(lp_metadata); - let (_height, timestamp) = block::get_block_info(); - let module_store = borrow_global(@initia_std); - let release_time = timestamp + module_store.lock_period; - let zapping_amount = fungible_asset::amount(&esinit); - let esinit_metadata = fungible_asset::asset_metadata(&esinit); - let stakelisted_amount = fungible_asset::amount(&stakelisted); - let stakelisted_metadata = fungible_asset::asset_metadata(&stakelisted); - - let (coin_a_metadata, _) = dex::pool_metadata(pair); - - // if pair is reversed, swap coin_a and coin_b - let (coin_a, coin_b) = - if (coin_a_metadata == esinit_metadata) { - (esinit, stakelisted) - } else { - (stakelisted, esinit) - }; - - let zid = - provide_lock_stake( - account, - bridge_id, - coin_a, - coin_b, - pair, - min_liquidity, - validator, - stage, - release_time, - esinit_metadata, - stakelisted_metadata, - ); - - event::emit( - ZappingEvent { - zid, - account: signer::address_of(account), - bridge_id, - stage, - lp_metadata, - validator, - zapping_amount, - stakelisted_amount, - stakelisted_metadata, - release_time, - }, - ); - } - - // - // Implementations - // - - fun register(account: &signer) { - assert!( - !exists(signer::address_of(account)), - error::already_exists(ELS_STORE_ALREADY_EXISTS), - ); - move_to( - account, - LSStore { entries: simple_map::create(), }, - ); - } - - fun lock_stake( - account: &signer, - bridge_id: u64, - lock_coin: FungibleAsset, - validator: String, - stage: u64, - release_time: u64, - esinit_metadata: Object, - stakelisted_metadata: Object, - ): u64 acquires ModuleStore, LSStore { - let account_addr = signer::address_of(account); - if (!exists(account_addr)) { - register(account); - }; - - if (!staking::is_account_registered(signer::address_of(account))) { - staking::register(account); - }; - - let (share, zid, delegation_res) = - create_lock_stake_entry( - bridge_id, - account_addr, - validator, - stage, - release_time, - lock_coin, - esinit_metadata, - stakelisted_metadata, - ); - - // deposit lock stake to account store - deposit_lock_stake_entry( - account_addr, - release_time, - share, - zid, - delegation_res, - ); - - zid - } - - fun provide_lock_stake( - account: &signer, - bridge_id: u64, - coin_a: FungibleAsset, - coin_b: FungibleAsset, - pair: Object, - min_liquidity: Option, - validator: String, - stage: u64, - release_time: u64, - esinit_metadata: Object, - stakelisted_metadata: Object, - ): u64 acquires LSStore, ModuleStore { - let lp_token = dex::provide_liquidity(pair, coin_a, coin_b, min_liquidity); - - let zid = - lock_stake( - account, - bridge_id, - lp_token, - validator, - stage, - release_time, - esinit_metadata, - stakelisted_metadata, - ); - - zid - } - - /// Execute lock staking and return created LSEntry - fun create_lock_stake_entry( - bridge_id: u64, - zapper: address, - validator: String, - stage: u64, - release_time: u64, - lock_coin: FungibleAsset, - esinit_metadata: Object, - stakelisted_metadata: Object, - ): (u64, u64, DelegationResponse) acquires ModuleStore { - let bond_amount = fungible_asset::amount(&lock_coin); - let share = bond_amount; - let coin_metadata = - object::object_address(&fungible_asset::asset_metadata(&lock_coin)); - let delegation = staking::delegate(validator, lock_coin); - - let module_store = borrow_global_mut(@initia_std); - let zid = module_store.zid; - assert!( - !table::contains(&module_store.zappings, zid), - error::already_exists(EZAPPING_ALREADY_EXIST), - ); - - let (_, block_time) = block::get_block_info(); - assert!( - release_time > block_time, - error::unavailable(ELOCK_STAKING_END), - ); - - // create zapping - let zapping = Zapping { - bridge_id, - zapper, - validator, - stage, - lock_period: module_store.lock_period, - release_time, - esinit_metadata, - stakelisted_metadata, - delegation, - share - }; - - let delegation_res = - staking::get_delegation_response_from_delegation(&zapping.delegation); - table::add( - &mut module_store.zappings, - zid, - zapping, - ); - - event::emit( - LockEvent { coin_metadata, bond_amount, release_time, share, }, - ); - module_store.zid = zid + 1; - (share, zid, delegation_res) - } - - // Deposit LSEntry to user's LSStore - fun deposit_lock_stake_entry( - account_addr: address, - release_time: u64, - share: u64, - zid: u64, - delegation_res: DelegationResponse - ) acquires LSStore { - assert!( - exists(account_addr), - error::not_found(ELS_STORE_NOT_FOUND), - ); - - let ls_store = borrow_global_mut(account_addr); - simple_map::add(&mut ls_store.entries, zid, true); - - event::emit( - DepositEvent { - zid, - addr: account_addr, - delegation: delegation_res_to_delegation_info(&delegation_res), - release_time, - share, - }, - ); - } - - fun withdraw_zapping(account: &signer, zid: u64): Zapping acquires ModuleStore, LSStore { - let account_addr = signer::address_of(account); - assert!( - exists(account_addr), - error::not_found(ELS_STORE_NOT_FOUND), - ); - - let ls_store = borrow_global_mut(account_addr); - assert!( - simple_map::contains_key(&ls_store.entries, &zid), - error::not_found(EZAPPING_NOT_EXIST), - ); - - let module_store = borrow_global_mut(@initia_std); - let zapping = table::remove(&mut module_store.zappings, zid); - simple_map::remove(&mut ls_store.entries, &zid); - - let delegation_res = - staking::get_delegation_response_from_delegation(&zapping.delegation); - - event::emit( - WithdrawEvent { - zid, - addr: account_addr, - delegation: delegation_res_to_delegation_info(&delegation_res), - release_time: zapping.release_time, - share: zapping.share, - }, - ); - - zapping - } - - /// Claim lock staking rewards with Delegation - fun claim(zapping: Zapping, zid: u64): (Delegation, FungibleAsset) { - let (_, block_time) = block::get_block_info(); - assert!( - block_time >= zapping.release_time, - error::unavailable(ELOCK_STAKING_IN_PROGRESS), - ); - - let reward = staking::claim_reward(&mut zapping.delegation); - let Zapping { - bridge_id: _, - zapper: _, - validator: _, - stage: _, - lock_period: _, - release_time: _, - esinit_metadata: _, - stakelisted_metadata: _, - delegation, - share, - } = zapping; - - let delegation_res = - staking::get_delegation_response_from_delegation(&delegation); - - event::emit( - ZappingClaimEvent { - zid, - coin_metadata: object::object_address( - &fungible_asset::asset_metadata(&reward) - ), - reward_amount: fungible_asset::amount(&reward), - delegation_reward_amount: staking::get_unclaimed_reward_from_delegation_response( - &delegation_res - ), - share, - }, - ); - - (delegation, reward) - } - - fun delegation_res_to_delegation_info( - delegation_res: &DelegationResponse - ): DelegationInfo { - DelegationInfo { - validator: staking::get_validator_from_delegation_response(delegation_res), - unclaimed_reward: staking::get_unclaimed_reward_from_delegation_response( - delegation_res - ), - share: staking::get_share_from_delegation_response(delegation_res), - } - } - - // - // ViewFunctions - // - - #[view] - public fun get_zapping(zid: u64): ZappingResponse acquires ModuleStore { - let module_store = borrow_global(@initia_std); - assert!( - table::contains(&module_store.zappings, zid), - error::not_found(EZAPPING_NOT_EXIST), - ); - let zapping = table::borrow(&module_store.zappings, zid); - - ZappingResponse { - bridge_id: zapping.bridge_id, - zapper: zapping.zapper, - validator: zapping.validator, - stage: zapping.stage, - lock_period: zapping.lock_period, - release_time: zapping.release_time, - esinit_metadata: zapping.esinit_metadata, - stakelisted_metadata: zapping.stakelisted_metadata, - delegation: staking::get_delegation_response_from_delegation( - &zapping.delegation - ), - share: zapping.share, - } - } - - #[view] - public fun get_delegation_info(zid: u64): DelegationInfo acquires ModuleStore { - let module_store = borrow_global(@initia_std); - assert!( - table::contains(&module_store.zappings, zid), - error::not_found(EZAPPING_NOT_EXIST), - ); - let zapping = table::borrow(&module_store.zappings, zid); - - let delegation_res = - staking::get_delegation_response_from_delegation(&zapping.delegation); - let delegation_info = delegation_res_to_delegation_info(&delegation_res); - - delegation_info - } - - #[view] - public fun get_delegation_infos(zids: vector): vector acquires ModuleStore { - let delegation_infos = vector[]; - vector::enumerate_ref( - &zids, - |_i, zid| { - let delegation_info = get_delegation_info(*zid); - vector::push_back( - &mut delegation_infos, - delegation_info, - ); - }, - ); - delegation_infos - } - - // - // Test Functions - // - - #[test_only] - use std::decimal128; - - #[test_only] - use std::option; - - #[test_only] - use std::string; - - #[test_only] - use initia_std::vip_reward; - - #[test_only] - public fun init_module_for_test() { - init_module(&initia_std::account::create_signer_for_test(@initia_std)); - } - - #[test_only] - fun initialize_coin(account: &signer, symbol: String,) - : ( - coin::BurnCapability, coin::FreezeCapability, coin::MintCapability - ) { - let (mint_cap, burn_cap, freeze_cap, _) = - coin::initialize_and_generate_extend_ref( - account, - option::none(), - string::utf8(b""), - symbol, - 6, - string::utf8(b""), - string::utf8(b""), - ); - - return (burn_cap, freeze_cap, mint_cap) - } - - #[test_only] - public fun test_setup_for_zapping( - chain: &signer, - account: &signer, - esinit_amount: u64, - stakelisted_amount: u64, - ): (Object, Object, Object, String) { - dex::init_module_for_test(); - staking::test_setup(); - init_module_for_test(); - - let (_burn_cap, _freeze_cap, mint_cap) = - initialize_coin(chain, string::utf8(b"INIT")); - coin::mint_to( - &mint_cap, - signer::address_of(chain), - esinit_amount * 2, - ); - coin::mint_to( - &mint_cap, - signer::address_of(account), - esinit_amount, - ); - let (_burn_cap, _freeze_cap, mint_cap) = - initialize_coin(chain, string::utf8(b"USDC")); - coin::mint_to( - &mint_cap, - signer::address_of(chain), - stakelisted_amount * 2, - ); - coin::mint_to( - &mint_cap, - signer::address_of(account), - stakelisted_amount, - ); - - let esinit_metadata = - coin::metadata( - signer::address_of(chain), - string::utf8(b"INIT"), - ); - let stakelisted_metadata = - coin::metadata( - signer::address_of(chain), - string::utf8(b"USDC"), - ); - let validator = string::utf8(b"val"); - - dex::create_pair_script( - chain, - string::utf8(b"pair"), - string::utf8(b"INIT-USDC"), - decimal128::from_ratio(3, 1000), - decimal128::from_ratio(5, 10), - decimal128::from_ratio(5, 10), - stakelisted_metadata, - esinit_metadata, - stakelisted_amount, - esinit_amount, - ); - - // check reversed pair - dex::create_pair_script( - chain, - string::utf8(b"pair"), - string::utf8(b"USDC-INIT"), - decimal128::from_ratio(3, 1000), - decimal128::from_ratio(5, 10), - decimal128::from_ratio(5, 10), - esinit_metadata, - stakelisted_metadata, - esinit_amount, - stakelisted_amount, - ); - - let lp_metadata = - coin::metadata( - signer::address_of(chain), - string::utf8(b"INIT-USDC"), - ); - staking::initialize_for_chain(chain, lp_metadata); - staking::set_staking_share_ratio( - *string::bytes(&validator), - &lp_metadata, - 1, - 1, - ); - - (esinit_metadata, stakelisted_metadata, lp_metadata, validator) - } - - #[test(chain = @0x1, account = @0x999)] - fun test_zapping(chain: &signer, account: &signer,) acquires ModuleStore, LSStore { - let (esinit_metadata, stakelisted_metadata, lp_metadata, val) = - test_setup_for_zapping( - chain, - account, - 1_000_000_000, - 1_000_000_000, - ); - - let bridge_id = 1; - let stage = 10; - let start_time = 1000000; - let lock_period = DEFAULT_LOCK_PERIOD; - let release_time = start_time + lock_period; - - block::set_block_info(1, start_time); - let esinit = - primary_fungible_store::withdraw( - account, - esinit_metadata, - 500_000_000, - ); - let stakelisted = - primary_fungible_store::withdraw( - account, - stakelisted_metadata, - 500_000_000, - ); - - zapping( - account, - bridge_id, - lp_metadata, - option::none(), - val, - stage, - esinit, - stakelisted, - ); - - let zapping = get_zapping(0); - assert!(zapping.stage == stage, 0); - assert!(zapping.release_time == release_time, 1); - - block::set_block_info(1, start_time + 1); - let esinit = - primary_fungible_store::withdraw( - account, - esinit_metadata, - 500_000_000, - ); - let stakelisted = - primary_fungible_store::withdraw( - account, - stakelisted_metadata, - 500_000_000, - ); - - zapping( - account, - bridge_id, - lp_metadata, - option::none(), - val, - stage, - esinit, - stakelisted, - ); - - let zapping = get_zapping(1); - assert!(zapping.stage == stage, 2); - assert!(zapping.release_time == release_time + 1, 3); - } - - #[test(chain = @0x1, account = @0x999)] - fun test_zapping_multiple(chain: &signer, account: &signer,) acquires ModuleStore, LSStore { - let (esinit_metadata, stakelisted_metadata, lp_metadata, val) = - test_setup_for_zapping( - chain, - account, - 1_000_000_000, - 1_000_000_000, - ); - - let bridge_id = 1; - let (stage, lock_period, start_time) = (10, 3600, 1000000); - let release_time = start_time + lock_period; - update_lock_period_script(chain, lock_period); - - block::set_block_info(1, start_time); - - let zapping_times = 0; - while (zapping_times < 500) { - let esinit = primary_fungible_store::withdraw( - account, esinit_metadata, 1_000 - ); - let stakelisted = - primary_fungible_store::withdraw(account, stakelisted_metadata, 1_000); - - zapping( - account, - bridge_id, - lp_metadata, - option::none(), - val, - stage, - esinit, - stakelisted, - ); - block::set_block_info( - 2 + zapping_times, - start_time + release_time * (zapping_times + 1) + 1, - ); - claim_zapping_script(account, zapping_times); - zapping_times = zapping_times + 1; - } - } - - #[test(chain = @0x1, account = @0x999)] - #[expected_failure(abort_code = 0x10004, location = fungible_asset)] - fun test_zapping_insufficient_zapping( - chain: &signer, account: &signer, - ) acquires ModuleStore, LSStore { - let (e_m, s_m, l_m, val) = test_setup_for_zapping(chain, account, 0, 0); - let stage = 10; - let start_time = 1000000; - - block::set_block_info(1, start_time); - let esinit = primary_fungible_store::withdraw(account, e_m, 500_000_000); - let stakelisted = primary_fungible_store::withdraw(account, s_m, 500_000_000); - - zapping( - account, - 1, - l_m, - option::none(), - val, - stage, - esinit, - stakelisted, - ); - } - - #[test(chain = @0x1, account = @0x3, relayer = @0x3d18d54532fc42e567090852db6eb21fa528f952)] - fun test_claim_reward( - chain: &signer, - account: &signer, - relayer: &signer, - ) acquires ModuleStore, LSStore { - let (e_m, s_m, l_m, val) = - test_setup_for_zapping( - chain, - account, - 1_000_000_000, - 1_000_000_000, - ); - let (stage, lock_period, start_time) = (10, 3600, 1000000); - staking::fund_reward_coin( - chain, - signer::address_of(relayer), - 2_000_000, - ); - - update_lock_period_script(chain, lock_period); - block::set_block_info(1, start_time); - - let esinit = primary_fungible_store::withdraw(account, e_m, 500_000_000); - let stakelisted = primary_fungible_store::withdraw(account, s_m, 500_000_000); - - zapping( - account, - 1, - l_m, - option::none(), - val, - stage, - esinit, - stakelisted, - ); - - let validator_reward = 1_000_000; - staking::deposit_reward_for_chain( - chain, - l_m, - vector[val], - vector[validator_reward], - ); - let zapping_reward = get_delegation_info(0).unclaimed_reward; - assert!(validator_reward == zapping_reward, 0); - - batch_claim_reward_script(account, vector[0]); - assert!( - primary_fungible_store::balance( - signer::address_of(account), - vip_reward::reward_metadata(), - ) == zapping_reward, - 0, - ); - } - - #[test(chain = @0x1, user_a = @0x998, user_b = @0x999, relayer = @0x3d18d54532fc42e567090852db6eb21fa528f952)] - fun test_zapping_claim( - chain: &signer, - user_a: &signer, - user_b: &signer, - relayer: &signer, - ) acquires ModuleStore, LSStore { - let (e_m, s_m, l_m, val) = - test_setup_for_zapping( - chain, - user_a, - 1_000_000_000, - 1_000_000_000, - ); - - let esinit = coin::withdraw(user_a, e_m, 250_000_000); - coin::deposit(signer::address_of(user_b), esinit); - let stakelisted = coin::withdraw(user_a, s_m, 250_000_000); - coin::deposit(signer::address_of(user_b), stakelisted); - - let bridge_id = 1; - let (stage, lock_period, start_time) = (10, 3600, 1000000); - let release_time = start_time + lock_period; - - block::set_block_info(1, start_time); - update_lock_period_script(chain, lock_period); - let esinit = primary_fungible_store::withdraw(user_a, e_m, 500_000_000); - let stakelisted = primary_fungible_store::withdraw(user_a, s_m, 500_000_000); - - zapping( - user_a, - bridge_id, - l_m, - option::none(), - val, - stage, - esinit, - stakelisted, - ); - - let esinit = primary_fungible_store::withdraw(user_b, e_m, 250_000_000); - let stakelisted = primary_fungible_store::withdraw(user_b, s_m, 250_000_000); - - zapping( - user_b, - 1, - l_m, - option::none(), - val, - stage, - esinit, - stakelisted, - ); - - block::set_block_info(2, release_time + 1); - - assert!( - primary_fungible_store::balance( - signer::address_of(user_a), - vip_reward::reward_metadata(), - ) == 0, - 2, - ); - staking::fund_reward_coin( - chain, - signer::address_of(relayer), - 2_000_000, - ); - - let validator_reward = 1_000_000; - staking::deposit_reward_for_chain( - chain, - l_m, - vector[val], - vector[validator_reward], - ); - batch_claim_zapping_script(user_a, vector[0]); - assert!( - primary_fungible_store::balance( - signer::address_of(user_a), - vip_reward::reward_metadata(), - ) == (validator_reward * 2) / 3, - 3, - ); - } - - #[test(chain = @0x1, account = @0x2)] - #[expected_failure(abort_code = 0xD0002, location = Self)] - fun test_zapping_claim_not_released( - chain: &signer, account: &signer, - ) acquires ModuleStore, LSStore { - let (e_m, s_m, l_m, val) = - test_setup_for_zapping( - chain, - account, - 1_000_000_000, - 1_000_000_000, - ); - let (stage, start_time) = (10, 1000000); - - block::set_block_info(1, start_time); - let esinit = primary_fungible_store::withdraw(account, e_m, 500_000_000); - let stakelisted = primary_fungible_store::withdraw(account, s_m, 500_000_000); - let bridge_id = 1; - - zapping( - account, - bridge_id, - l_m, - option::none(), - val, - stage, - esinit, - stakelisted, - ); - - claim_zapping_script(account, 0); - } -} diff --git a/initia_stdlib/tests/deflation_token.move b/initia_stdlib/tests/deflation_token.move index 10588bc..2ff22d1 100644 --- a/initia_stdlib/tests/deflation_token.move +++ b/initia_stdlib/tests/deflation_token.move @@ -10,7 +10,7 @@ module 0xcafe::deflation_token { use std::string; struct BurnStore has key { - burn_ref: BurnRef, + burn_ref: BurnRef } public fun initialize( @@ -25,21 +25,19 @@ module 0xcafe::deflation_token { function_info::new_function_info( account, string::utf8(b"deflation_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); dispatchable_fungible_asset::register_dispatch_functions( constructor_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } public fun withdraw( - store: Object, - amount: u64, - transfer_ref: &TransferRef, + store: Object, amount: u64, transfer_ref: &TransferRef ): FungibleAsset acquires BurnStore { // For every withdraw, we burn 10% from the store. let burn_amount = amount / 10; @@ -58,8 +56,12 @@ module 0xcafe::deflation_token { use initia_std::fungible_asset::{Metadata, TestToken}; #[test(creator = @0xcafe)] - #[expected_failure(major_status = 4037, location = initia_std::dispatchable_fungible_asset)] - fun test_self_reentrancy(creator: &signer,) { + #[ + expected_failure( + major_status = 4037, location = initia_std::dispatchable_fungible_asset + ) + ] + fun test_self_reentrancy(creator: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); diff --git a/initia_stdlib/tests/deflation_token_tests.move b/initia_stdlib/tests/deflation_token_tests.move index 0917b7e..8a5621a 100644 --- a/initia_stdlib/tests/deflation_token_tests.move +++ b/initia_stdlib/tests/deflation_token_tests.move @@ -11,7 +11,7 @@ module 0xcafe::deflation_token_tests { use std::signer; #[test(creator = @0xcafe, aaron = @0xface)] - fun test_deflation_e2e_basic_flow(creator: &signer, aaron: &signer,) { + fun test_deflation_e2e_basic_flow(creator: &signer, aaron: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); @@ -56,9 +56,13 @@ module 0xcafe::deflation_token_tests { } #[test(creator = @0xcafe, aaron = @0xface)] - #[expected_failure(abort_code = 0x70002, location = initia_std::dispatchable_fungible_asset)] + #[ + expected_failure( + abort_code = 0x70002, location = initia_std::dispatchable_fungible_asset + ) + ] fun test_deflation_assert_min_deposit( - creator: &signer, aaron: &signer, + creator: &signer, aaron: &signer ) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); @@ -82,7 +86,7 @@ module 0xcafe::deflation_token_tests { #[test(creator = @0xcafe)] #[expected_failure(abort_code = 0x1001C, location = initia_std::fungible_asset)] - fun test_deflation_fa_deposit(creator: &signer,) { + fun test_deflation_fa_deposit(creator: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); @@ -104,7 +108,7 @@ module 0xcafe::deflation_token_tests { #[test(creator = @0xcafe, aaron = @0xface)] #[expected_failure(abort_code = 0x1001C, location = initia_std::fungible_asset)] - fun test_deflation_fa_withdraw(creator: &signer, aaron: &signer,) { + fun test_deflation_fa_withdraw(creator: &signer, aaron: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); @@ -128,7 +132,7 @@ module 0xcafe::deflation_token_tests { #[test(creator = @0xcafe, aaron = @0xface)] #[expected_failure(abort_code = 0x8001D, location = initia_std::fungible_asset)] - fun test_double_init(creator: &signer,) { + fun test_double_init(creator: &signer) { let (creator_ref, _) = fungible_asset::create_test_token(creator); let (_, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); deflation_token::initialize(creator, &creator_ref); @@ -137,7 +141,7 @@ module 0xcafe::deflation_token_tests { function_info::new_function_info( creator, string::utf8(b"deflation_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); // Re-registering the overload function should yield an error @@ -145,20 +149,20 @@ module 0xcafe::deflation_token_tests { &creator_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } #[test(creator = @0xcafe)] #[expected_failure(abort_code = 0x10019, location = initia_std::fungible_asset)] - fun test_register_bad_withdraw(creator: &signer,) { + fun test_register_bad_withdraw(creator: &signer) { let (creator_ref, _) = fungible_asset::create_test_token(creator); let withdraw = function_info::new_function_info( creator, string::utf8(b"deflation_token"), - string::utf8(b"initialize"), + string::utf8(b"initialize") ); // Change the deposit and withdraw function. Should give a type mismatch error. @@ -166,20 +170,20 @@ module 0xcafe::deflation_token_tests { &creator_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } #[test(creator = @0xcafe)] #[expected_failure(abort_code = 0x1001A, location = initia_std::fungible_asset)] - fun test_register_bad_deposit(creator: &signer,) { + fun test_register_bad_deposit(creator: &signer) { let (creator_ref, _) = fungible_asset::create_test_token(creator); let withdraw = function_info::new_function_info( creator, string::utf8(b"deflation_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); // Change the deposit and withdraw function. Should give a type mismatch error. @@ -187,20 +191,20 @@ module 0xcafe::deflation_token_tests { &creator_ref, option::some(withdraw), option::some(withdraw), - option::none(), + option::none() ); } #[test(creator = @0xcafe)] #[expected_failure(abort_code = 0x1001B, location = initia_std::fungible_asset)] - fun test_register_bad_value(creator: &signer,) { + fun test_register_bad_value(creator: &signer) { let (creator_ref, _) = fungible_asset::create_test_token(creator); let withdraw = function_info::new_function_info( creator, string::utf8(b"deflation_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); // Change the deposit and withdraw function. Should give a type mismatch error. @@ -208,14 +212,14 @@ module 0xcafe::deflation_token_tests { &creator_ref, option::some(withdraw), option::none(), - option::some(withdraw), + option::some(withdraw) ); } #[test(creator = @0xcafe, aaron = @0xface)] #[expected_failure(major_status = 1081, location = initia_std::function_info)] fun test_register_bad_withdraw_non_exist( - creator: &signer, aaron: &signer, + creator: &signer, aaron: &signer ) { let (creator_ref, _) = fungible_asset::create_test_token(creator); @@ -223,7 +227,7 @@ module 0xcafe::deflation_token_tests { function_info::new_function_info( aaron, string::utf8(b"deflation_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); // Change the deposit and withdraw function. Should give a type mismatch error. @@ -231,20 +235,20 @@ module 0xcafe::deflation_token_tests { &creator_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } #[test(creator = @0xcafe)] #[expected_failure(abort_code = 2, location = initia_std::function_info)] - fun test_register_bad_withdraw_non_exist_2(creator: &signer,) { + fun test_register_bad_withdraw_non_exist_2(creator: &signer) { let (creator_ref, _) = fungible_asset::create_test_token(creator); let withdraw = function_info::new_function_info( creator, string::utf8(b"deflation_token"), - string::utf8(b"withdraw2"), + string::utf8(b"withdraw2") ); // Change the deposit and withdraw function. Should give a type mismatch error. @@ -252,12 +256,12 @@ module 0xcafe::deflation_token_tests { &creator_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } #[test(creator = @0xcafe)] - fun test_calling_overloadable_api_on_regular_fa(creator: &signer,) { + fun test_calling_overloadable_api_on_regular_fa(creator: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); @@ -274,13 +278,13 @@ module 0xcafe::deflation_token_tests { #[test(creator = @0xcafe)] #[expected_failure(abort_code = 0x6001E, location = initia_std::fungible_asset)] - fun test_register_on_non_metadata_object(creator: &signer,) { + fun test_register_on_non_metadata_object(creator: &signer) { let creator_ref = object::create_named_object(creator, b"TEST"); let withdraw = function_info::new_function_info( creator, string::utf8(b"deflation_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); // Change the deposit and withdraw function. Should give a type mismatch error. @@ -288,12 +292,12 @@ module 0xcafe::deflation_token_tests { &creator_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } #[test(creator = @0xcafe, aaron = @0xface)] - fun test_basic_flow_primary_fa(creator: &signer, aaron: &signer,) { + fun test_basic_flow_primary_fa(creator: &signer, aaron: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint_ref, transfer_ref, burn_ref) = primary_fungible_store::init_test_metadata_with_primary_store_enabled( @@ -343,7 +347,7 @@ module 0xcafe::deflation_token_tests { #[test(creator = @0xcafe, aaron = @0xface)] #[expected_failure(abort_code = 0x50003, location = initia_std::fungible_asset)] - fun test_deflation_set_frozen(creator: &signer, aaron: &signer,) { + fun test_deflation_set_frozen(creator: &signer, aaron: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, transfer_ref, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); @@ -375,7 +379,7 @@ module 0xcafe::deflation_token_tests { #[test(creator = @0xcafe, aaron = @0xface)] #[expected_failure(abort_code = 0x50008, location = initia_std::fungible_asset)] - fun test_deflation_wrong_withdraw(creator: &signer, aaron: &signer,) { + fun test_deflation_wrong_withdraw(creator: &signer, aaron: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); diff --git a/initia_stdlib/tests/nil_op_token.move b/initia_stdlib/tests/nil_op_token.move index 1cea956..f261110 100644 --- a/initia_stdlib/tests/nil_op_token.move +++ b/initia_stdlib/tests/nil_op_token.move @@ -17,21 +17,19 @@ module 0xcafe::nil_op_token { function_info::new_function_info( account, string::utf8(b"nil_op_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); dispatchable_fungible_asset::register_dispatch_functions( constructor_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } public fun withdraw( - store: Object, - _amount: u64, - transfer_ref: &TransferRef, + store: Object, _amount: u64, transfer_ref: &TransferRef ): FungibleAsset { // Always return a one FA. fungible_asset::withdraw_with_ref(transfer_ref, store, 1) diff --git a/initia_stdlib/tests/nil_op_token_tests.move b/initia_stdlib/tests/nil_op_token_tests.move index 72d4c4f..d88d55b 100644 --- a/initia_stdlib/tests/nil_op_token_tests.move +++ b/initia_stdlib/tests/nil_op_token_tests.move @@ -7,8 +7,12 @@ module initia_std::nil_op_token_tests { use std::option; #[test(creator = @0xcafe)] - #[expected_failure(abort_code = 0x70002, location = initia_std::dispatchable_fungible_asset)] - fun test_nil_op_token(creator: &signer,) { + #[ + expected_failure( + abort_code = 0x70002, location = initia_std::dispatchable_fungible_asset + ) + ] + fun test_nil_op_token(creator: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); diff --git a/initia_stdlib/tests/permissioned_token.move b/initia_stdlib/tests/permissioned_token.move index c134ead..adc9d6e 100644 --- a/initia_stdlib/tests/permissioned_token.move +++ b/initia_stdlib/tests/permissioned_token.move @@ -14,7 +14,7 @@ module 0xcafe::permissioned_token { const EWITHDRAW_NOT_ALLOWED: u64 = 1; struct AllowlistStore has key { - allowed_sender: vector
, + allowed_sender: vector
} public fun initialize( @@ -27,14 +27,14 @@ module 0xcafe::permissioned_token { function_info::new_function_info( account, string::utf8(b"permissioned_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); dispatchable_fungible_asset::register_dispatch_functions( constructor_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } @@ -47,16 +47,14 @@ module 0xcafe::permissioned_token { } public fun withdraw( - store: Object, - amount: u64, - transfer_ref: &TransferRef, + store: Object, amount: u64, transfer_ref: &TransferRef ): FungibleAsset acquires AllowlistStore { assert!( vector::contains( &borrow_global(@0xcafe).allowed_sender, - &object::object_address(&store), + &object::object_address(&store) ), - EWITHDRAW_NOT_ALLOWED, + EWITHDRAW_NOT_ALLOWED ); fungible_asset::withdraw_with_ref(transfer_ref, store, amount) diff --git a/initia_stdlib/tests/permissioned_token_tests.move b/initia_stdlib/tests/permissioned_token_tests.move index 257cd62..5edd7c7 100644 --- a/initia_stdlib/tests/permissioned_token_tests.move +++ b/initia_stdlib/tests/permissioned_token_tests.move @@ -8,7 +8,7 @@ module 0xcafe::permissioned_token_tests { #[test(creator = @0xcafe, aaron = @0xface)] fun test_permissioned_e2e_basic_flow( - creator: &signer, aaron: &signer, + creator: &signer, aaron: &signer ) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); @@ -18,7 +18,8 @@ module 0xcafe::permissioned_token_tests { let aaron_store = fungible_asset::create_test_store(aaron, metadata); let allowed_sender = vector[ object::object_address(&creator_store), - object::object_address(&aaron_store),]; + object::object_address(&aaron_store) + ]; permissioned_token::initialize(creator, &creator_ref, allowed_sender); @@ -41,7 +42,7 @@ module 0xcafe::permissioned_token_tests { #[test(creator = @0xcafe, aaron = @0xface)] #[expected_failure(abort_code = 1, location = 0xcafe::permissioned_token)] fun test_permissioned_disallowed_sender( - creator: &signer, aaron: &signer, + creator: &signer, aaron: &signer ) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); @@ -49,7 +50,7 @@ module 0xcafe::permissioned_token_tests { let creator_store = fungible_asset::create_test_store(creator, metadata); let aaron_store = fungible_asset::create_test_store(aaron, metadata); - let allowed_sender = vector[object::object_address(&creator_store),]; + let allowed_sender = vector[object::object_address(&creator_store)]; permissioned_token::initialize(creator, &creator_ref, allowed_sender); @@ -72,7 +73,7 @@ module 0xcafe::permissioned_token_tests { #[test(creator = @0xcafe, aaron = @0xface)] fun test_permissioned_update_disallowed_sender( - creator: &signer, aaron: &signer, + creator: &signer, aaron: &signer ) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); @@ -80,7 +81,7 @@ module 0xcafe::permissioned_token_tests { let creator_store = fungible_asset::create_test_store(creator, metadata); let aaron_store = fungible_asset::create_test_store(aaron, metadata); - let allowed_sender = vector[object::object_address(&creator_store),]; + let allowed_sender = vector[object::object_address(&creator_store)]; permissioned_token::initialize(creator, &creator_ref, allowed_sender); diff --git a/initia_stdlib/tests/reentrant_token.move b/initia_stdlib/tests/reentrant_token.move index cf3dd9f..9a5734d 100644 --- a/initia_stdlib/tests/reentrant_token.move +++ b/initia_stdlib/tests/reentrant_token.move @@ -17,21 +17,19 @@ module 0xcafe::reentrant_token { function_info::new_function_info( account, string::utf8(b"reentrant_token"), - string::utf8(b"deposit"), + string::utf8(b"deposit") ); dispatchable_fungible_asset::register_dispatch_functions( constructor_ref, option::none(), option::some(deposit), - option::none(), + option::none() ); } public fun deposit( - store: Object, - fa: FungibleAsset, - _transfer_ref: &TransferRef, + store: Object, fa: FungibleAsset, _transfer_ref: &TransferRef ) { // Re-entering into dispatchable_fungible_asset. Will be rejected by the MoveVM runtime. dispatchable_fungible_asset::deposit(store, fa); diff --git a/initia_stdlib/tests/reentrant_token_tests.move b/initia_stdlib/tests/reentrant_token_tests.move index 3775848..577627a 100644 --- a/initia_stdlib/tests/reentrant_token_tests.move +++ b/initia_stdlib/tests/reentrant_token_tests.move @@ -7,8 +7,12 @@ module 0xcafe::reentrant_token_tests { use std::option; #[test(creator = @0xcafe)] - #[expected_failure(major_status = 4037, location = initia_std::dispatchable_fungible_asset)] - fun test_reentrant_deposit(creator: &signer,) { + #[ + expected_failure( + major_status = 4037, location = initia_std::dispatchable_fungible_asset + ) + ] + fun test_reentrant_deposit(creator: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); diff --git a/initia_stdlib/tests/simple_dispatchable_token.move b/initia_stdlib/tests/simple_dispatchable_token.move index a4420ae..0791a74 100644 --- a/initia_stdlib/tests/simple_dispatchable_token.move +++ b/initia_stdlib/tests/simple_dispatchable_token.move @@ -18,36 +18,32 @@ module 0xcafe::simple_token { function_info::new_function_info( account, string::utf8(b"simple_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); let deposit = function_info::new_function_info( account, string::utf8(b"simple_token"), - string::utf8(b"deposit"), + string::utf8(b"deposit") ); dispatchable_fungible_asset::register_dispatch_functions( constructor_ref, option::some(withdraw), option::some(deposit), - option::none(), + option::none() ); } public fun withdraw( - store: Object, - amount: u64, - transfer_ref: &TransferRef, + store: Object, amount: u64, transfer_ref: &TransferRef ): FungibleAsset { fungible_asset::withdraw_with_ref(transfer_ref, store, amount) } public fun deposit( - store: Object, - fa: FungibleAsset, - transfer_ref: &TransferRef, + store: Object, fa: FungibleAsset, transfer_ref: &TransferRef ) { fungible_asset::deposit_with_ref(transfer_ref, store, fa) } diff --git a/initia_stdlib/tests/simple_dispatchable_token_fa_tests.move b/initia_stdlib/tests/simple_dispatchable_token_fa_tests.move index 07642c5..47e7900 100644 --- a/initia_stdlib/tests/simple_dispatchable_token_fa_tests.move +++ b/initia_stdlib/tests/simple_dispatchable_token_fa_tests.move @@ -38,7 +38,7 @@ module initia_std::simple_token_fa_tests { } #[test(creator = @0xcafe, aaron = @0xface)] - fun test_transfer_with_ref(creator: &signer, aaron: &signer,) { + fun test_transfer_with_ref(creator: &signer, aaron: &signer) { let (creator_ref, test_token) = create_test_token(creator); let (mint_ref, transfer_ref, _burn_ref, _mutate_metadata_ref) = init_test_metadata(&creator_ref); diff --git a/initia_stdlib/tests/simple_dispatchable_token_pfs_tests.move b/initia_stdlib/tests/simple_dispatchable_token_pfs_tests.move index e489efe..9cc836c 100644 --- a/initia_stdlib/tests/simple_dispatchable_token_pfs_tests.move +++ b/initia_stdlib/tests/simple_dispatchable_token_pfs_tests.move @@ -16,7 +16,7 @@ module initia_std::simple_token_pfs_tests { deposit_with_ref, withdraw_with_ref, primary_store_exists, - ensure_primary_store_exists, + ensure_primary_store_exists }; use 0xcafe::simple_token; use std::signer; @@ -42,7 +42,7 @@ module initia_std::simple_token_pfs_tests { } #[test(creator = @0xcafe, aaron = @0xface)] - fun test_basic_flow(creator: &signer, aaron: &signer,) { + fun test_basic_flow(creator: &signer, aaron: &signer) { let (creator_ref, metadata) = create_test_token(creator); let (mint_ref, transfer_ref, burn_ref) = init_test_metadata_with_primary_store_enabled(&creator_ref); @@ -71,7 +71,7 @@ module initia_std::simple_token_pfs_tests { #[test(creator = @0xcafe, aaron = @0xface)] fun test_basic_flow_with_min_balance( - creator: &signer, aaron: &signer, + creator: &signer, aaron: &signer ) { let (creator_ref, metadata) = create_test_token(creator); let (mint_ref, _transfer_ref, _) = diff --git a/initia_stdlib/tests/ten_x_token.move b/initia_stdlib/tests/ten_x_token.move index a22d99c..cba1c88 100644 --- a/initia_stdlib/tests/ten_x_token.move +++ b/initia_stdlib/tests/ten_x_token.move @@ -18,19 +18,19 @@ module 0xcafe::ten_x_token { function_info::new_function_info( account, string::utf8(b"ten_x_token"), - string::utf8(b"derived_balance"), + string::utf8(b"derived_balance") ); let supply_value = function_info::new_function_info( account, string::utf8(b"ten_x_token"), - string::utf8(b"derived_supply"), + string::utf8(b"derived_supply") ); dispatchable_fungible_asset::register_dispatch_functions( constructor_ref, option::none(), option::none(), - option::some(balance_value), + option::some(balance_value) ); dispatchable_fungible_asset::register_derive_supply_dispatch_function( constructor_ref, option::some(supply_value) diff --git a/initia_stdlib/tests/ten_x_token_tests.move b/initia_stdlib/tests/ten_x_token_tests.move index c4c3e2a..329f984 100644 --- a/initia_stdlib/tests/ten_x_token_tests.move +++ b/initia_stdlib/tests/ten_x_token_tests.move @@ -7,7 +7,7 @@ module initia_std::ten_x_token_tests { use std::option; #[test(creator = @0xcafe)] - fun test_ten_x(creator: &signer,) { + fun test_ten_x(creator: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); diff --git a/minitia_stdlib/doc/account.md b/minitia_stdlib/doc/account.md index 5f23719..43802ef 100644 --- a/minitia_stdlib/doc/account.md +++ b/minitia_stdlib/doc/account.md @@ -5,20 +5,29 @@ +- [Struct `AccountInfo`](#0x1_account_AccountInfo) - [Constants](#@Constants_0) - [Function `create_account_script`](#0x1_account_create_account_script) - [Function `create_account`](#0x1_account_create_account) - [Function `create_table_account`](#0x1_account_create_table_account) - [Function `create_object_account`](#0x1_account_create_object_account) - [Function `exists_at`](#0x1_account_exists_at) +- [Function `is_blocked`](#0x1_account_is_blocked) - [Function `get_account_number`](#0x1_account_get_account_number) - [Function `get_sequence_number`](#0x1_account_get_sequence_number) - [Function `is_base_account`](#0x1_account_is_base_account) - [Function `is_object_account`](#0x1_account_is_object_account) - [Function `is_table_account`](#0x1_account_is_table_account) - [Function `is_module_account`](#0x1_account_is_module_account) -- [Function `request_create_account`](#0x1_account_request_create_account) - [Function `get_account_info`](#0x1_account_get_account_info) +- [Function `is_module_account_with_info`](#0x1_account_is_module_account_with_info) +- [Function `is_base_account_with_info`](#0x1_account_is_base_account_with_info) +- [Function `is_object_account_with_info`](#0x1_account_is_object_account_with_info) +- [Function `is_table_account_with_info`](#0x1_account_is_table_account_with_info) +- [Function `is_blocked_with_info`](#0x1_account_is_blocked_with_info) +- [Function `get_account_number_with_info`](#0x1_account_get_account_number_with_info) +- [Function `get_sequence_number_with_info`](#0x1_account_get_sequence_number_with_info) +- [Function `account_info`](#0x1_account_account_info) - [Function `create_address`](#0x1_account_create_address) - [Function `create_signer`](#0x1_account_create_signer) @@ -28,6 +37,48 @@ + + +## Struct `AccountInfo` + + + +
struct AccountInfo has copy, drop
+
+ + + +##### Fields + + +
+
+account_number: u64 +
+
+ +
+
+sequence_number: u64 +
+
+ +
+
+account_type: u8 +
+
+ +
+
+is_blocked: bool +
+
+ +
+
+ + ## Constants @@ -100,8 +151,7 @@ This error type is used in native function. -
-Implementation +##### Implementation
public entry fun create_account_script(addr: address) {
@@ -111,8 +161,6 @@ This error type is used in native function.
 
 
 
-
- ## Function `create_account` @@ -124,22 +172,22 @@ This error type is used in native function. -
-Implementation +##### Implementation
public fun create_account(addr: address): u64 {
-    let (found, _, _, _) = get_account_info(addr);
-    assert!(!found, error::already_exists(EACCOUNT_ALREADY_EXISTS));
+    let (found, _, _, _, _) = account_info(addr);
+    assert!(
+        !found,
+        error::already_exists(EACCOUNT_ALREADY_EXISTS)
+    );
 
-    request_create_account(addr, ACCOUNT_TYPE_BASE)
+    request_create_account(addr, 0, ACCOUNT_TYPE_BASE)
 }
 
-
- ## Function `create_table_account` @@ -153,22 +201,26 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public(friend) fun create_table_account(addr: address): u64 {
-    let (found, _, _, _) = get_account_info(addr);
-    assert!(!found, error::already_exists(EACCOUNT_ALREADY_EXISTS));
-
-    request_create_account(addr, ACCOUNT_TYPE_TABLE)
+    let (found, account_number, sequence, account_type, _) = account_info(addr);
+    assert!(
+        !found || (account_type == ACCOUNT_TYPE_BASE && sequence == 0),
+        error::already_exists(EACCOUNT_ALREADY_EXISTS)
+    );
+
+    request_create_account(
+        addr,
+        account_number,
+        ACCOUNT_TYPE_TABLE
+    )
 }
 
-
- ## Function `create_object_account` @@ -182,13 +234,20 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public(friend) fun create_object_account(addr: address): u64 {
-    let (found, account_number, _, account_type) = get_account_info(addr);
-    if (found) {
+    let (found, account_number, sequence, account_type, _) = account_info(addr);
+
+    // base account with sequence 0 is considered as not created.
+    if (!found || (account_type == ACCOUNT_TYPE_BASE && sequence == 0)) {
+        request_create_account(
+            addr,
+            account_number,
+            ACCOUNT_TYPE_OBJECT
+        )
+    } else {
         // When an Object is deleted, the ObjectAccount in CosmosSDK is designed
         // not to be deleted in order to prevent unexpected issues. Therefore,
         // in this case, the creation of an account is omitted.
@@ -199,16 +258,12 @@ as both cannot have a pubkey, there is no way to use the account externally.
         } else {
             abort(error::already_exists(EACCOUNT_ALREADY_EXISTS))
         }
-    } else {
-        request_create_account(addr, ACCOUNT_TYPE_OBJECT)
     }
 }
 
-
- ## Function `exists_at` @@ -221,19 +276,39 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public fun exists_at(addr: address): bool {
-    let (found, _, _, _) = get_account_info(addr);
+    let (found, _, _, _, _) = account_info(addr);
     found
 }
 
-
+ + +## Function `is_blocked` + + + +
#[view]
+public fun is_blocked(addr: address): bool
+
+ + + +##### Implementation + + +
public fun is_blocked(addr: address): bool {
+    let (_, _, _, _, blocked) = account_info(addr);
+    blocked
+}
+
+ + @@ -247,12 +322,11 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public fun get_account_number(addr: address): u64 {
-    let (found, account_number, _, _) = get_account_info(addr);
+    let (found, account_number, _, _, _) = account_info(addr);
     assert!(found, error::not_found(EACCOUNT_NOT_FOUND));
 
     account_number
@@ -261,8 +335,6 @@ as both cannot have a pubkey, there is no way to use the account externally.
 
 
 
-
- ## Function `get_sequence_number` @@ -275,12 +347,11 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public fun get_sequence_number(addr: address): u64 {
-    let (found, _, sequence_number, _) = get_account_info(addr);
+    let (found, _, sequence_number, _, _) = account_info(addr);
     assert!(found, error::not_found(EACCOUNT_NOT_FOUND));
 
     sequence_number
@@ -289,8 +360,6 @@ as both cannot have a pubkey, there is no way to use the account externally.
 
 
 
-
- ## Function `is_base_account` @@ -303,12 +372,11 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public fun is_base_account(addr: address): bool {
-    let (found, _, _, account_type) = get_account_info(addr);
+    let (found, _, _, account_type, _) = account_info(addr);
     assert!(found, error::not_found(EACCOUNT_NOT_FOUND));
 
     account_type == ACCOUNT_TYPE_BASE
@@ -317,8 +385,6 @@ as both cannot have a pubkey, there is no way to use the account externally.
 
 
 
-
- ## Function `is_object_account` @@ -331,12 +397,11 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public fun is_object_account(addr: address): bool {
-    let (found, _, _, account_type) = get_account_info(addr);
+    let (found, _, _, account_type, _) = account_info(addr);
     assert!(found, error::not_found(EACCOUNT_NOT_FOUND));
 
     account_type == ACCOUNT_TYPE_OBJECT
@@ -345,8 +410,6 @@ as both cannot have a pubkey, there is no way to use the account externally.
 
 
 
-
- ## Function `is_table_account` @@ -359,12 +422,11 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public fun is_table_account(addr: address): bool {
-    let (found, _, _, account_type) = get_account_info(addr);
+    let (found, _, _, account_type, _) = account_info(addr);
     assert!(found, error::not_found(EACCOUNT_NOT_FOUND));
 
     account_type == ACCOUNT_TYPE_TABLE
@@ -373,8 +435,6 @@ as both cannot have a pubkey, there is no way to use the account externally.
 
 
 
-
- ## Function `is_module_account` @@ -387,12 +447,11 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
public fun is_module_account(addr: address): bool {
-    let (found, _, _, account_type) = get_account_info(addr);
+    let (found, _, _, account_type, _) = account_info(addr);
     assert!(found, error::not_found(EACCOUNT_NOT_FOUND));
 
     account_type == ACCOUNT_TYPE_MODULE
@@ -401,51 +460,203 @@ as both cannot have a pubkey, there is no way to use the account externally.
 
 
 
-
+ + +## Function `get_account_info` + + + +
#[view]
+public fun get_account_info(addr: address): (bool, account::AccountInfo)
+
+ - -## Function `request_create_account` +##### Implementation +
public fun get_account_info(addr: address): (bool, AccountInfo) {
+    let (found, account_number, sequence_number, account_type, is_blocked) =
+        account_info(addr);
 
-
fun request_create_account(addr: address, account_type: u8): u64
+    (found, AccountInfo { account_number, sequence_number, account_type, is_blocked })
+}
 
-
-Implementation + + +## Function `is_module_account_with_info` -
native fun request_create_account(addr: address, account_type: u8): u64;
+
+
public fun is_module_account_with_info(info: &account::AccountInfo): bool
 
-
+##### Implementation - -## Function `get_account_info` +
public fun is_module_account_with_info(info: &AccountInfo): bool {
+    info.account_type == ACCOUNT_TYPE_MODULE
+}
+
+ + + + + +## Function `is_base_account_with_info` + + + +
public fun is_base_account_with_info(info: &account::AccountInfo): bool
+
+ + + +##### Implementation + + +
public fun is_base_account_with_info(info: &AccountInfo): bool {
+    info.account_type == ACCOUNT_TYPE_BASE
+}
+
+ + + + + +## Function `is_object_account_with_info` -
public fun get_account_info(addr: address): (bool, u64, u64, u8)
+
public fun is_object_account_with_info(info: &account::AccountInfo): bool
 
-
-Implementation +##### Implementation -
native public fun get_account_info(addr: address): (bool /* found */, u64 /* account_number */, u64 /* sequence_number */, u8 /* account_type */);
+
public fun is_object_account_with_info(info: &AccountInfo): bool {
+    info.account_type == ACCOUNT_TYPE_OBJECT
+}
+
+ + + + + +## Function `is_table_account_with_info` + + + +
public fun is_table_account_with_info(info: &account::AccountInfo): bool
+
+ + + +##### Implementation + + +
public fun is_table_account_with_info(info: &AccountInfo): bool {
+    info.account_type == ACCOUNT_TYPE_TABLE
+}
+
+ + + + + +## Function `is_blocked_with_info` + + + +
public fun is_blocked_with_info(info: &account::AccountInfo): bool
+
+ + + +##### Implementation + + +
public fun is_blocked_with_info(info: &AccountInfo): bool {
+    info.is_blocked
+}
+
+ + + + + +## Function `get_account_number_with_info` + + + +
public fun get_account_number_with_info(info: &account::AccountInfo): u64
 
-
+##### Implementation + + +
public fun get_account_number_with_info(info: &AccountInfo): u64 {
+    info.account_number
+}
+
+ + + + + +## Function `get_sequence_number_with_info` + + + +
public fun get_sequence_number_with_info(info: &account::AccountInfo): u64
+
+ + + +##### Implementation + + +
public fun get_sequence_number_with_info(info: &AccountInfo): u64 {
+    info.sequence_number
+}
+
+ + + + + +## Function `account_info` + + + +
public fun account_info(addr: address): (bool, u64, u64, u8, bool)
+
+ + + +##### Implementation + + +
native public fun account_info(addr: address):
+    (
+    bool /* found */,
+    u64 /* account_number */,
+    u64 /* sequence_number */,
+    u8 /* account_type */,
+    bool /* is_blocked */
+);
+
+ + @@ -458,8 +669,7 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
native public(friend) fun create_address(bytes: vector<u8>): address;
@@ -467,8 +677,6 @@ as both cannot have a pubkey, there is no way to use the account externally.
 
 
 
-
- ## Function `create_signer` @@ -480,13 +688,8 @@ as both cannot have a pubkey, there is no way to use the account externally. -
-Implementation +##### Implementation
native public(friend) fun create_signer(addr: address): signer;
 
- - - -
diff --git a/minitia_stdlib/doc/address.md b/minitia_stdlib/doc/address.md index da7f19c..36be855 100644 --- a/minitia_stdlib/doc/address.md +++ b/minitia_stdlib/doc/address.md @@ -5,94 +5,180 @@ +- [Struct `FromSdkRequest`](#0x1_address_FromSdkRequest) +- [Struct `FromSdkResponse`](#0x1_address_FromSdkResponse) +- [Struct `ToSdkRequest`](#0x1_address_ToSdkRequest) +- [Struct `ToSdkResponse`](#0x1_address_ToSdkResponse) - [Function `from_sdk`](#0x1_address_from_sdk) - [Function `to_sdk`](#0x1_address_to_sdk) - [Function `to_string`](#0x1_address_to_string) - [Function `from_string`](#0x1_address_from_string) +- [Function `to_bytes`](#0x1_address_to_bytes) +- [Function `from_bytes`](#0x1_address_from_bytes) -
use 0x1::json;
-use 0x1::option;
+
use 0x1::bcs;
+use 0x1::from_bcs;
+use 0x1::json;
 use 0x1::query;
-use 0x1::simple_json;
 use 0x1::string;
 
- + -## Function `from_sdk` +## Struct `FromSdkRequest` -
public fun from_sdk(sdk_addr: string::String): address
+
struct FromSdkRequest has copy, drop
 
-
-Implementation +##### Fields -
public fun from_sdk(sdk_addr: String): address {
-    let obj = simple_json::empty();
-    simple_json::set_object(&mut obj, option::none<String>());
-    simple_json::increase_depth(&mut obj);
+
+
+sdk_addr: string::String +
+
- simple_json::set_string(&mut obj, option::some(string::utf8(b"sdk_addr")), sdk_addr); +
+
- let req = json::stringify(simple_json::to_json_object(&obj)); - let res = query::query_custom(b"from_sdk_address", *string::bytes(&req)); - let res = simple_json::from_json_object(json::parse(string::utf8(res))); - simple_json::increase_depth(&mut res); - let (_, data) = json::unpack_elem(simple_json::borrow(&mut res)); + - from_string(json::as_string(data)) -} +## Struct `FromSdkResponse` + + + +
struct FromSdkResponse has copy, drop
 
-
+##### Fields - -## Function `to_sdk` +
+
+vm_addr: address +
+
+
+
-
public fun to_sdk(vm_addr: address): string::String
+
+
+## Struct `ToSdkRequest`
+
+
+
+
struct ToSdkRequest has copy, drop
 
-
-Implementation +##### Fields + + +
+
+vm_addr: address +
+
+ +
+
+ + + + +## Struct `ToSdkResponse` -
public fun to_sdk(vm_addr: address): String {
-    let obj = simple_json::empty();
-    simple_json::set_object(&mut obj, option::none<String>());
-    simple_json::increase_depth(&mut obj);
 
-    simple_json::set_string(&mut obj, option::some(string::utf8(b"vm_addr")), to_string(vm_addr));
+
struct ToSdkResponse has copy, drop
+
+ + + +##### Fields + + +
+
+sdk_addr: string::String +
+
+ +
+
+ + + + +## Function `from_sdk` + + + +
public fun from_sdk(sdk_addr: string::String): address
+
- let req = json::stringify(simple_json::to_json_object(&obj)); - let res = query::query_custom(b"to_sdk_address", *string::bytes(&req)); - let res = simple_json::from_json_object(json::parse(string::utf8(res))); - simple_json::increase_depth(&mut res); - let (_, data) = json::unpack_elem(simple_json::borrow(&mut res)); - json::as_string(data) +##### Implementation + + +
public fun from_sdk(sdk_addr: String): address {
+    let res =
+        json::unmarshal<FromSdkResponse>(
+            query::query_custom(
+                b"from_sdk_address",
+                json::marshal(&FromSdkRequest { sdk_addr: sdk_addr })
+            )
+        );
+
+    res.vm_addr
 }
 
-
+ + +## Function `to_sdk` + + + +
public fun to_sdk(vm_addr: address): string::String
+
+ + + +##### Implementation + + +
public fun to_sdk(vm_addr: address): String {
+    let res =
+        json::unmarshal<ToSdkResponse>(
+            query::query_custom(
+                b"to_sdk_address",
+                json::marshal(&ToSdkRequest { vm_addr: vm_addr })
+            )
+        );
+
+    res.sdk_addr
+}
+
+ + @@ -105,17 +191,14 @@ -
-Implementation +##### Implementation -
public native fun to_string(addr: address): String;
+
native public fun to_string(addr: address): String;
 
-
- ## Function `from_string` @@ -127,13 +210,50 @@ -
-Implementation +##### Implementation + + +
native public fun from_string(addr_str: String): address;
+
+ + + + + +## Function `to_bytes` + + + +
public fun to_bytes(addr: address): vector<u8>
+
+ + + +##### Implementation + + +
public fun to_bytes(addr: address): vector<u8> {
+    bcs::to_bytes(&addr)
+}
+
+ + + + + +## Function `from_bytes` -
public native fun from_string(addr_str: String): address;
+
+
public fun from_bytes(bytes: vector<u8>): address
 
-
+##### Implementation + + +
public fun from_bytes(bytes: vector<u8>): address {
+    from_bcs::to_address(bytes)
+}
+
diff --git a/minitia_stdlib/doc/any.md b/minitia_stdlib/doc/any.md index 635cf3b..5c68c68 100644 --- a/minitia_stdlib/doc/any.md +++ b/minitia_stdlib/doc/any.md @@ -43,8 +43,7 @@ extension: Option -
-Fields +##### Fields
@@ -63,8 +62,6 @@ extension: Option
-
- ## Constants @@ -93,8 +90,7 @@ also required from T. -
-Implementation +##### Implementation
public fun pack<T: drop + store>(x: T): Any {
@@ -107,8 +103,6 @@ also required from T.
 
 
 
-
- ## Function `unpack` @@ -121,20 +115,20 @@ Unpack a value from the Any repres -
-Implementation +##### Implementation
public fun unpack<T>(x: Any): T {
-    assert!(type_info::type_name<T>() == x.type_name, error::invalid_argument(ETYPE_MISMATCH));
+    assert!(
+        type_info::type_name<T>() == x.type_name,
+        error::invalid_argument(ETYPE_MISMATCH)
+    );
     from_bytes<T>(x.data)
 }
 
-
- ## Function `type_name` @@ -147,15 +141,10 @@ Returns the type name of this Any -
-Implementation +##### Implementation
public fun type_name(x: &Any): &String {
     &x.type_name
 }
 
- - - -
diff --git a/minitia_stdlib/doc/aptos_hash.md b/minitia_stdlib/doc/aptos_hash.md new file mode 100644 index 0000000..e1de452 --- /dev/null +++ b/minitia_stdlib/doc/aptos_hash.md @@ -0,0 +1,79 @@ + + + +# Module `0x1::aptos_hash` + +AptosHash module exists to provide compatibility with aptos. + + +- [Function `sha2_256`](#0x1_aptos_hash_sha2_256) +- [Function `sha3_256`](#0x1_aptos_hash_sha3_256) +- [Function `keccak256`](#0x1_aptos_hash_keccak256) + + +
use 0x1::hash;
+use 0x1::keccak;
+
+ + + + + +## Function `sha2_256` + + + +
public fun sha2_256(data: vector<u8>): vector<u8>
+
+ + + +##### Implementation + + +
public fun sha2_256(data: vector<u8>): vector<u8> {
+    s2_256(data)
+}
+
+ + + + + +## Function `sha3_256` + + + +
public fun sha3_256(data: vector<u8>): vector<u8>
+
+ + + +##### Implementation + + +
public fun sha3_256(data: vector<u8>): vector<u8> {
+    s3_256(data)
+}
+
+ + + + + +## Function `keccak256` + + + +
public fun keccak256(data: vector<u8>): vector<u8>
+
+ + + +##### Implementation + + +
public fun keccak256(data: vector<u8>): vector<u8> {
+    k256(data)
+}
+
diff --git a/minitia_stdlib/doc/base64.md b/minitia_stdlib/doc/base64.md index bb9ad92..f81b263 100644 --- a/minitia_stdlib/doc/base64.md +++ b/minitia_stdlib/doc/base64.md @@ -27,8 +27,7 @@ -
-Implementation +##### Implementation
public fun to_string(bytes: vector<u8>): String {
@@ -38,8 +37,6 @@
 
 
 
-
- ## Function `from_string` @@ -51,8 +48,7 @@ -
-Implementation +##### Implementation
public fun from_string(str: String): vector<u8> {
@@ -62,8 +58,6 @@
 
 
 
-
- ## Function `encode` @@ -75,17 +69,14 @@ -
-Implementation +##### Implementation -
public native fun encode(bytes: vector<u8>): vector<u8>;
+
native public fun encode(bytes: vector<u8>): vector<u8>;
 
-
- ## Function `decode` @@ -97,13 +88,8 @@ -
-Implementation +##### Implementation -
public native fun decode(bytes: vector<u8>): vector<u8>;
+
native public fun decode(bytes: vector<u8>): vector<u8>;
 
- - - -
diff --git a/minitia_stdlib/doc/bigdecimal.md b/minitia_stdlib/doc/bigdecimal.md new file mode 100644 index 0000000..1c35a5e --- /dev/null +++ b/minitia_stdlib/doc/bigdecimal.md @@ -0,0 +1,1424 @@ + + + +# Module `0x1::bigdecimal` + + + +- [Struct `BigDecimal`](#0x1_bigdecimal_BigDecimal) +- [Constants](#@Constants_0) +- [Function `from_u64`](#0x1_bigdecimal_from_u64) +- [Function `from_u128`](#0x1_bigdecimal_from_u128) +- [Function `from_u256`](#0x1_bigdecimal_from_u256) +- [Function `new`](#0x1_bigdecimal_new) +- [Function `from_scaled`](#0x1_bigdecimal_from_scaled) +- [Function `get_scaled`](#0x1_bigdecimal_get_scaled) +- [Function `from_scaled_le_bytes`](#0x1_bigdecimal_from_scaled_le_bytes) +- [Function `get_scaled_le_bytes`](#0x1_bigdecimal_get_scaled_le_bytes) +- [Function `from_ratio`](#0x1_bigdecimal_from_ratio) +- [Function `from_ratio_u64`](#0x1_bigdecimal_from_ratio_u64) +- [Function `from_ratio_u128`](#0x1_bigdecimal_from_ratio_u128) +- [Function `from_ratio_u256`](#0x1_bigdecimal_from_ratio_u256) +- [Function `rev`](#0x1_bigdecimal_rev) +- [Function `one`](#0x1_bigdecimal_one) +- [Function `zero`](#0x1_bigdecimal_zero) +- [Function `eq`](#0x1_bigdecimal_eq) +- [Function `lt`](#0x1_bigdecimal_lt) +- [Function `le`](#0x1_bigdecimal_le) +- [Function `gt`](#0x1_bigdecimal_gt) +- [Function `ge`](#0x1_bigdecimal_ge) +- [Function `is_zero`](#0x1_bigdecimal_is_zero) +- [Function `is_one`](#0x1_bigdecimal_is_one) +- [Function `add`](#0x1_bigdecimal_add) +- [Function `add_by_u64`](#0x1_bigdecimal_add_by_u64) +- [Function `add_by_u128`](#0x1_bigdecimal_add_by_u128) +- [Function `add_by_u256`](#0x1_bigdecimal_add_by_u256) +- [Function `sub`](#0x1_bigdecimal_sub) +- [Function `sub_by_u64`](#0x1_bigdecimal_sub_by_u64) +- [Function `sub_by_u128`](#0x1_bigdecimal_sub_by_u128) +- [Function `sub_by_u256`](#0x1_bigdecimal_sub_by_u256) +- [Function `mul`](#0x1_bigdecimal_mul) +- [Function `mul_truncate`](#0x1_bigdecimal_mul_truncate) +- [Function `mul_ceil`](#0x1_bigdecimal_mul_ceil) +- [Function `mul_by_u64`](#0x1_bigdecimal_mul_by_u64) +- [Function `mul_by_u64_truncate`](#0x1_bigdecimal_mul_by_u64_truncate) +- [Function `mul_by_u64_ceil`](#0x1_bigdecimal_mul_by_u64_ceil) +- [Function `mul_by_u128`](#0x1_bigdecimal_mul_by_u128) +- [Function `mul_by_u128_truncate`](#0x1_bigdecimal_mul_by_u128_truncate) +- [Function `mul_by_u128_ceil`](#0x1_bigdecimal_mul_by_u128_ceil) +- [Function `mul_by_u256`](#0x1_bigdecimal_mul_by_u256) +- [Function `mul_by_u256_truncate`](#0x1_bigdecimal_mul_by_u256_truncate) +- [Function `mul_by_u256_ceil`](#0x1_bigdecimal_mul_by_u256_ceil) +- [Function `div`](#0x1_bigdecimal_div) +- [Function `div_by_u64`](#0x1_bigdecimal_div_by_u64) +- [Function `div_by_u128`](#0x1_bigdecimal_div_by_u128) +- [Function `div_by_u256`](#0x1_bigdecimal_div_by_u256) +- [Function `truncate`](#0x1_bigdecimal_truncate) +- [Function `truncate_u64`](#0x1_bigdecimal_truncate_u64) +- [Function `truncate_u128`](#0x1_bigdecimal_truncate_u128) +- [Function `truncate_u256`](#0x1_bigdecimal_truncate_u256) +- [Function `round_up`](#0x1_bigdecimal_round_up) +- [Function `round_up_u64`](#0x1_bigdecimal_round_up_u64) +- [Function `round_up_u128`](#0x1_bigdecimal_round_up_u128) +- [Function `round_up_u256`](#0x1_bigdecimal_round_up_u256) +- [Function `ceil`](#0x1_bigdecimal_ceil) +- [Function `ceil_u64`](#0x1_bigdecimal_ceil_u64) +- [Function `ceil_u128`](#0x1_bigdecimal_ceil_u128) +- [Function `ceil_u256`](#0x1_bigdecimal_ceil_u256) + + +
use 0x1::biguint;
+use 0x1::error;
+
+ + + + + +## Struct `BigDecimal` + + + +
struct BigDecimal has copy, drop, store
+
+ + + +##### Fields + + +
+
+scaled: biguint::BigUint +
+
+ +
+
+ + + + +## Constants + + + + + + +
const EDIVISION_BY_ZERO: u64 = 101;
+
+ + + + + + + +
const NEGATIVE_RESULT: u64 = 100;
+
+ + + + + + + +
const DECIMAL_FRACTIONAL: u64 = 1000000000000000000;
+
+ + + + + + + +
const FRACTIONAL_LENGTH: u64 = 18;
+
+ + + + + +## Function `from_u64` + +Create a BigDecimal from a u64 value by multiplying it by the fractional part. + + +
public fun from_u64(value: u64): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_u64(value: u64): BigDecimal {
+    BigDecimal {
+        scaled: biguint::mul(biguint::from_u64(value), f())
+    }
+}
+
+ + + + + +## Function `from_u128` + +Create a BigDecimal from a u128 value by multiplying it by the fractional part. + + +
public fun from_u128(value: u128): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_u128(value: u128): BigDecimal {
+    BigDecimal {
+        scaled: biguint::mul(biguint::from_u128(value), f())
+    }
+}
+
+ + + + + +## Function `from_u256` + +Create a BigDecimal from a u256 value by multiplying it by the fractional part. + + +
public fun from_u256(value: u256): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_u256(value: u256): BigDecimal {
+    BigDecimal {
+        scaled: biguint::mul(biguint::from_u256(value), f())
+    }
+}
+
+ + + + + +## Function `new` + +Create a BigDecimal from a BigUint value by multiplying it by the fractional part. + + +
public fun new(value: biguint::BigUint): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun new(value: BigUint): BigDecimal {
+    BigDecimal {
+        scaled: biguint::mul(value, f())
+    }
+}
+
+ + + + + +## Function `from_scaled` + +Create a BigDecimal from a scaled BigUint value. + + +
public fun from_scaled(scaled: biguint::BigUint): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_scaled(scaled: BigUint): BigDecimal {
+    BigDecimal { scaled: scaled }
+}
+
+ + + + + +## Function `get_scaled` + +Get the scaled value of a BigDecimal. + + +
public fun get_scaled(num: bigdecimal::BigDecimal): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun get_scaled(num: BigDecimal): BigUint {
+    num.scaled
+}
+
+ + + + + +## Function `from_scaled_le_bytes` + +Create a BigDecimal from a scaled BigUint le_bytes value. + + +
public fun from_scaled_le_bytes(le_bytes: vector<u8>): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_scaled_le_bytes(le_bytes: vector<u8>): BigDecimal {
+    BigDecimal { scaled: biguint::from_le_bytes(le_bytes) }
+}
+
+ + + + + +## Function `get_scaled_le_bytes` + + + +
public fun get_scaled_le_bytes(num: bigdecimal::BigDecimal): vector<u8>
+
+ + + +##### Implementation + + +
public fun get_scaled_le_bytes(num: BigDecimal): vector<u8> {
+    biguint::to_le_bytes(num.scaled)
+}
+
+ + + + + +## Function `from_ratio` + + + +
public fun from_ratio(numerator: biguint::BigUint, denominator: biguint::BigUint): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_ratio(numerator: BigUint, denominator: BigUint): BigDecimal {
+    assert!(
+        !biguint::is_zero(denominator), error::invalid_argument(EDIVISION_BY_ZERO)
+    );
+
+    let numerator = biguint::mul(numerator, f());
+    BigDecimal { scaled: biguint::div(numerator, denominator) }
+}
+
+ + + + + +## Function `from_ratio_u64` + + + +
public fun from_ratio_u64(numerator: u64, denominator: u64): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_ratio_u64(numerator: u64, denominator: u64): BigDecimal {
+    assert!(denominator != 0, error::invalid_argument(EDIVISION_BY_ZERO));
+
+    let numerator = biguint::from_u128(
+        (numerator as u128) * (DECIMAL_FRACTIONAL as u128)
+    );
+    let denominator = biguint::from_u64(denominator);
+
+    BigDecimal { scaled: biguint::div(numerator, denominator) }
+}
+
+ + + + + +## Function `from_ratio_u128` + + + +
public fun from_ratio_u128(numerator: u128, denominator: u128): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_ratio_u128(numerator: u128, denominator: u128): BigDecimal {
+    assert!(denominator != 0, error::invalid_argument(EDIVISION_BY_ZERO));
+
+    let numerator = biguint::from_u256(
+        (numerator as u256) * (DECIMAL_FRACTIONAL as u256)
+    );
+    let denominator = biguint::from_u128(denominator);
+
+    BigDecimal { scaled: biguint::div(numerator, denominator) }
+}
+
+ + + + + +## Function `from_ratio_u256` + + + +
public fun from_ratio_u256(numerator: u256, denominator: u256): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun from_ratio_u256(numerator: u256, denominator: u256): BigDecimal {
+    assert!(denominator != 0, error::invalid_argument(EDIVISION_BY_ZERO));
+
+    let numerator = biguint::mul(biguint::from_u256(numerator), f());
+    let denominator = biguint::from_u256(denominator);
+
+    BigDecimal { scaled: biguint::div(numerator, denominator) }
+}
+
+ + + + + +## Function `rev` + + + +
public fun rev(num: bigdecimal::BigDecimal): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun rev(num: BigDecimal): BigDecimal {
+    let fractional = f();
+    BigDecimal {
+        scaled: biguint::div(biguint::mul(fractional, fractional), num.scaled)
+    }
+}
+
+ + + + + +## Function `one` + + + +
public fun one(): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun one(): BigDecimal {
+    BigDecimal { scaled: f() }
+}
+
+ + + + + +## Function `zero` + + + +
public fun zero(): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun zero(): BigDecimal {
+    BigDecimal { scaled: biguint::zero() }
+}
+
+ + + + + +## Function `eq` + + + +
public fun eq(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bool
+
+ + + +##### Implementation + + +
public fun eq(num1: BigDecimal, num2: BigDecimal): bool {
+    biguint::eq(num1.scaled, num2.scaled)
+}
+
+ + + + + +## Function `lt` + + + +
public fun lt(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bool
+
+ + + +##### Implementation + + +
public fun lt(num1: BigDecimal, num2: BigDecimal): bool {
+    biguint::lt(num1.scaled, num2.scaled)
+}
+
+ + + + + +## Function `le` + + + +
public fun le(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bool
+
+ + + +##### Implementation + + +
public fun le(num1: BigDecimal, num2: BigDecimal): bool {
+    biguint::le(num1.scaled, num2.scaled)
+}
+
+ + + + + +## Function `gt` + + + +
public fun gt(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bool
+
+ + + +##### Implementation + + +
public fun gt(num1: BigDecimal, num2: BigDecimal): bool {
+    biguint::gt(num1.scaled, num2.scaled)
+}
+
+ + + + + +## Function `ge` + + + +
public fun ge(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bool
+
+ + + +##### Implementation + + +
public fun ge(num1: BigDecimal, num2: BigDecimal): bool {
+    biguint::ge(num1.scaled, num2.scaled)
+}
+
+ + + + + +## Function `is_zero` + + + +
public fun is_zero(num: bigdecimal::BigDecimal): bool
+
+ + + +##### Implementation + + +
public fun is_zero(num: BigDecimal): bool {
+    biguint::is_zero(num.scaled)
+}
+
+ + + + + +## Function `is_one` + + + +
public fun is_one(num: bigdecimal::BigDecimal): bool
+
+ + + +##### Implementation + + +
public fun is_one(num: BigDecimal): bool {
+    biguint::eq(num.scaled, f())
+}
+
+ + + + + +## Function `add` + + + +
public fun add(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun add(num1: BigDecimal, num2: BigDecimal): BigDecimal {
+    BigDecimal { scaled: biguint::add(num1.scaled, num2.scaled) }
+}
+
+ + + + + +## Function `add_by_u64` + + + +
public fun add_by_u64(num1: bigdecimal::BigDecimal, num2: u64): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun add_by_u64(num1: BigDecimal, num2: u64): BigDecimal {
+    BigDecimal {
+        scaled: biguint::add(num1.scaled, from_u64(num2).scaled)
+    }
+}
+
+ + + + + +## Function `add_by_u128` + + + +
public fun add_by_u128(num1: bigdecimal::BigDecimal, num2: u128): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun add_by_u128(num1: BigDecimal, num2: u128): BigDecimal {
+    BigDecimal {
+        scaled: biguint::add(num1.scaled, from_u128(num2).scaled)
+    }
+}
+
+ + + + + +## Function `add_by_u256` + + + +
public fun add_by_u256(num1: bigdecimal::BigDecimal, num2: u256): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun add_by_u256(num1: BigDecimal, num2: u256): BigDecimal {
+    BigDecimal {
+        scaled: biguint::add(num1.scaled, from_u256(num2).scaled)
+    }
+}
+
+ + + + + +## Function `sub` + + + +
public fun sub(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun sub(num1: BigDecimal, num2: BigDecimal): BigDecimal {
+    assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT));
+    BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) }
+}
+
+ + + + + +## Function `sub_by_u64` + + + +
public fun sub_by_u64(num1: bigdecimal::BigDecimal, num2: u64): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun sub_by_u64(num1: BigDecimal, num2: u64): BigDecimal {
+    let num2 = from_u64(num2);
+    assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT));
+    BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) }
+}
+
+ + + + + +## Function `sub_by_u128` + + + +
public fun sub_by_u128(num1: bigdecimal::BigDecimal, num2: u128): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun sub_by_u128(num1: BigDecimal, num2: u128): BigDecimal {
+    let num2 = from_u128(num2);
+    assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT));
+    BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) }
+}
+
+ + + + + +## Function `sub_by_u256` + + + +
public fun sub_by_u256(num1: bigdecimal::BigDecimal, num2: u256): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun sub_by_u256(num1: BigDecimal, num2: u256): BigDecimal {
+    let num2 = from_u256(num2);
+    assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT));
+    BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) }
+}
+
+ + + + + +## Function `mul` + + + +
public fun mul(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun mul(num1: BigDecimal, num2: BigDecimal): BigDecimal {
+    BigDecimal {
+        scaled: biguint::div(biguint::mul(num1.scaled, num2.scaled), f())
+    }
+}
+
+ + + + + +## Function `mul_truncate` + + + +
public fun mul_truncate(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun mul_truncate(num1: BigDecimal, num2: BigDecimal): BigUint {
+    truncate(mul(num1, num2))
+}
+
+ + + + + +## Function `mul_ceil` + + + +
public fun mul_ceil(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun mul_ceil(num1: BigDecimal, num2: BigDecimal): BigUint {
+    ceil(mul(num1, num2))
+}
+
+ + + + + +## Function `mul_by_u64` + + + +
public fun mul_by_u64(num1: bigdecimal::BigDecimal, num2: u64): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun mul_by_u64(num1: BigDecimal, num2: u64): BigDecimal {
+    BigDecimal { scaled: biguint::mul_by_u64(num1.scaled, num2) }
+}
+
+ + + + + +## Function `mul_by_u64_truncate` + + + +
public fun mul_by_u64_truncate(num1: bigdecimal::BigDecimal, num2: u64): u64
+
+ + + +##### Implementation + + +
public fun mul_by_u64_truncate(num1: BigDecimal, num2: u64): u64 {
+    truncate_u64(mul_by_u64(num1, num2))
+}
+
+ + + + + +## Function `mul_by_u64_ceil` + + + +
public fun mul_by_u64_ceil(num1: bigdecimal::BigDecimal, num2: u64): u64
+
+ + + +##### Implementation + + +
public fun mul_by_u64_ceil(num1: BigDecimal, num2: u64): u64 {
+    ceil_u64(mul_by_u64(num1, num2))
+}
+
+ + + + + +## Function `mul_by_u128` + + + +
public fun mul_by_u128(num1: bigdecimal::BigDecimal, num2: u128): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun mul_by_u128(num1: BigDecimal, num2: u128): BigDecimal {
+    BigDecimal { scaled: biguint::mul_by_u128(num1.scaled, num2) }
+}
+
+ + + + + +## Function `mul_by_u128_truncate` + + + +
public fun mul_by_u128_truncate(num1: bigdecimal::BigDecimal, num2: u128): u128
+
+ + + +##### Implementation + + +
public fun mul_by_u128_truncate(num1: BigDecimal, num2: u128): u128 {
+    truncate_u128(mul_by_u128(num1, num2))
+}
+
+ + + + + +## Function `mul_by_u128_ceil` + + + +
public fun mul_by_u128_ceil(num1: bigdecimal::BigDecimal, num2: u128): u128
+
+ + + +##### Implementation + + +
public fun mul_by_u128_ceil(num1: BigDecimal, num2: u128): u128 {
+    ceil_u128(mul_by_u128(num1, num2))
+}
+
+ + + + + +## Function `mul_by_u256` + + + +
public fun mul_by_u256(num1: bigdecimal::BigDecimal, num2: u256): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun mul_by_u256(num1: BigDecimal, num2: u256): BigDecimal {
+    BigDecimal { scaled: biguint::mul_by_u256(num1.scaled, num2) }
+}
+
+ + + + + +## Function `mul_by_u256_truncate` + + + +
public fun mul_by_u256_truncate(num1: bigdecimal::BigDecimal, num2: u256): u256
+
+ + + +##### Implementation + + +
public fun mul_by_u256_truncate(num1: BigDecimal, num2: u256): u256 {
+    truncate_u256(mul_by_u256(num1, num2))
+}
+
+ + + + + +## Function `mul_by_u256_ceil` + + + +
public fun mul_by_u256_ceil(num1: bigdecimal::BigDecimal, num2: u256): u256
+
+ + + +##### Implementation + + +
public fun mul_by_u256_ceil(num1: BigDecimal, num2: u256): u256 {
+    ceil_u256(mul_by_u256(num1, num2))
+}
+
+ + + + + +## Function `div` + + + +
public fun div(num1: bigdecimal::BigDecimal, num2: bigdecimal::BigDecimal): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun div(num1: BigDecimal, num2: BigDecimal): BigDecimal {
+    assert!(
+        !biguint::is_zero(num2.scaled), error::invalid_argument(EDIVISION_BY_ZERO)
+    );
+
+    BigDecimal {
+        scaled: biguint::div(biguint::mul(num1.scaled, f()), num2.scaled)
+    }
+}
+
+ + + + + +## Function `div_by_u64` + + + +
public fun div_by_u64(num1: bigdecimal::BigDecimal, num2: u64): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun div_by_u64(num1: BigDecimal, num2: u64): BigDecimal {
+    assert!(num2 != 0, error::invalid_argument(EDIVISION_BY_ZERO));
+
+    BigDecimal { scaled: biguint::div_by_u64(num1.scaled, num2) }
+}
+
+ + + + + +## Function `div_by_u128` + + + +
public fun div_by_u128(num1: bigdecimal::BigDecimal, num2: u128): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun div_by_u128(num1: BigDecimal, num2: u128): BigDecimal {
+    assert!(num2 != 0, error::invalid_argument(EDIVISION_BY_ZERO));
+
+    BigDecimal { scaled: biguint::div_by_u128(num1.scaled, num2) }
+}
+
+ + + + + +## Function `div_by_u256` + + + +
public fun div_by_u256(num1: bigdecimal::BigDecimal, num2: u256): bigdecimal::BigDecimal
+
+ + + +##### Implementation + + +
public fun div_by_u256(num1: BigDecimal, num2: u256): BigDecimal {
+    assert!(num2 != 0, error::invalid_argument(EDIVISION_BY_ZERO));
+
+    BigDecimal { scaled: biguint::div_by_u256(num1.scaled, num2) }
+}
+
+ + + + + +## Function `truncate` + + + +
public fun truncate(num: bigdecimal::BigDecimal): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun truncate(num: BigDecimal): BigUint {
+    biguint::div(num.scaled, f())
+}
+
+ + + + + +## Function `truncate_u64` + + + +
public fun truncate_u64(num: bigdecimal::BigDecimal): u64
+
+ + + +##### Implementation + + +
public fun truncate_u64(num: BigDecimal): u64 {
+    biguint::to_u64(truncate(num))
+}
+
+ + + + + +## Function `truncate_u128` + + + +
public fun truncate_u128(num: bigdecimal::BigDecimal): u128
+
+ + + +##### Implementation + + +
public fun truncate_u128(num: BigDecimal): u128 {
+    biguint::to_u128(truncate(num))
+}
+
+ + + + + +## Function `truncate_u256` + + + +
public fun truncate_u256(num: bigdecimal::BigDecimal): u256
+
+ + + +##### Implementation + + +
public fun truncate_u256(num: BigDecimal): u256 {
+    biguint::to_u256(truncate(num))
+}
+
+ + + + + +## Function `round_up` + + + +
public fun round_up(num: bigdecimal::BigDecimal): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun round_up(num: BigDecimal): BigUint {
+    biguint::div(biguint::add(num.scaled, hf()), f())
+}
+
+ + + + + +## Function `round_up_u64` + + + +
public fun round_up_u64(num: bigdecimal::BigDecimal): u64
+
+ + + +##### Implementation + + +
public fun round_up_u64(num: BigDecimal): u64 {
+    biguint::to_u64(round_up(num))
+}
+
+ + + + + +## Function `round_up_u128` + + + +
public fun round_up_u128(num: bigdecimal::BigDecimal): u128
+
+ + + +##### Implementation + + +
public fun round_up_u128(num: BigDecimal): u128 {
+    biguint::to_u128(round_up(num))
+}
+
+ + + + + +## Function `round_up_u256` + + + +
public fun round_up_u256(num: bigdecimal::BigDecimal): u256
+
+ + + +##### Implementation + + +
public fun round_up_u256(num: BigDecimal): u256 {
+    biguint::to_u256(round_up(num))
+}
+
+ + + + + +## Function `ceil` + + + +
public fun ceil(num: bigdecimal::BigDecimal): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun ceil(num: BigDecimal): BigUint {
+    biguint::div(biguint::add(num.scaled, f_1()), f())
+}
+
+ + + + + +## Function `ceil_u64` + + + +
public fun ceil_u64(num: bigdecimal::BigDecimal): u64
+
+ + + +##### Implementation + + +
public fun ceil_u64(num: BigDecimal): u64 {
+    biguint::to_u64(ceil(num))
+}
+
+ + + + + +## Function `ceil_u128` + + + +
public fun ceil_u128(num: bigdecimal::BigDecimal): u128
+
+ + + +##### Implementation + + +
public fun ceil_u128(num: BigDecimal): u128 {
+    biguint::to_u128(ceil(num))
+}
+
+ + + + + +## Function `ceil_u256` + + + +
public fun ceil_u256(num: bigdecimal::BigDecimal): u256
+
+ + + +##### Implementation + + +
public fun ceil_u256(num: BigDecimal): u256 {
+    biguint::to_u256(ceil(num))
+}
+
diff --git a/minitia_stdlib/doc/biguint.md b/minitia_stdlib/doc/biguint.md new file mode 100644 index 0000000..2a8038b --- /dev/null +++ b/minitia_stdlib/doc/biguint.md @@ -0,0 +1,823 @@ + + + +# Module `0x1::biguint` + + + +- [Struct `BigUint`](#0x1_biguint_BigUint) +- [Constants](#@Constants_0) +- [Function `from_le_bytes`](#0x1_biguint_from_le_bytes) +- [Function `zero`](#0x1_biguint_zero) +- [Function `one`](#0x1_biguint_one) +- [Function `from_u64`](#0x1_biguint_from_u64) +- [Function `to_u64`](#0x1_biguint_to_u64) +- [Function `from_u128`](#0x1_biguint_from_u128) +- [Function `to_u128`](#0x1_biguint_to_u128) +- [Function `from_u256`](#0x1_biguint_from_u256) +- [Function `to_u256`](#0x1_biguint_to_u256) +- [Function `to_le_bytes`](#0x1_biguint_to_le_bytes) +- [Function `add`](#0x1_biguint_add) +- [Function `add_by_u64`](#0x1_biguint_add_by_u64) +- [Function `add_by_u128`](#0x1_biguint_add_by_u128) +- [Function `add_by_u256`](#0x1_biguint_add_by_u256) +- [Function `sub`](#0x1_biguint_sub) +- [Function `sub_by_u64`](#0x1_biguint_sub_by_u64) +- [Function `sub_by_u128`](#0x1_biguint_sub_by_u128) +- [Function `sub_by_u256`](#0x1_biguint_sub_by_u256) +- [Function `mul`](#0x1_biguint_mul) +- [Function `mul_by_u64`](#0x1_biguint_mul_by_u64) +- [Function `mul_by_u128`](#0x1_biguint_mul_by_u128) +- [Function `mul_by_u256`](#0x1_biguint_mul_by_u256) +- [Function `div`](#0x1_biguint_div) +- [Function `div_by_u64`](#0x1_biguint_div_by_u64) +- [Function `div_by_u128`](#0x1_biguint_div_by_u128) +- [Function `div_by_u256`](#0x1_biguint_div_by_u256) +- [Function `eq`](#0x1_biguint_eq) +- [Function `lt`](#0x1_biguint_lt) +- [Function `le`](#0x1_biguint_le) +- [Function `gt`](#0x1_biguint_gt) +- [Function `ge`](#0x1_biguint_ge) +- [Function `is_zero`](#0x1_biguint_is_zero) +- [Function `is_one`](#0x1_biguint_is_one) + + +
+ + + + + +## Struct `BigUint` + + + +
struct BigUint has copy, drop, store
+
+ + + +##### Fields + + +
+
+bytes: vector<u8> +
+
+ +
+
+ + + + +## Constants + + + + + + +
const CAST_OVERFLOW: u64 = 102;
+
+ + + + + + + +
const EDIVISION_BY_ZERO: u64 = 101;
+
+ + + + + + + +
const INVALID_NUMERIC_TYPE: u64 = 103;
+
+ + + + + + + +
const NEGATIVE_RESULT: u64 = 100;
+
+ + + + + +## Function `from_le_bytes` + +Create a new BigUint from little-endian bytes. + + +
public fun from_le_bytes(le_bytes: vector<u8>): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun from_le_bytes(le_bytes: vector<u8>): BigUint {
+    BigUint { bytes: le_bytes }
+}
+
+ + + + + +## Function `zero` + + + +
public fun zero(): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun zero(): BigUint {
+    from_u64(0)
+}
+
+ + + + + +## Function `one` + + + +
public fun one(): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun one(): BigUint {
+    from_u64(1)
+}
+
+ + + + + +## Function `from_u64` + + + +
public fun from_u64(num: u64): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun from_u64(num: u64): BigUint {
+    let num_bytes = new_internal(num);
+    BigUint { bytes: num_bytes }
+}
+
+ + + + + +## Function `to_u64` + + + +
public fun to_u64(num: biguint::BigUint): u64
+
+ + + +##### Implementation + + +
public fun to_u64(num: BigUint): u64 {
+    cast_internal<u64>(num.bytes)
+}
+
+ + + + + +## Function `from_u128` + + + +
public fun from_u128(num: u128): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun from_u128(num: u128): BigUint {
+    let num_bytes = new_internal(num);
+    BigUint { bytes: num_bytes }
+}
+
+ + + + + +## Function `to_u128` + + + +
public fun to_u128(num: biguint::BigUint): u128
+
+ + + +##### Implementation + + +
public fun to_u128(num: BigUint): u128 {
+    cast_internal<u128>(num.bytes)
+}
+
+ + + + + +## Function `from_u256` + + + +
public fun from_u256(num: u256): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun from_u256(num: u256): BigUint {
+    let num_bytes = new_internal(num);
+    BigUint { bytes: num_bytes }
+}
+
+ + + + + +## Function `to_u256` + + + +
public fun to_u256(num: biguint::BigUint): u256
+
+ + + +##### Implementation + + +
public fun to_u256(num: BigUint): u256 {
+    cast_internal<u256>(num.bytes)
+}
+
+ + + + + +## Function `to_le_bytes` + + + +
public fun to_le_bytes(num: biguint::BigUint): vector<u8>
+
+ + + +##### Implementation + + +
public fun to_le_bytes(num: BigUint): vector<u8> {
+    num.bytes
+}
+
+ + + + + +## Function `add` + + + +
public fun add(num1: biguint::BigUint, num2: biguint::BigUint): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun add(num1: BigUint, num2: BigUint): BigUint {
+    let result_bytes = add_internal(num1.bytes, num2.bytes);
+    BigUint { bytes: result_bytes }
+}
+
+ + + + + +## Function `add_by_u64` + + + +
public fun add_by_u64(num1: biguint::BigUint, num2: u64): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun add_by_u64(num1: BigUint, num2: u64): BigUint {
+    let num2 = from_u64(num2);
+    add(num1, num2)
+}
+
+ + + + + +## Function `add_by_u128` + + + +
public fun add_by_u128(num1: biguint::BigUint, num2: u128): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun add_by_u128(num1: BigUint, num2: u128): BigUint {
+    let num2 = from_u128(num2);
+    add(num1, num2)
+}
+
+ + + + + +## Function `add_by_u256` + + + +
public fun add_by_u256(num1: biguint::BigUint, num2: u256): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun add_by_u256(num1: BigUint, num2: u256): BigUint {
+    let num2 = from_u256(num2);
+    add(num1, num2)
+}
+
+ + + + + +## Function `sub` + + + +
public fun sub(num1: biguint::BigUint, num2: biguint::BigUint): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun sub(num1: BigUint, num2: BigUint): BigUint {
+    let result_bytes = sub_internal(num1.bytes, num2.bytes);
+    BigUint { bytes: result_bytes }
+}
+
+ + + + + +## Function `sub_by_u64` + + + +
public fun sub_by_u64(num1: biguint::BigUint, num2: u64): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun sub_by_u64(num1: BigUint, num2: u64): BigUint {
+    let num2 = from_u64(num2);
+    sub(num1, num2)
+}
+
+ + + + + +## Function `sub_by_u128` + + + +
public fun sub_by_u128(num1: biguint::BigUint, num2: u128): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun sub_by_u128(num1: BigUint, num2: u128): BigUint {
+    let num2 = from_u128(num2);
+    sub(num1, num2)
+}
+
+ + + + + +## Function `sub_by_u256` + + + +
public fun sub_by_u256(num1: biguint::BigUint, num2: u256): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun sub_by_u256(num1: BigUint, num2: u256): BigUint {
+    let num2 = from_u256(num2);
+    sub(num1, num2)
+}
+
+ + + + + +## Function `mul` + + + +
public fun mul(num1: biguint::BigUint, num2: biguint::BigUint): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun mul(num1: BigUint, num2: BigUint): BigUint {
+    let result_bytes = mul_internal(num1.bytes, num2.bytes);
+    BigUint { bytes: result_bytes }
+}
+
+ + + + + +## Function `mul_by_u64` + + + +
public fun mul_by_u64(num1: biguint::BigUint, num2: u64): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun mul_by_u64(num1: BigUint, num2: u64): BigUint {
+    let num2 = from_u64(num2);
+    mul(num1, num2)
+}
+
+ + + + + +## Function `mul_by_u128` + + + +
public fun mul_by_u128(num1: biguint::BigUint, num2: u128): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun mul_by_u128(num1: BigUint, num2: u128): BigUint {
+    let num2 = from_u128(num2);
+    mul(num1, num2)
+}
+
+ + + + + +## Function `mul_by_u256` + + + +
public fun mul_by_u256(num1: biguint::BigUint, num2: u256): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun mul_by_u256(num1: BigUint, num2: u256): BigUint {
+    let num2 = from_u256(num2);
+    mul(num1, num2)
+}
+
+ + + + + +## Function `div` + + + +
public fun div(num1: biguint::BigUint, num2: biguint::BigUint): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun div(num1: BigUint, num2: BigUint): BigUint {
+    let result_bytes = div_internal(num1.bytes, num2.bytes);
+    BigUint { bytes: result_bytes }
+}
+
+ + + + + +## Function `div_by_u64` + + + +
public fun div_by_u64(num1: biguint::BigUint, num2: u64): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun div_by_u64(num1: BigUint, num2: u64): BigUint {
+    let num2 = from_u64(num2);
+    div(num1, num2)
+}
+
+ + + + + +## Function `div_by_u128` + + + +
public fun div_by_u128(num1: biguint::BigUint, num2: u128): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun div_by_u128(num1: BigUint, num2: u128): BigUint {
+    let num2 = from_u128(num2);
+    div(num1, num2)
+}
+
+ + + + + +## Function `div_by_u256` + + + +
public fun div_by_u256(num1: biguint::BigUint, num2: u256): biguint::BigUint
+
+ + + +##### Implementation + + +
public fun div_by_u256(num1: BigUint, num2: u256): BigUint {
+    let num2 = from_u256(num2);
+    div(num1, num2)
+}
+
+ + + + + +## Function `eq` + + + +
public fun eq(num1: biguint::BigUint, num2: biguint::BigUint): bool
+
+ + + +##### Implementation + + +
public fun eq(num1: BigUint, num2: BigUint): bool {
+    num1.bytes == num2.bytes
+}
+
+ + + + + +## Function `lt` + + + +
public fun lt(num1: biguint::BigUint, num2: biguint::BigUint): bool
+
+ + + +##### Implementation + + +
public fun lt(num1: BigUint, num2: BigUint): bool {
+    lt_internal(num1.bytes, num2.bytes)
+}
+
+ + + + + +## Function `le` + + + +
public fun le(num1: biguint::BigUint, num2: biguint::BigUint): bool
+
+ + + +##### Implementation + + +
public fun le(num1: BigUint, num2: BigUint): bool {
+    le_internal(num1.bytes, num2.bytes)
+}
+
+ + + + + +## Function `gt` + + + +
public fun gt(num1: biguint::BigUint, num2: biguint::BigUint): bool
+
+ + + +##### Implementation + + +
public fun gt(num1: BigUint, num2: BigUint): bool {
+    gt_internal(num1.bytes, num2.bytes)
+}
+
+ + + + + +## Function `ge` + + + +
public fun ge(num1: biguint::BigUint, num2: biguint::BigUint): bool
+
+ + + +##### Implementation + + +
public fun ge(num1: BigUint, num2: BigUint): bool {
+    ge_internal(num1.bytes, num2.bytes)
+}
+
+ + + + + +## Function `is_zero` + + + +
public fun is_zero(num: biguint::BigUint): bool
+
+ + + +##### Implementation + + +
public fun is_zero(num: BigUint): bool {
+    eq(num, zero())
+}
+
+ + + + + +## Function `is_one` + + + +
public fun is_one(num: biguint::BigUint): bool
+
+ + + +##### Implementation + + +
public fun is_one(num: BigUint): bool {
+    eq(num, one())
+}
+
diff --git a/minitia_stdlib/doc/block.md b/minitia_stdlib/doc/block.md index 133c6d0..e521ad6 100644 --- a/minitia_stdlib/doc/block.md +++ b/minitia_stdlib/doc/block.md @@ -6,6 +6,8 @@ - [Function `get_block_info`](#0x1_block_get_block_info) +- [Function `get_current_block_height`](#0x1_block_get_current_block_height) +- [Function `get_current_block_timestamp`](#0x1_block_get_current_block_timestamp)
@@ -23,8 +25,7 @@ -
-Implementation +##### Implementation
native public fun get_block_info(): (u64, u64);
@@ -32,4 +33,46 @@
 
 
 
-
+ + +## Function `get_current_block_height` + + + +
#[view]
+public fun get_current_block_height(): u64
+
+ + + +##### Implementation + + +
public fun get_current_block_height(): u64 {
+    let (height, _) = get_block_info();
+    height
+}
+
+ + + + + +## Function `get_current_block_timestamp` + + + +
#[view]
+public fun get_current_block_timestamp(): u64
+
+ + + +##### Implementation + + +
public fun get_current_block_timestamp(): u64 {
+    let (_, timestamp) = get_block_info();
+    timestamp
+}
+
diff --git a/minitia_stdlib/doc/code.md b/minitia_stdlib/doc/code.md index f4714f2..c28aa4c 100644 --- a/minitia_stdlib/doc/code.md +++ b/minitia_stdlib/doc/code.md @@ -11,17 +11,20 @@ - [Struct `ModulePublishedEvent`](#0x1_code_ModulePublishedEvent) - [Constants](#@Constants_0) - [Function `can_change_upgrade_policy_to`](#0x1_code_can_change_upgrade_policy_to) -- [Function `init_module`](#0x1_code_init_module) +- [Function `allowed_publishers`](#0x1_code_allowed_publishers) +- [Function `total_modules`](#0x1_code_total_modules) - [Function `init_genesis`](#0x1_code_init_genesis) - [Function `set_allowed_publishers`](#0x1_code_set_allowed_publishers) -- [Function `assert_allowed`](#0x1_code_assert_allowed) +- [Function `freeze_code_object`](#0x1_code_freeze_code_object) - [Function `publish`](#0x1_code_publish) -- [Function `request_publish`](#0x1_code_request_publish)
use 0x1::error;
 use 0x1::event;
+use 0x1::object;
+use 0x1::option;
 use 0x1::signer;
+use 0x1::simple_map;
 use 0x1::string;
 use 0x1::table;
 use 0x1::vector;
@@ -40,8 +43,7 @@
 
 
 
-
-Fields +##### Fields
@@ -52,11 +54,15 @@ It is a list of addresses with permission to distribute contracts, and an empty list is interpreted as allowing anyone to distribute. +
+total_modules: u64 +
+
+ The total number of modules published. +
-
- ## Resource `MetadataStore` @@ -68,8 +74,7 @@ -
-Fields +##### Fields
@@ -82,8 +87,6 @@
-
- ## Struct `ModuleMetadata` @@ -96,8 +99,7 @@ Describes an upgrade policy -
-Fields +##### Fields
@@ -110,8 +112,6 @@ Describes an upgrade policy
-
- ## Struct `ModulePublishedEvent` @@ -124,8 +124,7 @@ Describes an upgrade policy -
-Fields +##### Fields
@@ -144,13 +143,31 @@ Describes an upgrade policy
-
- ## Constants + + +code_object does not exist. + + +
const ECODE_OBJECT_DOES_NOT_EXIST: u64 = 9;
+
+ + + + + +The module ID is duplicated. + + +
const EDUPLICATE_MODULE_ID: u64 = 7;
+
+ + + allowed_publishers argument is invalid. @@ -181,6 +198,16 @@ The operation is expected to be executed by chain signer. + + +Not the owner of the package registry. + + +
const ENOT_PACKAGE_OWNER: u64 = 8;
+
+ + + Cannot upgrade an immutable package. @@ -232,16 +259,6 @@ Whether the modules in the package are immutable and cannot be upgraded. - - -The upgrade policy is unspecified. - - -
const UPGRADE_POLICY_UNSPECIFIED: u8 = 0;
-
- - - ## Function `can_change_upgrade_policy_to` @@ -255,8 +272,7 @@ strengthened but not weakened. -
-Implementation +##### Implementation
public fun can_change_upgrade_policy_to(from: u8, to: u8): bool {
@@ -266,33 +282,51 @@ strengthened but not weakened.
 
 
 
-
- - + -## Function `init_module` +## Function `allowed_publishers` -
fun init_module(chain: &signer)
+
#[view]
+public fun allowed_publishers(): vector<address>
 
-
-Implementation +##### Implementation -
fun init_module(chain: &signer) {
-    move_to(chain, ModuleStore {
-        allowed_publishers: vector[],
-    });
+
public fun allowed_publishers(): vector<address> acquires ModuleStore {
+    let module_store = borrow_global<ModuleStore>(@minitia_std);
+    module_store.allowed_publishers
 }
 
-
+ + +## Function `total_modules` + + + +
#[view]
+public fun total_modules(): u64
+
+ + + +##### Implementation + + +
public fun total_modules(): u64 acquires ModuleStore {
+    let module_store = borrow_global<ModuleStore>(@minitia_std);
+    module_store.total_modules
+}
+
+ + @@ -305,38 +339,41 @@ strengthened but not weakened. -
-Implementation +##### Implementation
public entry fun init_genesis(
-    chain: &signer,
-    module_ids: vector<String>,
-    allowed_publishers: vector<address>,
+    chain: &signer, module_ids: vector<String>, allowed_publishers: vector<address>
 ) acquires ModuleStore {
-    assert!(signer::address_of(chain) == @minitia_std, error::permission_denied(EINVALID_CHAIN_OPERATOR));
+    assert!(
+        signer::address_of(chain) == @minitia_std,
+        error::permission_denied(EINVALID_CHAIN_OPERATOR)
+    );
 
     let metadata_table = table::new<String, ModuleMetadata>();
-    vector::for_each_ref(&module_ids,
+    vector::for_each_ref(
+        &module_ids,
         |module_id| {
-            table::add<String, ModuleMetadata>(&mut metadata_table, *module_id, ModuleMetadata {
-                upgrade_policy: UPGRADE_POLICY_COMPATIBLE,
-            });
+            table::add<String, ModuleMetadata>(
+                &mut metadata_table,
+                *module_id,
+                ModuleMetadata { upgrade_policy: UPGRADE_POLICY_COMPATIBLE }
+            );
         }
     );
 
-    move_to<MetadataStore>(chain, MetadataStore {
-        metadata: metadata_table,
-    });
+    move_to<MetadataStore>(
+        chain,
+        MetadataStore { metadata: metadata_table }
+    );
 
     set_allowed_publishers(chain, allowed_publishers);
+    increase_total_modules(vector::length(&module_ids));
 }
 
-
- ## Function `set_allowed_publishers` @@ -348,12 +385,16 @@ strengthened but not weakened. -
-Implementation +##### Implementation -
public entry fun set_allowed_publishers(chain: &signer, allowed_publishers: vector<address>) acquires ModuleStore {
-    assert!(signer::address_of(chain) == @minitia_std, error::permission_denied(EINVALID_CHAIN_OPERATOR));
+
public entry fun set_allowed_publishers(
+    chain: &signer, allowed_publishers: vector<address>
+) acquires ModuleStore {
+    assert!(
+        signer::address_of(chain) == @minitia_std,
+        error::permission_denied(EINVALID_CHAIN_OPERATOR)
+    );
     assert_allowed(&allowed_publishers, @minitia_std);
 
     let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
@@ -363,35 +404,48 @@ strengthened but not weakened.
 
 
 
-
+ - +## Function `freeze_code_object` -## Function `assert_allowed` - -
fun assert_allowed(allowed_publishers: &vector<address>, addr: address)
+
public fun freeze_code_object(publisher: &signer, code_object: object::Object<code::MetadataStore>)
 
-
-Implementation +##### Implementation -
fun assert_allowed(allowed_publishers: &vector<address>, addr: address) {
+
public fun freeze_code_object(
+    publisher: &signer, code_object: Object<MetadataStore>
+) acquires MetadataStore {
+    let code_object_addr = object::object_address(&code_object);
+    assert!(
+        exists<MetadataStore>(code_object_addr),
+        error::not_found(ECODE_OBJECT_DOES_NOT_EXIST)
+    );
     assert!(
-        vector::is_empty(allowed_publishers) || vector::contains(allowed_publishers, &addr),
-        error::invalid_argument(EINVALID_ALLOWED_PUBLISHERS),
-    )
+        object::is_owner(code_object, signer::address_of(publisher)),
+        error::permission_denied(ENOT_PACKAGE_OWNER)
+    );
+
+    let registry = borrow_global_mut<MetadataStore>(code_object_addr);
+    let iter = table::iter_mut(
+        &mut registry.metadata, option::none(), option::none(), 1
+    );
+    loop {
+        if (!table::prepare_mut(iter)) { break };
+
+        let (_, metadata) = table::next_mut(iter);
+        metadata.upgrade_policy = UPGRADE_POLICY_IMMUTABLE;
+    }
 }
 
-
- ## Function `publish` @@ -405,93 +459,95 @@ package. -
-Implementation +##### Implementation
public entry fun publish(
     owner: &signer,
     module_ids: vector<String>, // 0x1::coin
     code: vector<vector<u8>>,
-    upgrade_policy: u8,
+    upgrade_policy: u8
 ) acquires ModuleStore, MetadataStore {
     // Disallow incompatible upgrade mode. Governance can decide later if this should be reconsidered.
-    assert!(vector::length(&code) == vector::length(&module_ids), error::invalid_argument(EINVALID_ARGUMENTS));
+    assert!(
+        vector::length(&code) == vector::length(&module_ids),
+        error::invalid_argument(EINVALID_ARGUMENTS)
+    );
+
+    // duplication check
+    let module_ids_set = simple_map::create<String, bool>();
+    vector::for_each_ref(
+        &module_ids,
+        |module_id| {
+            assert!(
+                !simple_map::contains_key(&module_ids_set, module_id),
+                error::invalid_argument(EDUPLICATE_MODULE_ID)
+            );
+            simple_map::add(
+                &mut module_ids_set,
+                *module_id,
+                true
+            );
+        }
+    );
 
     // Check whether arbitrary publish is allowed or not.
     let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
     assert!(
-        upgrade_policy > UPGRADE_POLICY_UNSPECIFIED,
-        error::invalid_argument(EUPGRADE_POLICY_UNSPECIFIED),
+        upgrade_policy == UPGRADE_POLICY_COMPATIBLE
+            || upgrade_policy == UPGRADE_POLICY_IMMUTABLE,
+        error::invalid_argument(EUPGRADE_POLICY_UNSPECIFIED)
     );
 
     let addr = signer::address_of(owner);
     assert_allowed(&module_store.allowed_publishers, addr);
 
     if (!exists<MetadataStore>(addr)) {
-        move_to<MetadataStore>(owner, MetadataStore {
-            metadata: table::new(),
-        });
+        move_to<MetadataStore>(
+            owner,
+            MetadataStore { metadata: table::new() }
+        );
     };
 
     // Check upgradability
     let metadata_table = &mut borrow_global_mut<MetadataStore>(addr).metadata;
-    vector::for_each_ref(&module_ids,
+    vector::for_each_ref(
+        &module_ids,
         |module_id| {
             if (table::contains<String, ModuleMetadata>(metadata_table, *module_id)) {
-                let metadata = table::borrow_mut<String, ModuleMetadata>(metadata_table, *module_id);
-                assert!(metadata.upgrade_policy < UPGRADE_POLICY_IMMUTABLE,
-                    error::invalid_argument(EUPGRADE_IMMUTABLE));
-                assert!(can_change_upgrade_policy_to(metadata.upgrade_policy, upgrade_policy),
-                    error::invalid_argument(EUPGRADE_WEAKER_POLICY));
+                let metadata =
+                    table::borrow_mut<String, ModuleMetadata>(
+                        metadata_table, *module_id
+                    );
+                assert!(
+                    metadata.upgrade_policy < UPGRADE_POLICY_IMMUTABLE,
+                    error::invalid_argument(EUPGRADE_IMMUTABLE)
+                );
+                assert!(
+                    can_change_upgrade_policy_to(
+                        metadata.upgrade_policy,
+                        upgrade_policy
+                    ),
+                    error::invalid_argument(EUPGRADE_WEAKER_POLICY)
+                );
 
                 metadata.upgrade_policy = upgrade_policy;
             } else {
-                table::add<String, ModuleMetadata>(metadata_table, *module_id, ModuleMetadata {
-                    upgrade_policy,
-                });
+                table::add<String, ModuleMetadata>(
+                    metadata_table,
+                    *module_id,
+                    ModuleMetadata { upgrade_policy }
+                );
             };
 
-            event::emit(ModulePublishedEvent {
-                module_id: *module_id,
-                upgrade_policy,
-            });
+            event::emit(
+                ModulePublishedEvent { module_id: *module_id, upgrade_policy }
+            );
         }
     );
 
     // Request publish
-    request_publish(addr, module_ids, code, upgrade_policy)
+    increase_total_modules(vector::length(&module_ids));
+    request_publish(addr, module_ids, code)
 }
 
- - - -
- - - -## Function `request_publish` - -Native function to initiate module loading - - -
fun request_publish(owner: address, expected_modules: vector<string::String>, code: vector<vector<u8>>, policy: u8)
-
- - - -
-Implementation - - -
native fun request_publish(
-    owner: address,
-    expected_modules: vector<String>,
-    code: vector<vector<u8>>,
-    policy: u8
-);
-
- - - -
diff --git a/minitia_stdlib/doc/coin.md b/minitia_stdlib/doc/coin.md index 4976f66..02d905f 100644 --- a/minitia_stdlib/doc/coin.md +++ b/minitia_stdlib/doc/coin.md @@ -12,6 +12,8 @@ TODO - make is_module_account or some blacklist from freeze. - [Struct `BurnCapability`](#0x1_coin_BurnCapability) - [Struct `FreezeCapability`](#0x1_coin_FreezeCapability) - [Constants](#@Constants_0) +- [Function `sudo_transfer`](#0x1_coin_sudo_transfer) +- [Function `sudo_deposit`](#0x1_coin_sudo_deposit) - [Function `initialize`](#0x1_coin_initialize) - [Function `initialize_and_generate_extend_ref`](#0x1_coin_initialize_and_generate_extend_ref) - [Function `withdraw`](#0x1_coin_withdraw) @@ -32,7 +34,6 @@ TODO - make is_module_account or some blacklist from freeze. - [Function `decimals`](#0x1_coin_decimals) - [Function `metadata_address`](#0x1_coin_metadata_address) - [Function `metadata`](#0x1_coin_metadata) -- [Function `is_coin_initialized`](#0x1_coin_is_coin_initialized) - [Function `is_coin`](#0x1_coin_is_coin) - [Function `is_coin_by_symbol`](#0x1_coin_is_coin_by_symbol) - [Function `metadata_to_denom`](#0x1_coin_metadata_to_denom) @@ -40,6 +41,7 @@ TODO - make is_module_account or some blacklist from freeze.
use 0x1::bcs;
+use 0x1::error;
 use 0x1::event;
 use 0x1::from_bcs;
 use 0x1::fungible_asset;
@@ -47,6 +49,7 @@ TODO - make is_module_account or some blacklist from freeze.
 use 0x1::object;
 use 0x1::option;
 use 0x1::primary_fungible_store;
+use 0x1::signer;
 use 0x1::string;
 
@@ -63,8 +66,7 @@ TODO - make is_module_account or some blacklist from freeze. -
-Fields +##### Fields
@@ -89,8 +91,6 @@ TODO - make is_module_account or some blacklist from freeze.
-
- ## Struct `CoinCreatedEvent` @@ -103,8 +103,7 @@ TODO - make is_module_account or some blacklist from freeze. -
-Fields +##### Fields
@@ -117,8 +116,6 @@ TODO - make is_module_account or some blacklist from freeze.
-
- ## Struct `MintCapability` @@ -130,8 +127,7 @@ TODO - make is_module_account or some blacklist from freeze. -
-Fields +##### Fields
@@ -144,8 +140,6 @@ TODO - make is_module_account or some blacklist from freeze.
-
- ## Struct `BurnCapability` @@ -157,8 +151,7 @@ TODO - make is_module_account or some blacklist from freeze. -
-Fields +##### Fields
@@ -171,8 +164,6 @@ TODO - make is_module_account or some blacklist from freeze.
-
- ## Struct `FreezeCapability` @@ -184,8 +175,7 @@ TODO - make is_module_account or some blacklist from freeze. -
-Fields +##### Fields
@@ -198,8 +188,6 @@ TODO - make is_module_account or some blacklist from freeze.
-
- ## Constants @@ -225,6 +213,67 @@ Only fungible asset metadata owner can make changes. + + + + +
const EUNAUTHORIZED: u64 = 1;
+
+ + + + + +## Function `sudo_transfer` + + + +
public entry fun sudo_transfer(chain: &signer, sender: &signer, recipient: address, metadata: object::Object<fungible_asset::Metadata>, amount: u64)
+
+ + + +##### Implementation + + +
public entry fun sudo_transfer(
+    chain: &signer,
+    sender: &signer,
+    recipient: address,
+    metadata: Object<Metadata>,
+    amount: u64
+) {
+    check_sudo(chain);
+
+    primary_fungible_store::sudo_transfer(sender, metadata, recipient, amount)
+}
+
+ + + + + +## Function `sudo_deposit` + + + +
public(friend) fun sudo_deposit(account_addr: address, fa: fungible_asset::FungibleAsset)
+
+ + + +##### Implementation + + +
public(friend) fun sudo_deposit(
+    account_addr: address, fa: FungibleAsset
+) {
+    primary_fungible_store::sudo_deposit(account_addr, fa)
+}
+
+ + + ## Function `initialize` @@ -236,28 +285,28 @@ Only fungible asset metadata owner can make changes. -
-Implementation +##### Implementation -
public fun initialize (
+
public fun initialize(
     creator: &signer,
     maximum_supply: Option<u128>,
     name: String,
     symbol: String,
     decimals: u8,
     icon_uri: String,
-    project_uri: String,
+    project_uri: String
 ): (MintCapability, BurnCapability, FreezeCapability) {
-    let (mint_cap, burn_cap, freeze_cap, _) = initialize_and_generate_extend_ref(
-        creator,
-        maximum_supply,
-        name,
-        symbol,
-        decimals,
-        icon_uri,
-        project_uri,
-    );
+    let (mint_cap, burn_cap, freeze_cap, _) =
+        initialize_and_generate_extend_ref(
+            creator,
+            maximum_supply,
+            name,
+            symbol,
+            decimals,
+            icon_uri,
+            project_uri
+        );
 
     (mint_cap, burn_cap, freeze_cap)
 }
@@ -265,8 +314,6 @@ Only fungible asset metadata owner can make changes.
 
 
 
-
- ## Function `initialize_and_generate_extend_ref` @@ -278,21 +325,24 @@ Only fungible asset metadata owner can make changes. -
-Implementation +##### Implementation -
public fun initialize_and_generate_extend_ref (
+
public fun initialize_and_generate_extend_ref(
     creator: &signer,
     maximum_supply: Option<u128>,
     name: String,
     symbol: String,
     decimals: u8,
     icon_uri: String,
-    project_uri: String,
+    project_uri: String
 ): (MintCapability, BurnCapability, FreezeCapability, ExtendRef) {
     // create object for fungible asset metadata
-    let constructor_ref = &object::create_named_object(creator, *string::bytes(&symbol), false);
+    let constructor_ref =
+        &object::create_named_object(
+            creator,
+            *string::bytes(&symbol)
+        );
 
     primary_fungible_store::create_primary_store_enabled_fungible_asset(
         constructor_ref,
@@ -301,7 +351,7 @@ Only fungible asset metadata owner can make changes.
         symbol,
         decimals,
         icon_uri,
-        project_uri,
+        project_uri
     );
 
     let mint_ref = fungible_asset::generate_mint_ref(constructor_ref);
@@ -309,26 +359,26 @@ Only fungible asset metadata owner can make changes.
     let transfer_ref = fungible_asset::generate_transfer_ref(constructor_ref);
 
     let object_signer = object::generate_signer(constructor_ref);
-    move_to(&object_signer, ManagingRefs {
-        mint_ref,
-        burn_ref,
-        transfer_ref,
-    });
+    move_to(
+        &object_signer,
+        ManagingRefs { mint_ref, burn_ref, transfer_ref }
+    );
 
     let metadata_addr = object::address_from_constructor_ref(constructor_ref);
-    event::emit(CoinCreatedEvent {
-        metadata_addr,
-    });
+    event::emit(CoinCreatedEvent { metadata_addr });
 
     let metadata = object::object_from_constructor_ref<Metadata>(constructor_ref);
-    (MintCapability { metadata }, BurnCapability { metadata }, FreezeCapability { metadata }, object::generate_extend_ref(constructor_ref))
+    (
+        MintCapability { metadata },
+        BurnCapability { metadata },
+        FreezeCapability { metadata },
+        object::generate_extend_ref(constructor_ref)
+    )
 }
 
-
- ## Function `withdraw` @@ -340,14 +390,11 @@ Only fungible asset metadata owner can make changes. -
-Implementation +##### Implementation -
public fun withdraw (
-    account: &signer,
-    metadata: Object<Metadata>,
-    amount: u64,
+
public fun withdraw(
+    account: &signer, metadata: Object<Metadata>, amount: u64
 ): FungibleAsset {
     primary_fungible_store::withdraw(account, metadata, amount)
 }
@@ -355,8 +402,6 @@ Only fungible asset metadata owner can make changes.
 
 
 
-
- ## Function `deposit` @@ -368,22 +413,16 @@ Only fungible asset metadata owner can make changes. -
-Implementation +##### Implementation -
public fun deposit (
-    account_addr: address,
-    fa: FungibleAsset,
-) {
+
public fun deposit(account_addr: address, fa: FungibleAsset) {
     primary_fungible_store::deposit(account_addr, fa)
 }
 
-
- ## Function `transfer` @@ -395,15 +434,14 @@ Only fungible asset metadata owner can make changes. -
-Implementation +##### Implementation -
public entry fun transfer (
+
public entry fun transfer(
     sender: &signer,
     recipient: address,
     metadata: Object<Metadata>,
-    amount: u64,
+    amount: u64
 ) {
     primary_fungible_store::transfer(sender, metadata, recipient, amount)
 }
@@ -411,8 +449,6 @@ Only fungible asset metadata owner can make changes.
 
 
 
-
- ## Function `mint` @@ -425,18 +461,17 @@ Mint FAs as the owner of metadat object. -
-Implementation +##### Implementation -
public fun mint(
-    mint_cap: &MintCapability,
-    amount: u64,
-): FungibleAsset acquires ManagingRefs {
+
public fun mint(mint_cap: &MintCapability, amount: u64): FungibleAsset acquires ManagingRefs {
     let metadata = mint_cap.metadata;
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
 
-    assert!(exists<ManagingRefs>(metadata_addr), ERR_MANAGING_REFS_NOT_FOUND);
+    assert!(
+        exists<ManagingRefs>(metadata_addr),
+        ERR_MANAGING_REFS_NOT_FOUND
+    );
     let refs = borrow_global<ManagingRefs>(metadata_addr);
 
     fungible_asset::mint(&refs.mint_ref, amount)
@@ -445,8 +480,6 @@ Mint FAs as the owner of metadat object.
 
 
 
-
- ## Function `mint_to` @@ -459,19 +492,19 @@ Mint FAs as the owner of metadat object to the primary fungible store of the giv -
-Implementation +##### Implementation
public fun mint_to(
-    mint_cap: &MintCapability,
-    recipient: address,
-    amount: u64,
+    mint_cap: &MintCapability, recipient: address, amount: u64
 ) acquires ManagingRefs {
     let metadata = mint_cap.metadata;
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
 
-    assert!(exists<ManagingRefs>(metadata_addr), ERR_MANAGING_REFS_NOT_FOUND);
+    assert!(
+        exists<ManagingRefs>(metadata_addr),
+        ERR_MANAGING_REFS_NOT_FOUND
+    );
     let refs = borrow_global<ManagingRefs>(metadata_addr);
 
     primary_fungible_store::mint(&refs.mint_ref, recipient, amount)
@@ -480,8 +513,6 @@ Mint FAs as the owner of metadat object to the primary fungible store of the giv
 
 
 
-
- ## Function `burn` @@ -494,18 +525,17 @@ Burn FAs as the owner of metadat object. -
-Implementation +##### Implementation -
public fun burn(
-    burn_cap: &BurnCapability,
-    fa: FungibleAsset,
-) acquires ManagingRefs {
+
public fun burn(burn_cap: &BurnCapability, fa: FungibleAsset) acquires ManagingRefs {
     let metadata = burn_cap.metadata;
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
 
-    assert!(exists<ManagingRefs>(metadata_addr), ERR_MANAGING_REFS_NOT_FOUND);
+    assert!(
+        exists<ManagingRefs>(metadata_addr),
+        ERR_MANAGING_REFS_NOT_FOUND
+    );
     let refs = borrow_global<ManagingRefs>(metadata_addr);
 
     fungible_asset::burn(&refs.burn_ref, fa)
@@ -514,8 +544,6 @@ Burn FAs as the owner of metadat object.
 
 
 
-
- ## Function `freeze_coin_store` @@ -528,28 +556,31 @@ Freeze the primary store of an account. -
-Implementation +##### Implementation
public fun freeze_coin_store(
-    freeze_cap: &FreezeCapability,
-    account_addr: address,
+    freeze_cap: &FreezeCapability, account_addr: address
 ) acquires ManagingRefs {
     let metadata = freeze_cap.metadata;
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
 
-    assert!(exists<ManagingRefs>(metadata_addr), ERR_MANAGING_REFS_NOT_FOUND);
+    assert!(
+        exists<ManagingRefs>(metadata_addr),
+        ERR_MANAGING_REFS_NOT_FOUND
+    );
     let refs = borrow_global<ManagingRefs>(metadata_addr);
 
-    primary_fungible_store::set_frozen_flag(&refs.transfer_ref, account_addr, true)
+    primary_fungible_store::set_frozen_flag(
+        &refs.transfer_ref,
+        account_addr,
+        true
+    )
 }
 
-
- ## Function `unfreeze_coin_store` @@ -562,28 +593,31 @@ Unfreeze the primary store of an account. -
-Implementation +##### Implementation
public fun unfreeze_coin_store(
-    freeze_cap: &FreezeCapability,
-    account_addr: address,
+    freeze_cap: &FreezeCapability, account_addr: address
 ) acquires ManagingRefs {
     let metadata = freeze_cap.metadata;
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
 
-    assert!(exists<ManagingRefs>(metadata_addr), ERR_MANAGING_REFS_NOT_FOUND);
+    assert!(
+        exists<ManagingRefs>(metadata_addr),
+        ERR_MANAGING_REFS_NOT_FOUND
+    );
     let refs = borrow_global<ManagingRefs>(metadata_addr);
 
-    primary_fungible_store::set_frozen_flag(&refs.transfer_ref, account_addr, false)
+    primary_fungible_store::set_frozen_flag(
+        &refs.transfer_ref,
+        account_addr,
+        false
+    )
 }
 
-
- ## Function `balance` @@ -596,8 +630,7 @@ Unfreeze the primary store of an account. -
-Implementation +##### Implementation
public fun balance(account: address, metadata: Object<Metadata>): u64 {
@@ -607,8 +640,6 @@ Unfreeze the primary store of an account.
 
 
 
-
- ## Function `is_frozen` @@ -621,8 +652,7 @@ Unfreeze the primary store of an account. -
-Implementation +##### Implementation
public fun is_frozen(account: address, metadata: Object<Metadata>): bool {
@@ -632,8 +662,6 @@ Unfreeze the primary store of an account.
 
 
 
-
- ## Function `balances` @@ -646,14 +674,11 @@ Unfreeze the primary store of an account. -
-Implementation +##### Implementation
public fun balances(
-    account: address,
-    start_after: Option<address>,
-    limit: u8,
+    account: address, start_after: Option<address>, limit: u8
 ): (vector<Object<Metadata>>, vector<u64>) {
     primary_fungible_store::balances(account, start_after, limit)
 }
@@ -661,8 +686,6 @@ Unfreeze the primary store of an account.
 
 
 
-
- ## Function `supply` @@ -676,8 +699,7 @@ Get the current supply from the metadata object. -
-Implementation +##### Implementation
public fun supply(metadata: Object<Metadata>): Option<u128> {
@@ -687,8 +709,6 @@ Get the current supply from the metadata object.
 
 
 
-
- ## Function `maximum` @@ -702,8 +722,7 @@ Get the maximum supply from the metadata object. -
-Implementation +##### Implementation
public fun maximum(metadata: Object<Metadata>): Option<u128> {
@@ -713,8 +732,6 @@ Get the maximum supply from the metadata object.
 
 
 
-
- ## Function `name` @@ -728,8 +745,7 @@ Get the name of the fungible asset from the metadata object. -
-Implementation +##### Implementation
public fun name(metadata: Object<Metadata>): String {
@@ -739,8 +755,6 @@ Get the name of the fungible asset from the metadata object.
 
 
 
-
- ## Function `symbol` @@ -754,8 +768,7 @@ Get the symbol of the fungible asset from the metadata object. -
-Implementation +##### Implementation
public fun symbol(metadata: Object<Metadata>): String {
@@ -765,8 +778,6 @@ Get the symbol of the fungible asset from the metadata object.
 
 
 
-
- ## Function `decimals` @@ -780,8 +791,7 @@ Get the decimals from the metadata object. -
-Implementation +##### Implementation
public fun decimals(metadata: Object<Metadata>): u8 {
@@ -791,8 +801,6 @@ Get the decimals from the metadata object.
 
 
 
-
- ## Function `metadata_address` @@ -805,19 +813,16 @@ Get the decimals from the metadata object. -
-Implementation +##### Implementation
public fun metadata_address(creator: address, symbol: String): address {
-    object::create_object_address(creator, *string::bytes(&symbol))
+    object::create_object_address(&creator, *string::bytes(&symbol))
 }
 
-
- ## Function `metadata` @@ -830,8 +835,7 @@ Get the decimals from the metadata object. -
-Implementation +##### Implementation
public fun metadata(creator: address, symbol: String): Object<Metadata> {
@@ -841,34 +845,6 @@ Get the decimals from the metadata object.
 
 
 
-
- - - -## Function `is_coin_initialized` - - - -
#[view]
-public fun is_coin_initialized(metadata: object::Object<fungible_asset::Metadata>): bool
-
- - - -
-Implementation - - -
public fun is_coin_initialized(metadata: Object<Metadata>): bool {
-    let metadata_addr = object::object_address(metadata);
-    exists<ManagingRefs>(metadata_addr)
-}
-
- - - -
- ## Function `is_coin` @@ -881,8 +857,7 @@ Get the decimals from the metadata object. -
-Implementation +##### Implementation
public fun is_coin(metadata_addr: address): bool {
@@ -892,8 +867,6 @@ Get the decimals from the metadata object.
 
 
 
-
- ## Function `is_coin_by_symbol` @@ -906,8 +879,7 @@ Get the decimals from the metadata object. -
-Implementation +##### Implementation
public fun is_coin_by_symbol(creator: address, symbol: String): bool {
@@ -918,8 +890,6 @@ Get the decimals from the metadata object.
 
 
 
-
- ## Function `metadata_to_denom` @@ -932,12 +902,11 @@ Get the decimals from the metadata object. -
-Implementation +##### Implementation
public fun metadata_to_denom(metadata: Object<Metadata>): String {
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
     let symbol = symbol(metadata);
     let std_metadata_addr = metadata_address(@minitia_std, symbol);
 
@@ -955,8 +924,6 @@ Get the decimals from the metadata object.
 
 
 
-
- ## Function `denom_to_metadata` @@ -969,23 +936,20 @@ Get the decimals from the metadata object. -
-Implementation +##### Implementation
public fun denom_to_metadata(denom: String): Object<Metadata> {
-    let addr = if (string::length(&denom) > 5 && &b"move/" == string::bytes(&string::sub_string(&denom, 0, 5))) {
-        let len = string::length(&denom);
-        let hex_string = string::sub_string(&denom, 5, len);
-        from_bcs::to_address(hex::decode_string(&hex_string))
-    } else {
-        metadata_address(@minitia_std, denom)
-    };
+    let addr =
+        if (string::length(&denom) > 5
+            && &b"move/" == string::bytes(&string::sub_string(&denom, 0, 5))) {
+            let len = string::length(&denom);
+            let hex_string = string::sub_string(&denom, 5, len);
+            from_bcs::to_address(hex::decode_string(&hex_string))
+        } else {
+            metadata_address(@minitia_std, denom)
+        };
 
     object::address_to_object(addr)
 }
 
- - - -
diff --git a/minitia_stdlib/doc/collection.md b/minitia_stdlib/doc/collection.md index 73f535e..4949e3b 100644 --- a/minitia_stdlib/doc/collection.md +++ b/minitia_stdlib/doc/collection.md @@ -35,15 +35,11 @@ require adding the field original_name. - [Constants](#@Constants_0) - [Function `create_fixed_collection`](#0x1_collection_create_fixed_collection) - [Function `create_unlimited_collection`](#0x1_collection_create_unlimited_collection) -- [Function `create_untracked_collection`](#0x1_collection_create_untracked_collection) -- [Function `create_collection_internal`](#0x1_collection_create_collection_internal) - [Function `create_collection_address`](#0x1_collection_create_collection_address) - [Function `create_collection_seed`](#0x1_collection_create_collection_seed) - [Function `increment_supply`](#0x1_collection_increment_supply) - [Function `decrement_supply`](#0x1_collection_decrement_supply) - [Function `generate_mutator_ref`](#0x1_collection_generate_mutator_ref) -- [Function `check_collection_exists`](#0x1_collection_check_collection_exists) -- [Function `borrow`](#0x1_collection_borrow) - [Function `count`](#0x1_collection_count) - [Function `creator`](#0x1_collection_creator) - [Function `description`](#0x1_collection_description) @@ -51,7 +47,6 @@ require adding the field original_name. - [Function `uri`](#0x1_collection_uri) - [Function `nfts`](#0x1_collection_nfts) - [Function `decompose_nft_response`](#0x1_collection_decompose_nft_response) -- [Function `borrow_mut`](#0x1_collection_borrow_mut) - [Function `set_description`](#0x1_collection_set_description) - [Function `set_uri`](#0x1_collection_set_uri) @@ -80,8 +75,7 @@ Represents the common fields for a collection. -
-Fields +##### Fields
@@ -119,8 +113,6 @@ Represents the common fields for a collection.
-
- ## Struct `MutatorRef` @@ -133,8 +125,7 @@ This enables mutating description and URI by higher level services. -
-Fields +##### Fields
@@ -147,8 +138,6 @@ This enables mutating description and URI by higher level services.
-
- ## Struct `MutationEvent` @@ -163,8 +152,7 @@ directly understand the behavior in a writeset. -
-Fields +##### Fields
@@ -195,8 +183,6 @@ directly understand the behavior in a writeset.
-
- ## Resource `FixedSupply` @@ -210,8 +196,7 @@ and adding events and supply tracking to a collection. -
-Fields +##### Fields
@@ -236,8 +221,6 @@ and adding events and supply tracking to a collection.
-
- ## Resource `UnlimitedSupply` @@ -250,8 +233,7 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t -
-Fields +##### Fields
@@ -270,8 +252,6 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t
-
- ## Struct `NftResponse` @@ -283,8 +263,7 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t -
-Fields +##### Fields
@@ -303,8 +282,6 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t
-
- ## Struct `CreateCollectionEvent` @@ -317,8 +294,7 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t -
-Fields +##### Fields
@@ -343,8 +319,6 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t
-
- ## Struct `BurnEvent` @@ -357,8 +331,7 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t -
-Fields +##### Fields
@@ -383,8 +356,6 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t
-
- ## Struct `MintEvent` @@ -397,8 +368,7 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t -
-Fields +##### Fields
@@ -423,8 +393,6 @@ Unlimited supply tracker, this is useful for adding events and supply tracking t
-
- ## Constants @@ -489,6 +457,16 @@ The description is over the maximum length + + +The collection name is invalid + + +
const EINVALID_COLLECTION_NAME: u64 = 7;
+
+ + + The max supply must be positive @@ -542,8 +520,7 @@ Beyond that, it adds supply tracking with events. -
-Implementation +##### Implementation
public fun create_fixed_collection(
@@ -552,17 +529,16 @@ Beyond that, it adds supply tracking with events.
     max_supply: u64,
     name: String,
     royalty: Option<Royalty>,
-    uri: String,
+    uri: String
 ): ConstructorRef {
-    assert!(max_supply != 0, error::invalid_argument(EMAX_SUPPLY_CANNOT_BE_ZERO));
+    assert!(
+        max_supply != 0,
+        error::invalid_argument(EMAX_SUPPLY_CANNOT_BE_ZERO)
+    );
     let collection_seed = create_collection_seed(&name);
-    let constructor_ref = object::create_named_object(creator, collection_seed, false);
+    let constructor_ref = object::create_named_object(creator, collection_seed);
 
-    let supply = FixedSupply {
-        current_supply: 0,
-        max_supply,
-        total_minted: 0,
-    };
+    let supply = FixedSupply { current_supply: 0, max_supply, total_minted: 0 };
 
     create_collection_internal(
         creator,
@@ -571,15 +547,13 @@ Beyond that, it adds supply tracking with events.
         name,
         royalty,
         uri,
-        option::some(supply),
+        option::some(supply)
     )
 }
 
-
- ## Function `create_unlimited_collection` @@ -593,8 +567,7 @@ the supply of nfts. -
-Implementation +##### Implementation
public fun create_unlimited_collection(
@@ -602,15 +575,12 @@ the supply of nfts.
     description: String,
     name: String,
     royalty: Option<Royalty>,
-    uri: String,
+    uri: String
 ): ConstructorRef {
     let collection_seed = create_collection_seed(&name);
-    let constructor_ref = object::create_named_object(creator, collection_seed, false);
+    let constructor_ref = object::create_named_object(creator, collection_seed);
 
-    let supply = UnlimitedSupply {
-        current_supply: 0,
-        total_minted: 0,
-    };
+    let supply = UnlimitedSupply { current_supply: 0, total_minted: 0 };
 
     create_collection_internal(
         creator,
@@ -619,122 +589,13 @@ the supply of nfts.
         name,
         royalty,
         uri,
-        option::some(supply),
-    )
-}
-
- - - -
- - - -## Function `create_untracked_collection` - -Creates an untracked collection, or a collection that supports an arbitrary amount of -nfts. This is useful for mass airdrops that fully leverage Aptos parallelization. -TODO: Hide this until we bring back meaningful way to enforce burns - - -
fun create_untracked_collection(creator: &signer, description: string::String, name: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
-
- - - -
-Implementation - - -
fun create_untracked_collection(
-    creator: &signer,
-    description: String,
-    name: String,
-    royalty: Option<Royalty>,
-    uri: String,
-): ConstructorRef {
-    let collection_seed = create_collection_seed(&name);
-    let constructor_ref = object::create_named_object(creator, collection_seed, false);
-
-    create_collection_internal<FixedSupply>(
-        creator,
-        constructor_ref,
-        description,
-        name,
-        royalty,
-        uri,
-        option::none(),
+        option::some(supply)
     )
 }
 
-
- - - -## Function `create_collection_internal` - - - -
fun create_collection_internal<Supply: key>(creator: &signer, constructor_ref: object::ConstructorRef, description: string::String, name: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String, supply: option::Option<Supply>): object::ConstructorRef
-
- - - -
-Implementation - - -
inline fun create_collection_internal<Supply: key>(
-    creator: &signer,
-    constructor_ref: ConstructorRef,
-    description: String,
-    name: String,
-    royalty: Option<Royalty>,
-    uri: String,
-    supply: Option<Supply>,
-): ConstructorRef {
-    assert!(string::length(&name) <= MAX_COLLECTION_NAME_LENGTH, error::out_of_range(ECOLLECTION_NAME_TOO_LONG));
-    assert!(string::length(&uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
-    assert!(string::length(&description) <= MAX_DESCRIPTION_LENGTH, error::out_of_range(EDESCRIPTION_TOO_LONG));
-
-    let object_signer = &object::generate_signer(&constructor_ref);
-    let creator_addr = signer::address_of(creator);
-
-    let collection = Collection {
-        creator: creator_addr,
-        description,
-        name,
-        uri,
-        nfts: table::new(),
-    };
-    move_to(object_signer, collection);
-
-    if (option::is_some(&supply)) {
-        move_to(object_signer, option::destroy_some(supply));
-        let collection_addr = signer::address_of(object_signer);
-        event::emit(CreateCollectionEvent { collection: collection_addr, creator: creator_addr, name });
-    } else {
-        option::destroy_none(supply)
-    };
-
-    if (option::is_some(&royalty)) {
-        royalty::init(&constructor_ref, option::extract(&mut royalty))
-    };
-
-    let transfer_ref = object::generate_transfer_ref(&constructor_ref);
-    object::disable_ungated_transfer(&transfer_ref);
-
-    constructor_ref
-}
-
- - - -
- ## Function `create_collection_address` @@ -747,19 +608,16 @@ Generates the collections address based upon the creators address and the collec -
-Implementation +##### Implementation
public fun create_collection_address(creator: address, name: &String): address {
-    object::create_object_address(creator, create_collection_seed(name))
+    object::create_object_address(&creator, create_collection_seed(name))
 }
 
-
- ## Function `create_collection_seed` @@ -772,20 +630,20 @@ Named objects are derived from a seed, the collection's seed is its name. -
-Implementation +##### Implementation
public fun create_collection_seed(name: &String): vector<u8> {
-    assert!(string::length(name) <= MAX_COLLECTION_NAME_LENGTH, error::out_of_range(ECOLLECTION_NAME_TOO_LONG));
+    assert!(
+        string::length(name) <= MAX_COLLECTION_NAME_LENGTH,
+        error::out_of_range(ECOLLECTION_NAME_TOO_LONG)
+    );
     *string::bytes(name)
 }
 
-
- ## Function `increment_supply` @@ -798,16 +656,13 @@ Called by nft on mint to increment supply if there's an appropriate Supply struc -
-Implementation +##### Implementation
public(friend) fun increment_supply(
-    collection: Object<Collection>,
-    token_id: String,
-    nft: address,
+    collection: Object<Collection>, token_id: String, nft: address
 ) acquires Collection, FixedSupply, UnlimitedSupply {
-    let collection_addr = object::object_address(collection);
+    let collection_addr = object::object_address(&collection);
     let collection = borrow_global_mut<Collection>(collection_addr);
     if (exists<FixedSupply>(collection_addr)) {
         let supply = borrow_global_mut<FixedSupply>(collection_addr);
@@ -815,28 +670,22 @@ Called by nft on mint to increment supply if there's an appropriate Supply struc
         supply.total_minted = supply.total_minted + 1;
         assert!(
             supply.current_supply <= supply.max_supply,
-            error::out_of_range(ECOLLECTION_SUPPLY_EXCEEDED),
+            error::out_of_range(ECOLLECTION_SUPPLY_EXCEEDED)
         );
         table::add(&mut collection.nfts, token_id, nft);
-        event::emit(
-            MintEvent { collection: collection_addr, token_id, nft },
-        );
+        event::emit(MintEvent { collection: collection_addr, token_id, nft });
     } else if (exists<UnlimitedSupply>(collection_addr)) {
         let supply = borrow_global_mut<UnlimitedSupply>(collection_addr);
         supply.current_supply = supply.current_supply + 1;
         supply.total_minted = supply.total_minted + 1;
         table::add(&mut collection.nfts, token_id, nft);
-        event::emit(
-            MintEvent { collection: collection_addr, token_id, nft },
-        );
+        event::emit(MintEvent { collection: collection_addr, token_id, nft });
     }
 }
 
-
- ## Function `decrement_supply` @@ -849,39 +698,30 @@ Called by nft on burn to decrement supply if there's an appropriate Supply struc -
-Implementation +##### Implementation
public(friend) fun decrement_supply(
-    collection: Object<Collection>,
-    token_id: String,
-    nft: address,
+    collection: Object<Collection>, token_id: String, nft: address
 ) acquires Collection, FixedSupply, UnlimitedSupply {
-    let collection_addr = object::object_address(collection);
+    let collection_addr = object::object_address(&collection);
     let collection = borrow_global_mut<Collection>(collection_addr);
     if (exists<FixedSupply>(collection_addr)) {
         let supply = borrow_global_mut<FixedSupply>(collection_addr);
         supply.current_supply = supply.current_supply - 1;
         table::remove(&mut collection.nfts, token_id);
-        event::emit(
-            BurnEvent { collection: collection_addr, token_id, nft },
-        );
+        event::emit(BurnEvent { collection: collection_addr, token_id, nft });
     } else if (exists<UnlimitedSupply>(collection_addr)) {
         let supply = borrow_global_mut<UnlimitedSupply>(collection_addr);
         supply.current_supply = supply.current_supply - 1;
         table::remove(&mut collection.nfts, token_id);
-        event::emit(
-            BurnEvent { collection: collection_addr, token_id, nft },
-        );
+        event::emit(BurnEvent { collection: collection_addr, token_id, nft });
     }
 }
 
-
- ## Function `generate_mutator_ref` @@ -894,73 +734,17 @@ Creates a MutatorRef, which gates the ability to mutate any fields that support -
-Implementation +##### Implementation
public fun generate_mutator_ref(ref: &ConstructorRef): MutatorRef {
     let object = object::object_from_constructor_ref<Collection>(ref);
-    MutatorRef { self: object::object_address(object) }
-}
-
- - - -
- - - -## Function `check_collection_exists` - - - -
fun check_collection_exists(addr: address)
-
- - - -
-Implementation - - -
inline fun check_collection_exists(addr: address) {
-    assert!(
-        exists<Collection>(addr),
-        error::not_found(ECOLLECTION_DOES_NOT_EXIST),
-    );
-}
-
- - - -
- - - -## Function `borrow` - - - -
fun borrow<T: key>(collection: object::Object<T>): &collection::Collection
-
- - - -
-Implementation - - -
inline fun borrow<T: key>(collection: Object<T>): &Collection {
-    let collection_address = object::object_address(collection);
-    check_collection_exists(collection_address);
-    borrow_global<Collection>(collection_address)
+    MutatorRef { self: object::object_address(&object) }
 }
 
-
- ## Function `count` @@ -974,12 +758,11 @@ Provides the count of the current selection if supply tracking is used -
-Implementation +##### Implementation
public fun count<T: key>(collection: Object<T>): Option<u64> acquires FixedSupply, UnlimitedSupply {
-    let collection_address = object::object_address(collection);
+    let collection_address = object::object_address(&collection);
     check_collection_exists(collection_address);
 
     if (exists<FixedSupply>(collection_address)) {
@@ -996,8 +779,6 @@ Provides the count of the current selection if supply tracking is used
 
 
 
-
- ## Function `creator` @@ -1010,8 +791,7 @@ Provides the count of the current selection if supply tracking is used -
-Implementation +##### Implementation
public fun creator<T: key>(collection: Object<T>): address acquires Collection {
@@ -1021,8 +801,6 @@ Provides the count of the current selection if supply tracking is used
 
 
 
-
- ## Function `description` @@ -1035,8 +813,7 @@ Provides the count of the current selection if supply tracking is used -
-Implementation +##### Implementation
public fun description<T: key>(collection: Object<T>): String acquires Collection {
@@ -1046,8 +823,6 @@ Provides the count of the current selection if supply tracking is used
 
 
 
-
- ## Function `name` @@ -1060,8 +835,7 @@ Provides the count of the current selection if supply tracking is used -
-Implementation +##### Implementation
public fun name<T: key>(collection: Object<T>): String acquires Collection {
@@ -1071,8 +845,6 @@ Provides the count of the current selection if supply tracking is used
 
 
 
-
- ## Function `uri` @@ -1085,8 +857,7 @@ Provides the count of the current selection if supply tracking is used -
-Implementation +##### Implementation
public fun uri<T: key>(collection: Object<T>): String acquires Collection {
@@ -1096,8 +867,6 @@ Provides the count of the current selection if supply tracking is used
 
 
 
-
- ## Function `nfts` @@ -1112,14 +881,11 @@ if start_after is not none, seach nfts in range (start_after, ...] -
-Implementation +##### Implementation
public fun nfts<T: key>(
-    collection: Object<T>,
-    start_after: Option<String>,
-    limit: u64,
+    collection: Object<T>, start_after: Option<String>, limit: u64
 ): vector<NftResponse> acquires Collection {
     let collection = borrow(collection);
 
@@ -1131,20 +897,18 @@ if start_after is not none, seach nfts in range (start_after, ...]
         &collection.nfts,
         option::none(),
         start_after,
-        2,
+        2
     );
 
     let res: vector<NftResponse> = vector[];
 
-    while (table::prepare<String, address>(&mut nfts_iter) && vector::length(&res) < (limit as u64)) {
-        let (token_id, nft) = table::next<String, address>(&mut nfts_iter);
+    while (table::prepare<String, address>(nfts_iter)
+        && vector::length(&res) < (limit as u64)) {
+        let (token_id, nft) = table::next<String, address>(nfts_iter);
 
         vector::push_back(
             &mut res,
-            NftResponse {
-                token_id,
-                nft: *nft,
-            },
+            NftResponse { token_id, nft: *nft }
         );
     };
 
@@ -1154,8 +918,6 @@ if start_after is not none, seach nfts in range (start_after, ...]
 
 
 
-
- ## Function `decompose_nft_response` @@ -1167,8 +929,7 @@ if start_after is not none, seach nfts in range (start_after, ...] -
-Implementation +##### Implementation
public fun decompose_nft_response(nft_response: &NftResponse): (String, address) {
@@ -1178,33 +939,6 @@ if start_after is not none, seach nfts in range (start_after, ...]
 
 
 
-
- - - -## Function `borrow_mut` - - - -
fun borrow_mut(mutator_ref: &collection::MutatorRef): &mut collection::Collection
-
- - - -
-Implementation - - -
inline fun borrow_mut(mutator_ref: &MutatorRef): &mut Collection {
-    check_collection_exists(mutator_ref.self);
-    borrow_global_mut<Collection>(mutator_ref.self)
-}
-
- - - -
- ## Function `set_description` @@ -1216,12 +950,16 @@ if start_after is not none, seach nfts in range (start_after, ...] -
-Implementation +##### Implementation -
public fun set_description(mutator_ref: &MutatorRef, description: String) acquires Collection {
-    assert!(string::length(&description) <= MAX_DESCRIPTION_LENGTH, error::out_of_range(EDESCRIPTION_TOO_LONG));
+
public fun set_description(
+    mutator_ref: &MutatorRef, description: String
+) acquires Collection {
+    assert!(
+        string::length(&description) <= MAX_DESCRIPTION_LENGTH,
+        error::out_of_range(EDESCRIPTION_TOO_LONG)
+    );
     let collection = borrow_mut(mutator_ref);
     event::emit(
         MutationEvent {
@@ -1229,7 +967,7 @@ if start_after is not none, seach nfts in range (start_after, ...]
             mutated_field_name: string::utf8(b"description"),
             old_value: collection.description,
             new_value: description
-        },
+        }
     );
     collection.description = description;
 }
@@ -1237,8 +975,6 @@ if start_after is not none, seach nfts in range (start_after, ...]
 
 
 
-
- ## Function `set_uri` @@ -1250,12 +986,14 @@ if start_after is not none, seach nfts in range (start_after, ...] -
-Implementation +##### Implementation
public fun set_uri(mutator_ref: &MutatorRef, uri: String) acquires Collection {
-    assert!(string::length(&uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
+    assert!(
+        string::length(&uri) <= MAX_URI_LENGTH,
+        error::out_of_range(EURI_TOO_LONG)
+    );
     let collection = borrow_mut(mutator_ref);
     event::emit(
         MutationEvent {
@@ -1263,12 +1001,8 @@ if start_after is not none, seach nfts in range (start_after, ...]
             mutated_field_name: string::utf8(b"uri"),
             old_value: collection.uri,
             new_value: uri
-        },
+        }
     );
     collection.uri = uri;
 }
 
- - - -
diff --git a/minitia_stdlib/doc/comparator.md b/minitia_stdlib/doc/comparator.md index f62a107..59afdc2 100644 --- a/minitia_stdlib/doc/comparator.md +++ b/minitia_stdlib/doc/comparator.md @@ -31,8 +31,7 @@ Provides a framework for comparing two elements -
-Fields +##### Fields
@@ -45,8 +44,6 @@ Provides a framework for comparing two elements
-
- ## Constants @@ -90,8 +87,7 @@ Provides a framework for comparing two elements -
-Implementation +##### Implementation
public fun is_equal(result: &Result): bool {
@@ -101,8 +97,6 @@ Provides a framework for comparing two elements
 
 
 
-
- ## Function `is_smaller_than` @@ -114,8 +108,7 @@ Provides a framework for comparing two elements -
-Implementation +##### Implementation
public fun is_smaller_than(result: &Result): bool {
@@ -125,8 +118,6 @@ Provides a framework for comparing two elements
 
 
 
-
- ## Function `is_greater_than` @@ -138,8 +129,7 @@ Provides a framework for comparing two elements -
-Implementation +##### Implementation
public fun is_greater_than(result: &Result): bool {
@@ -149,8 +139,6 @@ Provides a framework for comparing two elements
 
 
 
-
- ## Function `compare` @@ -162,8 +150,7 @@ Provides a framework for comparing two elements -
-Implementation +##### Implementation
public fun compare<T>(left: &T, right: &T): Result {
@@ -176,8 +163,6 @@ Provides a framework for comparing two elements
 
 
 
-
- ## Function `compare_u8_vector` @@ -189,8 +174,7 @@ Provides a framework for comparing two elements -
-Implementation +##### Implementation
public fun compare_u8_vector(left: vector<u8>, right: vector<u8>): Result {
@@ -220,7 +204,3 @@ Provides a framework for comparing two elements
     }
 }
 
- - - -
diff --git a/minitia_stdlib/doc/copyable_any.md b/minitia_stdlib/doc/copyable_any.md index 36ce028..ae04079 100644 --- a/minitia_stdlib/doc/copyable_any.md +++ b/minitia_stdlib/doc/copyable_any.md @@ -33,8 +33,7 @@ The same as any::Any but with the -
-Fields +##### Fields
@@ -53,8 +52,6 @@ The same as any::Any but with the
-
- ## Constants @@ -83,8 +80,7 @@ also required from T. -
-Implementation +##### Implementation
public fun pack<T: drop + store + copy>(x: T): Any {
@@ -97,8 +93,6 @@ also required from T.
 
 
 
-
- ## Function `unpack` @@ -111,20 +105,20 @@ Unpack a value from the Any -
-Implementation +##### Implementation
public fun unpack<T>(x: Any): T {
-    assert!(type_info::type_name<T>() == x.type_name, error::invalid_argument(ETYPE_MISMATCH));
+    assert!(
+        type_info::type_name<T>() == x.type_name,
+        error::invalid_argument(ETYPE_MISMATCH)
+    );
     from_bytes<T>(x.data)
 }
 
-
- ## Function `type_name` @@ -137,15 +131,10 @@ Returns the type name of this Any -
-Implementation +##### Implementation
public fun type_name(x: &Any): &String {
     &x.type_name
 }
 
- - - -
diff --git a/minitia_stdlib/doc/cosmos.md b/minitia_stdlib/doc/cosmos.md index 8ddb7ce..689c9ba 100644 --- a/minitia_stdlib/doc/cosmos.md +++ b/minitia_stdlib/doc/cosmos.md @@ -7,6 +7,7 @@ This module provides interfaces to allow CosmosMessage execution after the move execution finished. +- [Struct `VoteRequest`](#0x1_cosmos_VoteRequest) - [Function `stargate_vote`](#0x1_cosmos_stargate_vote) - [Function `stargate`](#0x1_cosmos_stargate) - [Function `move_execute`](#0x1_cosmos_move_execute) @@ -18,28 +19,66 @@ execution after the move execution finished. - [Function `transfer`](#0x1_cosmos_transfer) - [Function `nft_transfer`](#0x1_cosmos_nft_transfer) - [Function `pay_fee`](#0x1_cosmos_pay_fee) -- [Function `stargate_internal`](#0x1_cosmos_stargate_internal) -- [Function `move_execute_internal`](#0x1_cosmos_move_execute_internal) -- [Function `move_script_internal`](#0x1_cosmos_move_script_internal) -- [Function `delegate_internal`](#0x1_cosmos_delegate_internal) -- [Function `fund_community_pool_internal`](#0x1_cosmos_fund_community_pool_internal) -- [Function `transfer_internal`](#0x1_cosmos_transfer_internal) -- [Function `nft_transfer_internal`](#0x1_cosmos_nft_transfer_internal) -- [Function `pay_fee_internal`](#0x1_cosmos_pay_fee_internal)
use 0x1::collection;
 use 0x1::fungible_asset;
 use 0x1::json;
 use 0x1::object;
-use 0x1::option;
 use 0x1::signer;
-use 0x1::simple_json;
 use 0x1::string;
 
+ + +## Struct `VoteRequest` + + + +
struct VoteRequest has copy, drop
+
+ + + +##### Fields + + +
+
+_type_: string::String +
+
+ +
+
+proposal_id: u64 +
+
+ +
+
+voter: string::String +
+
+ +
+
+option: u64 +
+
+ +
+
+metadata: string::String +
+
+ +
+
+ + ## Function `stargate_vote` @@ -51,8 +90,7 @@ execution after the move execution finished. -
-Implementation +##### Implementation
public entry fun stargate_vote(
@@ -62,54 +100,44 @@ execution after the move execution finished.
     option: u64,
     metadata: String
 ) {
-    let obj = simple_json::empty();
-    simple_json::set_object(&mut obj, option::none<String>());
-    simple_json::increase_depth(&mut obj);
-    simple_json::set_int_raw(&mut obj, option::some(string::utf8(b"proposal_id")), true, (proposal_id as u256));
-    simple_json::set_string(&mut obj, option::some(string::utf8(b"voter")), voter);
-    simple_json::set_int_raw(&mut obj, option::some(string::utf8(b"option")), true, (option as u256));
-    simple_json::set_string(&mut obj, option::some(string::utf8(b"metadata")), metadata);
-    simple_json::set_string(&mut obj, option::some(string::utf8(b"@type")), string::utf8(b"/cosmos.gov.v1.MsgVote"));
-
-    let req = json::stringify(simple_json::to_json_object(&obj));
-    stargate(sender, req);
+    stargate(
+        sender,
+        json::marshal(
+            &VoteRequest {
+                _type_: string::utf8(b"/cosmos.gov.v1.MsgVote"),
+                proposal_id,
+                voter,
+                option,
+                metadata
+            }
+        )
+    );
 }
 
-
- ## Function `stargate` -
public entry fun stargate(sender: &signer, data: string::String)
+
public entry fun stargate(sender: &signer, data: vector<u8>)
 
-
-Implementation +##### Implementation -
public entry fun stargate (
-    sender: &signer,
-    data: String,
-) {
-    stargate_internal(
-        signer::address_of(sender),
-        *string::bytes(&data),
-    )
+
public entry fun stargate(sender: &signer, data: vector<u8>) {
+    stargate_internal(signer::address_of(sender), data)
 }
 
-
- ## Function `move_execute` @@ -121,17 +149,16 @@ execution after the move execution finished. -
-Implementation +##### Implementation -
public entry fun move_execute (
+
public entry fun move_execute(
     sender: &signer,
     module_address: address,
     module_name: String,
     function_name: String,
     type_args: vector<String>,
-    args: vector<vector<u8>>,
+    args: vector<vector<u8>>
 ) {
     move_execute_internal(
         signer::address_of(sender),
@@ -140,15 +167,13 @@ execution after the move execution finished.
         *string::bytes(&function_name),
         vector::map_ref(&type_args, |v| *string::bytes(v)),
         args,
-        false,
+        false
     )
 }
 
-
- ## Function `move_execute_with_json` @@ -160,17 +185,16 @@ execution after the move execution finished. -
-Implementation +##### Implementation -
public entry fun move_execute_with_json (
+
public entry fun move_execute_with_json(
     sender: &signer,
     module_address: address,
     module_name: String,
     function_name: String,
     type_args: vector<String>,
-    args: vector<String>,
+    args: vector<String>
 ) {
     move_execute_internal(
         signer::address_of(sender),
@@ -179,15 +203,13 @@ execution after the move execution finished.
         *string::bytes(&function_name),
         vector::map_ref(&type_args, |v| *string::bytes(v)),
         vector::map_ref(&args, |v| *string::bytes(v)),
-        true,
+        true
     )
 }
 
-
- ## Function `move_script` @@ -199,30 +221,27 @@ execution after the move execution finished. -
-Implementation +##### Implementation -
public entry fun move_script (
+
public entry fun move_script(
     sender: &signer,
     code_bytes: vector<u8>,
     type_args: vector<String>,
-    args: vector<vector<u8>>,
+    args: vector<vector<u8>>
 ) {
     move_script_internal(
         signer::address_of(sender),
         code_bytes,
         vector::map_ref(&type_args, |v| *string::bytes(v)),
         args,
-        false,
+        false
     )
 }
 
-
- ## Function `move_script_with_json` @@ -234,30 +253,27 @@ execution after the move execution finished. -
-Implementation +##### Implementation -
public entry fun move_script_with_json (
+
public entry fun move_script_with_json(
     sender: &signer,
     code_bytes: vector<u8>,
     type_args: vector<String>,
-    args: vector<String>,
+    args: vector<String>
 ) {
     move_script_internal(
         signer::address_of(sender),
         code_bytes,
         vector::map_ref(&type_args, |v| *string::bytes(v)),
         vector::map_ref(&args, |v| *string::bytes(v)),
-        false,
+        true
     )
 }
 
-
- ## Function `delegate` @@ -269,29 +285,26 @@ execution after the move execution finished. -
-Implementation +##### Implementation -
public entry fun delegate (
+
public entry fun delegate(
     delegator: &signer,
     validator: String,
     metadata: Object<Metadata>,
-    amount: u64,
+    amount: u64
 ) {
     delegate_internal(
         signer::address_of(delegator),
         *string::bytes(&validator),
         &metadata,
-        amount,
+        amount
     )
 }
 
-
- ## Function `fund_community_pool` @@ -303,27 +316,22 @@ execution after the move execution finished. -
-Implementation +##### Implementation -
public entry fun fund_community_pool (
-    sender: &signer,
-    metadata: Object<Metadata>,
-    amount: u64,
+
public entry fun fund_community_pool(
+    sender: &signer, metadata: Object<Metadata>, amount: u64
 ) {
     fund_community_pool_internal(
         signer::address_of(sender),
         &metadata,
-        amount,
+        amount
     )
 }
 
-
- ## Function `transfer` @@ -337,11 +345,10 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-020-fungible-token-transfer -
-Implementation +##### Implementation -
public entry fun transfer (
+
public entry fun transfer(
     sender: &signer,
     receiver: String,
     metadata: Object<Metadata>,
@@ -351,7 +358,7 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-020-fungible-token-transfer
     revision_number: u64,
     revision_height: u64,
     timeout_timestamp: u64,
-    memo: String,
+    memo: String
 ) {
     transfer_internal(
         signer::address_of(sender),
@@ -363,15 +370,13 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-020-fungible-token-transfer
         revision_number,
         revision_height,
         timeout_timestamp,
-        *string::bytes(&memo),
+        *string::bytes(&memo)
     )
 }
 
-
- ## Function `nft_transfer` @@ -385,11 +390,10 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-721-nft-transfer -
-Implementation +##### Implementation -
public entry fun nft_transfer (
+
public entry fun nft_transfer(
     sender: &signer,
     receiver: String,
     collection: Object<Collection>,
@@ -399,7 +403,7 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-721-nft-transfer
     revision_number: u64,
     revision_height: u64,
     timeout_timestamp: u64,
-    memo: String,
+    memo: String
 ) {
     nft_transfer_internal(
         signer::address_of(sender),
@@ -411,15 +415,13 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-721-nft-transfer
         revision_number,
         revision_height,
         timeout_timestamp,
-        *string::bytes(&memo),
+        *string::bytes(&memo)
     )
 }
 
-
- ## Function `pay_fee` @@ -433,11 +435,10 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-029-fee-payment -
-Implementation +##### Implementation -
public entry fun pay_fee (
+
public entry fun pay_fee(
     sender: &signer,
     source_port: String,
     source_channel: String,
@@ -446,7 +447,7 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-029-fee-payment
     ack_fee_metadata: Object<Metadata>,
     ack_fee_amount: u64,
     timeout_fee_metadata: Object<Metadata>,
-    timeout_fee_amount: u64,
+    timeout_fee_amount: u64
 ) {
     pay_fee_internal(
         signer::address_of(sender),
@@ -457,245 +458,7 @@ https://github.com/cosmos/ibc/tree/main/spec/app/ics-029-fee-payment
         &ack_fee_metadata,
         ack_fee_amount,
         &timeout_fee_metadata,
-        timeout_fee_amount,
+        timeout_fee_amount
     )
 }
 
- - - -
- - - -## Function `stargate_internal` - - - -
fun stargate_internal(sender: address, data: vector<u8>)
-
- - - -
-Implementation - - -
native fun stargate_internal (
-    sender: address,
-    data: vector<u8>,
-);
-
- - - -
- - - -## Function `move_execute_internal` - - - -
fun move_execute_internal(sender: address, module_address: address, module_name: vector<u8>, function_name: vector<u8>, type_args: vector<vector<u8>>, args: vector<vector<u8>>, is_json: bool)
-
- - - -
-Implementation - - -
native fun move_execute_internal (
-    sender: address,
-    module_address: address,
-    module_name: vector<u8>,
-    function_name: vector<u8>,
-    type_args: vector<vector<u8>>,
-    args: vector<vector<u8>>,
-    is_json: bool,
-);
-
- - - -
- - - -## Function `move_script_internal` - - - -
fun move_script_internal(sender: address, code_bytes: vector<u8>, type_args: vector<vector<u8>>, args: vector<vector<u8>>, is_json: bool)
-
- - - -
-Implementation - - -
native fun move_script_internal (
-    sender: address,
-    code_bytes: vector<u8>,
-    type_args: vector<vector<u8>>,
-    args: vector<vector<u8>>,
-    is_json: bool,
-);
-
- - - -
- - - -## Function `delegate_internal` - - - -
fun delegate_internal(delegator: address, validator: vector<u8>, metadata: &object::Object<fungible_asset::Metadata>, amount: u64)
-
- - - -
-Implementation - - -
native fun delegate_internal (
-    delegator: address,
-    validator: vector<u8>,
-    metadata: &Object<Metadata>,
-    amount: u64,
-);
-
- - - -
- - - -## Function `fund_community_pool_internal` - - - -
fun fund_community_pool_internal(sender: address, metadata: &object::Object<fungible_asset::Metadata>, amount: u64)
-
- - - -
-Implementation - - -
native fun fund_community_pool_internal (
-    sender: address,
-    metadata: &Object<Metadata>,
-    amount: u64,
-);
-
- - - -
- - - -## Function `transfer_internal` - - - -
fun transfer_internal(sender: address, receiver: vector<u8>, metadata: &object::Object<fungible_asset::Metadata>, token_amount: u64, source_port: vector<u8>, source_channel: vector<u8>, revision_number: u64, revision_height: u64, timeout_timestamp: u64, memo: vector<u8>)
-
- - - -
-Implementation - - -
native fun transfer_internal (
-    sender: address,
-    receiver: vector<u8>,
-    metadata: &Object<Metadata>,
-    token_amount: u64,
-    source_port: vector<u8>,
-    source_channel: vector<u8>,
-    revision_number: u64,
-    revision_height: u64,
-    timeout_timestamp: u64,
-    memo: vector<u8>,
-);
-
- - - -
- - - -## Function `nft_transfer_internal` - - - -
fun nft_transfer_internal(sender: address, receiver: vector<u8>, collection: &object::Object<collection::Collection>, token_ids: vector<vector<u8>>, source_port: vector<u8>, source_channel: vector<u8>, revision_number: u64, revision_height: u64, timeout_timestamp: u64, memo: vector<u8>)
-
- - - -
-Implementation - - -
native fun nft_transfer_internal (
-    sender: address,
-    receiver: vector<u8>,
-    collection: &Object<Collection>,
-    token_ids: vector<vector<u8>>,
-    source_port: vector<u8>,
-    source_channel: vector<u8>,
-    revision_number: u64,
-    revision_height: u64,
-    timeout_timestamp: u64,
-    memo: vector<u8>,
-);
-
- - - -
- - - -## Function `pay_fee_internal` - - - -
fun pay_fee_internal(sender: address, source_port: vector<u8>, source_channel: vector<u8>, recv_fee_metadata: &object::Object<fungible_asset::Metadata>, recv_fee_amount: u64, ack_fee_metadata: &object::Object<fungible_asset::Metadata>, ack_fee_amount: u64, timeout_fee_metadata: &object::Object<fungible_asset::Metadata>, timeout_fee_amount: u64)
-
- - - -
-Implementation - - -
native fun pay_fee_internal (
-    sender: address,
-    source_port: vector<u8>,
-    source_channel: vector<u8>,
-    recv_fee_metadata: &Object<Metadata>,
-    recv_fee_amount: u64,
-    ack_fee_metadata: &Object<Metadata>,
-    ack_fee_amount: u64,
-    timeout_fee_metadata: &Object<Metadata>,
-    timeout_fee_amount: u64,
-);
-
- - - -
diff --git a/minitia_stdlib/doc/debug.md b/minitia_stdlib/doc/debug.md index 029ff17..9be477b 100644 --- a/minitia_stdlib/doc/debug.md +++ b/minitia_stdlib/doc/debug.md @@ -9,9 +9,6 @@ Module providing debug functionality. - [Constants](#@Constants_0) - [Function `print`](#0x1_debug_print) - [Function `print_stack_trace`](#0x1_debug_print_stack_trace) -- [Function `format`](#0x1_debug_format) -- [Function `native_print`](#0x1_debug_native_print) -- [Function `native_stack_trace`](#0x1_debug_native_stack_trace)
use 0x1::string;
@@ -54,8 +51,7 @@ Module providing debug functionality.
 
 
 
-
-Implementation +##### Implementation
public fun print<T>(x: &T) {
@@ -65,8 +61,6 @@ Module providing debug functionality.
 
 
 
-
- ## Function `print_stack_trace` @@ -78,83 +72,10 @@ Module providing debug functionality. -
-Implementation +##### Implementation
public fun print_stack_trace() {
     native_print(native_stack_trace());
 }
 
- - - -
- - - -## Function `format` - - - -
fun format<T>(x: &T): string::String
-
- - - -
-Implementation - - -
inline fun format<T>(x: &T): String {
-    debug_string(x)
-}
-
- - - -
- - - -## Function `native_print` - - - -
fun native_print(x: string::String)
-
- - - -
-Implementation - - -
native fun native_print(x: String);
-
- - - -
- - - -## Function `native_stack_trace` - - - -
fun native_stack_trace(): string::String
-
- - - -
-Implementation - - -
native fun native_stack_trace(): String;
-
- - - -
diff --git a/minitia_stdlib/doc/decimal128.md b/minitia_stdlib/doc/decimal128.md deleted file mode 100644 index dadd595..0000000 --- a/minitia_stdlib/doc/decimal128.md +++ /dev/null @@ -1,579 +0,0 @@ - - - -# Module `0x1::decimal128` - - - -- [Struct `Decimal128`](#0x1_decimal128_Decimal128) -- [Constants](#@Constants_0) -- [Function `new`](#0x1_decimal128_new) -- [Function `new_u64`](#0x1_decimal128_new_u64) -- [Function `one`](#0x1_decimal128_one) -- [Function `zero`](#0x1_decimal128_zero) -- [Function `from_ratio_u64`](#0x1_decimal128_from_ratio_u64) -- [Function `from_ratio`](#0x1_decimal128_from_ratio) -- [Function `add`](#0x1_decimal128_add) -- [Function `sub`](#0x1_decimal128_sub) -- [Function `mul_u64`](#0x1_decimal128_mul_u64) -- [Function `mul_u128`](#0x1_decimal128_mul_u128) -- [Function `mul`](#0x1_decimal128_mul) -- [Function `div_u64`](#0x1_decimal128_div_u64) -- [Function `div`](#0x1_decimal128_div) -- [Function `val`](#0x1_decimal128_val) -- [Function `is_same`](#0x1_decimal128_is_same) -- [Function `from_string`](#0x1_decimal128_from_string) -- [Function `pow`](#0x1_decimal128_pow) - - -
use 0x1::error;
-use 0x1::string;
-
- - - - - -## Struct `Decimal128` - -A fixed-point decimal value with 18 fractional digits, i.e. Decimal128{ val: 1_000_000_000_000_000_000 } == 1.0 - - -
struct Decimal128 has copy, drop, store
-
- - - -
-Fields - - -
-
-val: u128 -
-
- -
-
- - -
- - - -## Constants - - - - - - -
const DECIMAL_FRACTIONAL: u128 = 1000000000000000000;
-
- - - - - - - -
const EDIV_WITH_ZERO: u64 = 0;
-
- - - - - - - -
const EFAILED_TO_DESERIALIZE: u64 = 1;
-
- - - - - - - -
const EOUT_OF_RANGE: u64 = 2;
-
- - - - - - - -
const FRACTIONAL_LENGTH: u64 = 18;
-
- - - - - - - -
const MAX_INTEGER_PART: u128 = 340282366920938463463;
-
- - - - - -## Function `new` - - - -
public fun new(val: u128): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun new(val: u128): Decimal128 {
-    Decimal128 { val }
-}
-
- - - -
- - - -## Function `new_u64` - - - -
public fun new_u64(val: u64): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun new_u64(val: u64): Decimal128 {
-    Decimal128 { val: (val as u128) }
-}
-
- - - -
- - - -## Function `one` - - - -
public fun one(): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun one(): Decimal128 {
-    Decimal128 { val: DECIMAL_FRACTIONAL }
-}
-
- - - -
- - - -## Function `zero` - - - -
public fun zero(): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun zero(): Decimal128 {
-    Decimal128 { val: 0 }
-}
-
- - - -
- - - -## Function `from_ratio_u64` - - - -
public fun from_ratio_u64(numerator: u64, denominator: u64): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun from_ratio_u64(numerator: u64, denominator: u64): Decimal128 {
-    assert!(denominator != 0, EDIV_WITH_ZERO);
-
-    new((numerator as u128) * DECIMAL_FRACTIONAL / (denominator as u128))
-}
-
- - - -
- - - -## Function `from_ratio` - - - -
public fun from_ratio(numerator: u128, denominator: u128): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun from_ratio(numerator: u128, denominator: u128): Decimal128 {
-    assert!(denominator != 0, EDIV_WITH_ZERO);
-
-    new(numerator * DECIMAL_FRACTIONAL / denominator)
-}
-
- - - -
- - - -## Function `add` - - - -
public fun add(left: &decimal128::Decimal128, right: &decimal128::Decimal128): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun add(left: &Decimal128, right: &Decimal128): Decimal128 {
-    new(left.val + right.val)
-}
-
- - - -
- - - -## Function `sub` - - - -
public fun sub(left: &decimal128::Decimal128, right: &decimal128::Decimal128): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun sub(left: &Decimal128, right: &Decimal128): Decimal128 {
-    new(left.val - right.val)
-}
-
- - - -
- - - -## Function `mul_u64` - - - -
public fun mul_u64(decimal: &decimal128::Decimal128, val: u64): u64
-
- - - -
-Implementation - - -
public fun mul_u64(decimal: &Decimal128, val: u64): u64 {
-    (decimal.val * (val as u128) / DECIMAL_FRACTIONAL as u64)
-}
-
- - - -
- - - -## Function `mul_u128` - - - -
public fun mul_u128(decimal: &decimal128::Decimal128, val: u128): u128
-
- - - -
-Implementation - - -
public fun mul_u128(decimal: &Decimal128, val: u128): u128 {
-   decimal.val * val / DECIMAL_FRACTIONAL
-}
-
- - - -
- - - -## Function `mul` - - - -
public fun mul(a: &decimal128::Decimal128, b: &decimal128::Decimal128): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun mul(a: &Decimal128, b: &Decimal128): Decimal128 {
-    new(a.val * b.val / DECIMAL_FRACTIONAL)
-}
-
- - - -
- - - -## Function `div_u64` - - - -
public fun div_u64(decimal: &decimal128::Decimal128, val: u64): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun div_u64(decimal: &Decimal128, val: u64): Decimal128 {
-    new(decimal.val / (val as u128))
-}
-
- - - -
- - - -## Function `div` - - - -
public fun div(decimal: &decimal128::Decimal128, val: u128): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun div(decimal: &Decimal128, val: u128): Decimal128 {
-    new(decimal.val / val)
-}
-
- - - -
- - - -## Function `val` - - - -
public fun val(decimal: &decimal128::Decimal128): u128
-
- - - -
-Implementation - - -
public fun val(decimal: &Decimal128): u128 {
-    decimal.val
-}
-
- - - -
- - - -## Function `is_same` - - - -
public fun is_same(left: &decimal128::Decimal128, right: &decimal128::Decimal128): bool
-
- - - -
-Implementation - - -
public fun is_same(left: &Decimal128, right: &Decimal128): bool {
-    left.val == right.val
-}
-
- - - -
- - - -## Function `from_string` - - - -
public fun from_string(num: &string::String): decimal128::Decimal128
-
- - - -
-Implementation - - -
public fun from_string(num: &String): Decimal128 {
-    let vec = string::bytes(num);
-    let len = vector::length(vec);
-
-    let cursor = 0;
-    let dot_index = 0;
-    let val: u128 = 0;
-    while (cursor < len) {
-        let s = *vector::borrow(vec, cursor);
-        cursor = cursor + 1;
-
-        // find `.` position
-        if (s == 46) continue;
-
-        val = val * 10;
-        assert!(s >= 48 && s <= 57, error::invalid_argument(EFAILED_TO_DESERIALIZE));
-
-        let n = (s - 48 as u128);
-        val = val + n;
-
-        if (cursor == dot_index + 1) {
-            // use `<` not `<=` to safely check "out of range"
-            // (i.e. to avoid fractional part checking)
-            assert!(val < MAX_INTEGER_PART, error::invalid_argument(EOUT_OF_RANGE));
-
-            dot_index = dot_index + 1;
-        };
-    };
-
-    // ignore fractional part longer than `FRACTIONAL_LENGTH`
-    let val = if (dot_index == len) {
-        val * pow(10, FRACTIONAL_LENGTH)
-    } else {
-        let fractional_length = len - dot_index - 1;
-        if (fractional_length > FRACTIONAL_LENGTH) {
-            val / pow(10, fractional_length - FRACTIONAL_LENGTH)
-        } else {
-            val * pow(10, FRACTIONAL_LENGTH - fractional_length)
-        }
-    };
-
-    new(val)
-}
-
- - - -
- - - -## Function `pow` - - - -
fun pow(num: u128, pow_amount: u64): u128
-
- - - -
-Implementation - - -
fun pow(num: u128, pow_amount: u64): u128 {
-    let index = 0;
-    let val = 1;
-    while (index < pow_amount) {
-        val = val * num;
-        index = index + 1;
-    };
-
-    val
-}
-
- - - -
diff --git a/minitia_stdlib/doc/decimal256.md b/minitia_stdlib/doc/decimal256.md deleted file mode 100644 index bb0add4..0000000 --- a/minitia_stdlib/doc/decimal256.md +++ /dev/null @@ -1,681 +0,0 @@ - - - -# Module `0x1::decimal256` - - - -- [Struct `Decimal256`](#0x1_decimal256_Decimal256) -- [Constants](#@Constants_0) -- [Function `new`](#0x1_decimal256_new) -- [Function `new_u64`](#0x1_decimal256_new_u64) -- [Function `new_u128`](#0x1_decimal256_new_u128) -- [Function `one`](#0x1_decimal256_one) -- [Function `zero`](#0x1_decimal256_zero) -- [Function `from_ratio_u64`](#0x1_decimal256_from_ratio_u64) -- [Function `from_ratio_u128`](#0x1_decimal256_from_ratio_u128) -- [Function `from_ratio`](#0x1_decimal256_from_ratio) -- [Function `add`](#0x1_decimal256_add) -- [Function `sub`](#0x1_decimal256_sub) -- [Function `mul_u64`](#0x1_decimal256_mul_u64) -- [Function `mul_u128`](#0x1_decimal256_mul_u128) -- [Function `mul_u256`](#0x1_decimal256_mul_u256) -- [Function `mul`](#0x1_decimal256_mul) -- [Function `div_u64`](#0x1_decimal256_div_u64) -- [Function `div_u128`](#0x1_decimal256_div_u128) -- [Function `div`](#0x1_decimal256_div) -- [Function `val`](#0x1_decimal256_val) -- [Function `is_same`](#0x1_decimal256_is_same) -- [Function `from_string`](#0x1_decimal256_from_string) -- [Function `pow`](#0x1_decimal256_pow) - - -
use 0x1::error;
-use 0x1::string;
-
- - - - - -## Struct `Decimal256` - -A fixed-point decimal value with 18 fractional digits, i.e. Decimal256{ val: 1_000_000_000_000_000_000 } == 1.0 - - -
struct Decimal256 has copy, drop, store
-
- - - -
-Fields - - -
-
-val: u256 -
-
- -
-
- - -
- - - -## Constants - - - - - - -
const DECIMAL_FRACTIONAL: u256 = 1000000000000000000;
-
- - - - - - - -
const EDIV_WITH_ZERO: u64 = 0;
-
- - - - - - - -
const EFAILED_TO_DESERIALIZE: u64 = 1;
-
- - - - - - - -
const EOUT_OF_RANGE: u64 = 2;
-
- - - - - - - -
const FRACTIONAL_LENGTH: u64 = 18;
-
- - - - - - - -
const MAX_INTEGER_PART: u256 = 115792089237316195423570985008687907853269984665640564039457;
-
- - - - - -## Function `new` - - - -
public fun new(val: u256): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun new(val: u256): Decimal256 {
-    Decimal256 { val }
-}
-
- - - -
- - - -## Function `new_u64` - - - -
public fun new_u64(val: u64): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun new_u64(val: u64): Decimal256 {
-    Decimal256 { val: (val as u256) }
-}
-
- - - -
- - - -## Function `new_u128` - - - -
public fun new_u128(val: u128): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun new_u128(val: u128): Decimal256 {
-    Decimal256 { val: (val as u256) }
-}
-
- - - -
- - - -## Function `one` - - - -
public fun one(): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun one(): Decimal256 {
-    Decimal256 { val: DECIMAL_FRACTIONAL }
-}
-
- - - -
- - - -## Function `zero` - - - -
public fun zero(): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun zero(): Decimal256 {
-    Decimal256 { val: 0 }
-}
-
- - - -
- - - -## Function `from_ratio_u64` - - - -
public fun from_ratio_u64(numerator: u64, denominator: u64): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun from_ratio_u64(numerator: u64, denominator: u64): Decimal256 {
-    assert!(denominator != 0, EDIV_WITH_ZERO);
-
-    new((numerator as u256) * DECIMAL_FRACTIONAL / (denominator as u256))
-}
-
- - - -
- - - -## Function `from_ratio_u128` - - - -
public fun from_ratio_u128(numerator: u128, denominator: u128): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun from_ratio_u128(numerator: u128, denominator: u128): Decimal256 {
-    assert!(denominator != 0, EDIV_WITH_ZERO);
-
-    new((numerator as u256) * DECIMAL_FRACTIONAL / (denominator as u256))
-}
-
- - - -
- - - -## Function `from_ratio` - - - -
public fun from_ratio(numerator: u256, denominator: u256): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun from_ratio(numerator: u256, denominator: u256): Decimal256 {
-    assert!(denominator != 0, EDIV_WITH_ZERO);
-
-    new(numerator * DECIMAL_FRACTIONAL / denominator)
-}
-
- - - -
- - - -## Function `add` - - - -
public fun add(left: &decimal256::Decimal256, right: &decimal256::Decimal256): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun add(left: &Decimal256, right: &Decimal256): Decimal256 {
-    new(left.val + right.val)
-}
-
- - - -
- - - -## Function `sub` - - - -
public fun sub(left: &decimal256::Decimal256, right: &decimal256::Decimal256): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun sub(left: &Decimal256, right: &Decimal256): Decimal256 {
-    new(left.val - right.val)
-}
-
- - - -
- - - -## Function `mul_u64` - - - -
public fun mul_u64(decimal: &decimal256::Decimal256, val: u64): u64
-
- - - -
-Implementation - - -
public fun mul_u64(decimal: &Decimal256, val: u64): u64 {
-    (decimal.val * (val as u256) / DECIMAL_FRACTIONAL as u64)
-}
-
- - - -
- - - -## Function `mul_u128` - - - -
public fun mul_u128(decimal: &decimal256::Decimal256, val: u128): u128
-
- - - -
-Implementation - - -
public fun mul_u128(decimal: &Decimal256, val: u128): u128 {
-    (decimal.val * (val as u256) / DECIMAL_FRACTIONAL as u128)
-}
-
- - - -
- - - -## Function `mul_u256` - - - -
public fun mul_u256(decimal: &decimal256::Decimal256, val: u256): u256
-
- - - -
-Implementation - - -
public fun mul_u256(decimal: &Decimal256, val: u256): u256 {
-    decimal.val * val / DECIMAL_FRACTIONAL
-}
-
- - - -
- - - -## Function `mul` - - - -
public fun mul(a: &decimal256::Decimal256, b: &decimal256::Decimal256): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun mul(a: &Decimal256, b: &Decimal256): Decimal256 {
-    new(a.val * b.val / DECIMAL_FRACTIONAL)
-}
-
- - - -
- - - -## Function `div_u64` - - - -
public fun div_u64(decimal: &decimal256::Decimal256, val: u64): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun div_u64(decimal: &Decimal256, val: u64): Decimal256 {
-    new(decimal.val / (val as u256))
-}
-
- - - -
- - - -## Function `div_u128` - - - -
public fun div_u128(decimal: &decimal256::Decimal256, val: u128): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun div_u128(decimal: &Decimal256, val: u128): Decimal256 {
-    new(decimal.val / (val as u256))
-}
-
- - - -
- - - -## Function `div` - - - -
public fun div(decimal: &decimal256::Decimal256, val: u256): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun div(decimal: &Decimal256, val: u256): Decimal256 {
-    new(decimal.val / val)
-}
-
- - - -
- - - -## Function `val` - - - -
public fun val(decimal: &decimal256::Decimal256): u256
-
- - - -
-Implementation - - -
public fun val(decimal: &Decimal256): u256 {
-    decimal.val
-}
-
- - - -
- - - -## Function `is_same` - - - -
public fun is_same(left: &decimal256::Decimal256, right: &decimal256::Decimal256): bool
-
- - - -
-Implementation - - -
public fun is_same(left: &Decimal256, right: &Decimal256): bool {
-    left.val == right.val
-}
-
- - - -
- - - -## Function `from_string` - - - -
public fun from_string(num: &string::String): decimal256::Decimal256
-
- - - -
-Implementation - - -
public fun from_string(num: &String): Decimal256 {
-    let vec = string::bytes(num);
-    let len = vector::length(vec);
-
-    let cursor = 0;
-    let dot_index = 0;
-    let val: u256 = 0;
-    while (cursor < len) {
-        let s = *vector::borrow(vec, cursor);
-        cursor = cursor + 1;
-
-        // find `.` position
-        if (s == 46) continue;
-
-        val = val * 10;
-        assert!(s >= 48 && s <= 57, error::invalid_argument(EFAILED_TO_DESERIALIZE));
-
-        let n = (s - 48 as u256);
-        val = val + n;
-
-        if (cursor == dot_index + 1) {
-            // use `<` not `<=` to safely check "out of range"
-            // (i.e. to avoid fractional part checking)
-            assert!(val < MAX_INTEGER_PART, error::invalid_argument(EOUT_OF_RANGE));
-
-            dot_index = dot_index + 1;
-        };
-    };
-
-    // ignore fractional part longer than `FRACTIONAL_LENGTH`
-    let val = if (dot_index == len) {
-        val * pow(10, FRACTIONAL_LENGTH)
-    } else {
-        let fractional_length = len - dot_index - 1;
-        if (fractional_length > FRACTIONAL_LENGTH) {
-            val / pow(10, fractional_length - FRACTIONAL_LENGTH)
-        } else {
-            val * pow(10, FRACTIONAL_LENGTH - fractional_length)
-        }
-    };
-
-    new(val)
-}
-
- - - -
- - - -## Function `pow` - - - -
fun pow(num: u256, pow_amount: u64): u256
-
- - - -
-Implementation - - -
fun pow(num: u256, pow_amount: u64): u256 {
-    let index = 0;
-    let val = 1;
-    while (index < pow_amount) {
-        val = val * num;
-        index = index + 1;
-    };
-
-    val
-}
-
- - - -
diff --git a/minitia_stdlib/doc/dex.md b/minitia_stdlib/doc/dex.md index a4b2e56..3022e9a 100644 --- a/minitia_stdlib/doc/dex.md +++ b/minitia_stdlib/doc/dex.md @@ -54,8 +54,6 @@ - [Function `get_timestamp_from_weight`](#0x1_dex_get_timestamp_from_weight) - [Function `unpack_pair_response`](#0x1_dex_unpack_pair_response) - [Function `unpack_current_weight_response`](#0x1_dex_unpack_current_weight_response) -- [Function `check_chain_permission`](#0x1_dex_check_chain_permission) -- [Function `init_module`](#0x1_dex_init_module) - [Function `create_pair_script`](#0x1_dex_create_pair_script) - [Function `create_lbp_pair_script`](#0x1_dex_create_lbp_pair_script) - [Function `update_swap_fee_rate`](#0x1_dex_update_swap_fee_rate) @@ -69,22 +67,16 @@ - [Function `swap`](#0x1_dex_swap) - [Function `create_pair`](#0x1_dex_create_pair) - [Function `provide_liquidity`](#0x1_dex_provide_liquidity) -- [Function `coin_address`](#0x1_dex_coin_address) -- [Function `check_lbp_ended`](#0x1_dex_check_lbp_ended) -- [Function `generate_pair_key`](#0x1_dex_generate_pair_key) -- [Function `get_weight`](#0x1_dex_get_weight) - [Function `pool_info`](#0x1_dex_pool_info) - [Function `swap_simulation`](#0x1_dex_swap_simulation) - [Function `swap_simulation_given_out`](#0x1_dex_swap_simulation_given_out) - [Function `pool_metadata`](#0x1_dex_pool_metadata) -- [Function `pow`](#0x1_dex_pow) -- [Function `ln`](#0x1_dex_ln) -- [Function `mul_decimal128s`](#0x1_dex_mul_decimal128s) -
use 0x1::block;
+
use 0x1::bigdecimal;
+use 0x1::biguint;
+use 0x1::block;
 use 0x1::coin;
-use 0x1::decimal128;
 use 0x1::error;
 use 0x1::event;
 use 0x1::fungible_asset;
@@ -110,8 +102,7 @@ Pool configuration
 
 
 
-
-Fields +##### Fields
@@ -128,7 +119,7 @@ Pool configuration
-swap_fee_rate: decimal128::Decimal128 +swap_fee_rate: bigdecimal::BigDecimal
@@ -136,8 +127,6 @@ Pool configuration
-
- ## Resource `Pool` @@ -149,8 +138,7 @@ Pool configuration -
-Fields +##### Fields
@@ -169,8 +157,6 @@ Pool configuration
-
- ## Struct `Weights` @@ -182,8 +168,7 @@ Pool configuration -
-Fields +##### Fields
@@ -202,8 +187,6 @@ Pool configuration
-
- ## Struct `Weight` @@ -215,25 +198,24 @@ Pool configuration -
-Fields +##### Fields
-coin_a_weight: decimal128::Decimal128 +coin_a_weight: bigdecimal::BigDecimal
-coin_b_weight: decimal128::Decimal128 +coin_b_weight: bigdecimal::BigDecimal
-timestamp: u64 +timestamp: u64
@@ -241,8 +223,6 @@ Pool configuration
-
- ## Struct `PairKey` @@ -255,8 +235,7 @@ Key for pair -
-Fields +##### Fields
@@ -281,8 +260,6 @@ Key for pair
-
- ## Struct `PairResponse` @@ -294,8 +271,7 @@ Key for pair -
-Fields +##### Fields
@@ -324,7 +300,7 @@ Key for pair
-swap_fee_rate: decimal128::Decimal128 +swap_fee_rate: bigdecimal::BigDecimal
@@ -332,8 +308,6 @@ Key for pair
-
- ## Struct `PairByDenomResponse` @@ -345,8 +319,7 @@ Key for pair -
-Fields +##### Fields
@@ -375,7 +348,7 @@ Key for pair
-swap_fee_rate: decimal128::Decimal128 +swap_fee_rate: bigdecimal::BigDecimal
@@ -383,8 +356,6 @@ Key for pair
-
- ## Resource `CoinCapabilities` @@ -397,8 +368,7 @@ Coin capabilities -
-Fields +##### Fields
@@ -423,8 +393,6 @@ Coin capabilities
-
- ## Struct `ProvideEvent` @@ -438,8 +406,7 @@ Event emitted when provide liquidity. -
-Fields +##### Fields
@@ -482,8 +449,6 @@ Event emitted when provide liquidity.
-
- ## Struct `WithdrawEvent` @@ -497,8 +462,7 @@ Event emitted when withdraw liquidity. -
-Fields +##### Fields
@@ -541,8 +505,6 @@ Event emitted when withdraw liquidity.
-
- ## Struct `SwapEvent` @@ -556,8 +518,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -600,8 +561,6 @@ Event emitted when swap token.
-
- ## Struct `SingleAssetProvideEvent` @@ -614,8 +573,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -664,8 +622,6 @@ Event emitted when swap token.
-
- ## Struct `PoolInfoResponse` @@ -677,8 +633,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -703,8 +658,6 @@ Event emitted when swap token.
-
- ## Struct `ConfigResponse` @@ -716,8 +669,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -728,7 +680,7 @@ Event emitted when swap token.
-swap_fee_rate: decimal128::Decimal128 +swap_fee_rate: bigdecimal::BigDecimal
@@ -736,8 +688,6 @@ Event emitted when swap token.
-
- ## Struct `CurrentWeightResponse` @@ -749,19 +699,18 @@ Event emitted when swap token. -
-Fields +##### Fields
-coin_a_weight: decimal128::Decimal128 +coin_a_weight: bigdecimal::BigDecimal
-coin_b_weight: decimal128::Decimal128 +coin_b_weight: bigdecimal::BigDecimal
@@ -769,8 +718,6 @@ Event emitted when swap token.
-
- ## Struct `PairMetadataResponse` @@ -782,8 +729,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -802,8 +748,6 @@ Event emitted when swap token.
-
- ## Struct `PairDenomResponse` @@ -815,8 +759,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -835,8 +778,6 @@ Event emitted when swap token.
-
- ## Struct `CreatePairEvent` @@ -849,8 +790,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -879,7 +819,7 @@ Event emitted when swap token.
-swap_fee_rate: decimal128::Decimal128 +swap_fee_rate: bigdecimal::BigDecimal
@@ -887,8 +827,6 @@ Event emitted when swap token.
-
- ## Struct `SwapFeeUpdateEvent` @@ -901,8 +839,7 @@ Event emitted when swap token. -
-Fields +##### Fields
@@ -925,7 +862,7 @@ Event emitted when swap token.
-swap_fee_rate: decimal128::Decimal128 +swap_fee_rate: bigdecimal::BigDecimal
@@ -933,8 +870,6 @@ Event emitted when swap token.
-
- ## Resource `ModuleStore` @@ -947,8 +882,7 @@ Module store for storing pair infos -
-Fields +##### Fields
@@ -967,13 +901,21 @@ Module store for storing pair infos
-
- ## Constants + + +Only chain can execute. + + +
const EUNAUTHORIZED: u64 = 7;
+
+ + + Wrong coin type given @@ -984,6 +926,16 @@ Wrong coin type given + + +Weights sum must be 1.0 + + +
const EINVALID_WEIGHTS: u64 = 21;
+
+ + + LBP is not ended, only swap allowed @@ -1093,16 +1045,6 @@ All start_after must be provided or not - - -Only chain can execute. - - -
const EUNAUTHORIZED: u64 = 7;
-
- - - end time must be larger than start time @@ -1113,21 +1055,22 @@ end time must be larger than start time - + -Can not withdraw zero liquidity +Zero amount in the swap simulation is not allowed -
const EZERO_LIQUIDITY: u64 = 2;
+
const EZERO_AMOUNT_IN: u64 = 20;
 
- + +Can not withdraw zero liquidity -
const MAX_FEE_RATE: u128 = 50000000000000000;
+
const EZERO_LIQUIDITY: u64 = 2;
 
@@ -1146,7 +1089,7 @@ Can not withdraw zero liquidity Result Precision of pow and ln function -
const PRECISION: u128 = 100000;
+
const PRECISION: u64 = 100000;
 
@@ -1163,28 +1106,20 @@ Result Precision of pow and ln function -
-Implementation +##### Implementation -
public fun get_pair_metadata(
-    pair: Object<Config>,
-): PairMetadataResponse acquires Pool {
-    let pool = borrow_global_mut<Pool>(object::object_address(pair));
+
public fun get_pair_metadata(pair: Object<Config>): PairMetadataResponse acquires Pool {
+    let pool = borrow_global_mut<Pool>(object::object_address(&pair));
     let coin_a_metadata = fungible_asset::store_metadata(pool.coin_a_store);
     let coin_b_metadata = fungible_asset::store_metadata(pool.coin_b_store);
 
-    PairMetadataResponse {
-        coin_a_metadata,
-        coin_b_metadata,
-    }
+    PairMetadataResponse { coin_a_metadata, coin_b_metadata }
 }
 
-
- ## Function `get_pair_denom` @@ -1197,26 +1132,21 @@ Result Precision of pow and ln function -
-Implementation +##### Implementation -
public fun get_pair_denom(
-    pair: Object<Config>,
-): PairDenomResponse acquires Pool {
+
public fun get_pair_denom(pair: Object<Config>): PairDenomResponse acquires Pool {
     let pair_metadata = get_pair_metadata(pair);
 
     PairDenomResponse {
         coin_a_denom: coin::metadata_to_denom(pair_metadata.coin_a_metadata),
-        coin_b_denom: coin::metadata_to_denom(pair_metadata.coin_b_metadata),
+        coin_b_denom: coin::metadata_to_denom(pair_metadata.coin_b_metadata)
     }
 }
 
-
- ## Function `get_spot_price` @@ -1226,45 +1156,43 @@ https://balancer.fi/whitepaper.pdf (2)
#[view]
-public fun get_spot_price(pair: object::Object<dex::Config>, base_coin: object::Object<fungible_asset::Metadata>): decimal128::Decimal128
+public fun get_spot_price(pair: object::Object<dex::Config>, base_coin: object::Object<fungible_asset::Metadata>): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation
public fun get_spot_price(
-    pair: Object<Config>,
-    base_coin: Object<Metadata>,
-): Decimal128 acquires Config, Pool {
-    let (coin_a_pool, coin_b_pool, coin_a_weight, coin_b_weight, _) = pool_info(pair, false);
+    pair: Object<Config>, base_coin: Object<Metadata>
+): BigDecimal acquires Config, Pool {
+    let (coin_a_pool, coin_b_pool, coin_a_weight, coin_b_weight, _) =
+        pool_info(pair, false);
 
     let pair_key = generate_pair_key(pair);
-    let base_addr = object::object_address(base_coin);
+    let base_addr = object::object_address(&base_coin);
     assert!(
         base_addr == pair_key.coin_a || base_addr == pair_key.coin_b,
-        error::invalid_argument(ECOIN_TYPE),
+        error::invalid_argument(ECOIN_TYPE)
     );
     let is_base_a = base_addr == pair_key.coin_a;
-    let (base_pool, quote_pool, base_weight, quote_weight) = if (is_base_a) {
-        (coin_a_pool, coin_b_pool, coin_a_weight, coin_b_weight)
-    } else {
-        (coin_b_pool, coin_a_pool, coin_b_weight, coin_a_weight)
-    };
+    let (base_pool, quote_pool, base_weight, quote_weight) =
+        if (is_base_a) {
+            (coin_a_pool, coin_b_pool, coin_a_weight, coin_b_weight)
+        } else {
+            (coin_b_pool, coin_a_pool, coin_b_weight, coin_a_weight)
+        };
 
-    decimal128::from_ratio_u64(
-        decimal128::mul_u64(&base_weight, quote_pool),
-        decimal128::mul_u64("e_weight, base_pool),
+    bigdecimal::div(
+        bigdecimal::mul_by_u64(base_weight, quote_pool),
+        bigdecimal::mul_by_u64(quote_weight, base_pool)
     )
 }
 
-
- ## Function `get_spot_price_by_denom` @@ -1272,19 +1200,17 @@ https://balancer.fi/whitepaper.pdf (2)
#[view]
-public fun get_spot_price_by_denom(pair_denom: string::String, base_coin: string::String): decimal128::Decimal128
+public fun get_spot_price_by_denom(pair_denom: string::String, base_coin: string::String): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation
public fun get_spot_price_by_denom(
-    pair_denom: String,
-    base_coin: String,
-): Decimal128 acquires Config, Pool {
+    pair_denom: String, base_coin: String
+): BigDecimal acquires Config, Pool {
     let pair_metadata = coin::denom_to_metadata(pair_denom);
     let base_metadata = coin::denom_to_metadata(base_coin);
     get_spot_price(object::convert(pair_metadata), base_metadata)
@@ -1293,8 +1219,6 @@ https://balancer.fi/whitepaper.pdf (2)
 
 
 
-
- ## Function `get_swap_simulation` @@ -1308,36 +1232,35 @@ Return swap simulation result -
-Implementation +##### Implementation
public fun get_swap_simulation(
-    pair: Object<Config>,
-    offer_metadata: Object<Metadata>,
-    offer_amount: u64,
+    pair: Object<Config>, offer_metadata: Object<Metadata>, offer_amount: u64
 ): u64 acquires Config, Pool {
     let pair_key = generate_pair_key(pair);
-    let offer_address = object::object_address(offer_metadata);
+    let offer_address = object::object_address(&offer_metadata);
     assert!(
         offer_address == pair_key.coin_a || offer_address == pair_key.coin_b,
-        error::invalid_argument(ECOIN_TYPE),
+        error::invalid_argument(ECOIN_TYPE)
     );
     let is_offer_a = offer_address == pair_key.coin_a;
     let (pool_a, pool_b, weight_a, weight_b, swap_fee_rate) = pool_info(pair, true);
-    let (offer_pool, return_pool, offer_weight, return_weight) = if (is_offer_a) {
-        (pool_a, pool_b, weight_a, weight_b)
-    } else {
-        (pool_b, pool_a, weight_b, weight_a)
-    };
-    let (return_amount, _fee_amount) = swap_simulation(
-        offer_pool,
-        return_pool,
-        offer_weight,
-        return_weight,
-        offer_amount,
-        swap_fee_rate,
-    );
+    let (offer_pool, return_pool, offer_weight, return_weight) =
+        if (is_offer_a) {
+            (pool_a, pool_b, weight_a, weight_b)
+        } else {
+            (pool_b, pool_a, weight_b, weight_a)
+        };
+    let (return_amount, _fee_amount) =
+        swap_simulation(
+            offer_pool,
+            return_pool,
+            offer_weight,
+            return_weight,
+            offer_amount,
+            swap_fee_rate
+        );
 
     return_amount
 }
@@ -1345,8 +1268,6 @@ Return swap simulation result
 
 
 
-
- ## Function `get_swap_simulation_by_denom` @@ -1359,25 +1280,24 @@ Return swap simulation result -
-Implementation +##### Implementation
public fun get_swap_simulation_by_denom(
-    pair_denom: String,
-    offer_denom: String,
-    offer_amount: u64,
+    pair_denom: String, offer_denom: String, offer_amount: u64
 ): u64 acquires Config, Pool {
     let pair_metadata = coin::denom_to_metadata(pair_denom);
     let offer_metadata = coin::denom_to_metadata(offer_denom);
-    get_swap_simulation(object::convert(pair_metadata), offer_metadata, offer_amount)
+    get_swap_simulation(
+        object::convert(pair_metadata),
+        offer_metadata,
+        offer_amount
+    )
 }
 
-
- ## Function `get_swap_simulation_given_out` @@ -1391,36 +1311,35 @@ Return swap simulation result -
-Implementation +##### Implementation
public fun get_swap_simulation_given_out(
-    pair: Object<Config>,
-    offer_metadata: Object<Metadata>,
-    return_amount: u64,
+    pair: Object<Config>, offer_metadata: Object<Metadata>, return_amount: u64
 ): u64 acquires Config, Pool {
     let pair_key = generate_pair_key(pair);
-    let offer_address = object::object_address(offer_metadata);
+    let offer_address = object::object_address(&offer_metadata);
     assert!(
         offer_address == pair_key.coin_a || offer_address == pair_key.coin_b,
-        error::invalid_argument(ECOIN_TYPE),
+        error::invalid_argument(ECOIN_TYPE)
     );
     let is_offer_a = offer_address == pair_key.coin_a;
     let (pool_a, pool_b, weight_a, weight_b, swap_fee_rate) = pool_info(pair, true);
-    let (offer_pool, return_pool, offer_weight, return_weight) = if (is_offer_a) {
-        (pool_a, pool_b, weight_a, weight_b)
-    } else {
-        (pool_b, pool_a, weight_b, weight_a)
-    };
-    let (offer_amount, _fee_amount) = swap_simulation_given_out(
-        offer_pool,
-        return_pool,
-        offer_weight,
-        return_weight,
-        return_amount,
-        swap_fee_rate,
-    );
+    let (offer_pool, return_pool, offer_weight, return_weight) =
+        if (is_offer_a) {
+            (pool_a, pool_b, weight_a, weight_b)
+        } else {
+            (pool_b, pool_a, weight_b, weight_a)
+        };
+    let (offer_amount, _fee_amount) =
+        swap_simulation_given_out(
+            offer_pool,
+            return_pool,
+            offer_weight,
+            return_weight,
+            return_amount,
+            swap_fee_rate
+        );
 
     offer_amount
 }
@@ -1428,8 +1347,6 @@ Return swap simulation result
 
 
 
-
- ## Function `get_swap_simulation_given_out_by_denom` @@ -1442,25 +1359,24 @@ Return swap simulation result -
-Implementation +##### Implementation
public fun get_swap_simulation_given_out_by_denom(
-    pair_denom: String,
-    offer_denom: String,
-    return_amount: u64,
+    pair_denom: String, offer_denom: String, return_amount: u64
 ): u64 acquires Config, Pool {
     let pair_metadata = coin::denom_to_metadata(pair_denom);
     let offer_metadata = coin::denom_to_metadata(offer_denom);
-    get_swap_simulation_given_out(object::convert(pair_metadata), offer_metadata, return_amount)
+    get_swap_simulation_given_out(
+        object::convert(pair_metadata),
+        offer_metadata,
+        return_amount
+    )
 }
 
-
- ## Function `get_pool_info` @@ -1474,25 +1390,22 @@ get pool info -
-Implementation +##### Implementation
public fun get_pool_info(pair: Object<Config>): PoolInfoResponse acquires Pool {
-    let pair_addr = object::object_address(pair);
+    let pair_addr = object::object_address(&pair);
     let pool = borrow_global<Pool>(pair_addr);
     PoolInfoResponse {
         coin_a_amount: fungible_asset::balance(pool.coin_a_store),
         coin_b_amount: fungible_asset::balance(pool.coin_b_store),
-        total_share: option::extract(&mut fungible_asset::supply(pair)),
+        total_share: option::extract(&mut fungible_asset::supply(pair))
     }
 }
 
-
- ## Function `get_pool_info_by_denom` @@ -1506,8 +1419,7 @@ get pool info -
-Implementation +##### Implementation
public fun get_pool_info_by_denom(pair_denom: String): PoolInfoResponse acquires Pool {
@@ -1518,8 +1430,6 @@ get pool info
 
 
 
-
- ## Function `get_config` @@ -1533,25 +1443,19 @@ get config -
-Implementation +##### Implementation
public fun get_config(pair: Object<Config>): ConfigResponse acquires Config {
-    let pair_addr = object::object_address(pair);
+    let pair_addr = object::object_address(&pair);
     let config = borrow_global<Config>(pair_addr);
 
-    ConfigResponse {
-        weights: config.weights,
-        swap_fee_rate: config.swap_fee_rate,
-    }
+    ConfigResponse { weights: config.weights, swap_fee_rate: config.swap_fee_rate }
 }
 
-
- ## Function `get_config_by_denom` @@ -1565,8 +1469,7 @@ get config -
-Implementation +##### Implementation
public fun get_config_by_denom(pair_denom: String): ConfigResponse acquires Config {
@@ -1577,8 +1480,6 @@ get config
 
 
 
-
- ## Function `get_current_weight` @@ -1591,25 +1492,19 @@ get config -
-Implementation +##### Implementation
public fun get_current_weight(pair: Object<Config>): CurrentWeightResponse acquires Config {
-    let pair_addr = object::object_address(pair);
+    let pair_addr = object::object_address(&pair);
     let config = borrow_global<Config>(pair_addr);
     let (coin_a_weight, coin_b_weight) = get_weight(&config.weights);
-    CurrentWeightResponse {
-        coin_a_weight,
-        coin_b_weight,
-    }
+    CurrentWeightResponse { coin_a_weight, coin_b_weight }
 }
 
-
- ## Function `get_current_weight_by_denom` @@ -1622,11 +1517,12 @@ get config -
-Implementation +##### Implementation -
public fun get_current_weight_by_denom(pair_denom: String): CurrentWeightResponse acquires Config {
+
public fun get_current_weight_by_denom(
+    pair_denom: String
+): CurrentWeightResponse acquires Config {
     let pair_metadata = coin::denom_to_metadata(pair_denom);
     get_current_weight(object::convert(pair_metadata))
 }
@@ -1634,8 +1530,6 @@ get config
 
 
 
-
- ## Function `get_all_pairs` @@ -1648,52 +1542,55 @@ get config -
-Implementation +##### Implementation
public fun get_all_pairs(
     coin_a_start_after: Option<address>,
     coin_b_start_after: Option<address>,
     liquidity_token_start_after: Option<address>,
-    limit: u8,
+    limit: u8
 ): vector<PairResponse> acquires ModuleStore {
     if (limit > MAX_LIMIT) {
         limit = MAX_LIMIT;
     };
 
     assert!(
-        option::is_some(&coin_a_start_after) == option::is_some(&coin_b_start_after)
-            && option::is_some(&coin_b_start_after) == option::is_some(&liquidity_token_start_after),
+        option::is_some(&coin_a_start_after)
+            == option::is_some(&coin_b_start_after)
+            && option::is_some(&coin_b_start_after)
+                == option::is_some(&liquidity_token_start_after),
         ESTART_AFTER
     );
 
     let module_store = borrow_global<ModuleStore>(@minitia_std);
 
-    let start_after = if (option::is_some(&coin_a_start_after)) {
-        option::some(PairKey {
-            coin_a: option::extract(&mut coin_a_start_after),
-            coin_b: option::extract(&mut coin_b_start_after),
-            liquidity_token: option::extract(&mut liquidity_token_start_after),
-        })
-    } else {
-        option::some(PairKey {
-            coin_a: @0x0,
-            coin_b: @0x0,
-            liquidity_token: @0x0,
-        })
-    };
+    let start_after =
+        if (option::is_some(&coin_a_start_after)) {
+            option::some(
+                PairKey {
+                    coin_a: option::extract(&mut coin_a_start_after),
+                    coin_b: option::extract(&mut coin_b_start_after),
+                    liquidity_token: option::extract(&mut liquidity_token_start_after)
+                }
+            )
+        } else {
+            option::some(
+                PairKey { coin_a: @0x0, coin_b: @0x0, liquidity_token: @0x0 }
+            )
+        };
 
     let res = vector[];
     let pairs_iter = table::iter(
         &module_store.pairs,
         start_after,
         option::none(),
-        1,
+        1
     );
 
-    while (vector::length(&res) < (limit as u64) && table::prepare<PairKey, PairResponse>(&mut pairs_iter)) {
-        let (key, value) = table::next<PairKey, PairResponse>(&mut pairs_iter);
+    while (vector::length(&res) < (limit as u64)
+        && table::prepare<PairKey, PairResponse>(pairs_iter)) {
+        let (key, value) = table::next<PairKey, PairResponse>(pairs_iter);
         if (&key != option::borrow(&start_after)) {
             vector::push_back(&mut res, *value)
         }
@@ -1705,8 +1602,6 @@ get config
 
 
 
-
- ## Function `get_all_pairs_by_denom` @@ -1719,63 +1614,82 @@ get config -
-Implementation +##### Implementation
public fun get_all_pairs_by_denom(
     coin_a_start_after: Option<String>,
     coin_b_start_after: Option<String>,
     liquidity_token_start_after: Option<String>,
-    limit: u8,
+    limit: u8
 ): vector<PairByDenomResponse> acquires ModuleStore {
     if (limit > MAX_LIMIT) {
         limit = MAX_LIMIT;
     };
 
     assert!(
-        option::is_some(&coin_a_start_after) == option::is_some(&coin_b_start_after)
-            && option::is_some(&coin_b_start_after) == option::is_some(&liquidity_token_start_after),
+        option::is_some(&coin_a_start_after)
+            == option::is_some(&coin_b_start_after)
+            && option::is_some(&coin_b_start_after)
+                == option::is_some(&liquidity_token_start_after),
         ESTART_AFTER
     );
 
     let module_store = borrow_global<ModuleStore>(@minitia_std);
 
-    let start_after = if (option::is_some(&coin_a_start_after)) {
-        let coin_a_start_after = coin::denom_to_metadata(option::extract(&mut coin_a_start_after));
-        let coin_b_start_after = coin::denom_to_metadata(option::extract(&mut coin_b_start_after));
-        let liquidity_token_start_after = coin::denom_to_metadata(option::extract(&mut liquidity_token_start_after));
-        option::some(PairKey {
-            coin_a: object::object_address(coin_a_start_after),
-            coin_b: object::object_address(coin_b_start_after),
-            liquidity_token: object::object_address(liquidity_token_start_after),
-        })
-    } else {
-        option::some(PairKey {
-            coin_a: @0x0,
-            coin_b: @0x0,
-            liquidity_token: @0x0,
-        })
-    };
+    let start_after =
+        if (option::is_some(&coin_a_start_after)) {
+            let coin_a_start_after =
+                coin::denom_to_metadata(option::extract(&mut coin_a_start_after));
+            let coin_b_start_after =
+                coin::denom_to_metadata(option::extract(&mut coin_b_start_after));
+            let liquidity_token_start_after =
+                coin::denom_to_metadata(
+                    option::extract(&mut liquidity_token_start_after)
+                );
+            option::some(
+                PairKey {
+                    coin_a: object::object_address(&coin_a_start_after),
+                    coin_b: object::object_address(&coin_b_start_after),
+                    liquidity_token: object::object_address(
+                        &liquidity_token_start_after
+                    )
+                }
+            )
+        } else {
+            option::some(
+                PairKey { coin_a: @0x0, coin_b: @0x0, liquidity_token: @0x0 }
+            )
+        };
 
     let res = vector[];
     let pairs_iter = table::iter(
         &module_store.pairs,
         start_after,
         option::none(),
-        1,
+        1
     );
 
-    while (vector::length(&res) < (limit as u64) && table::prepare<PairKey, PairResponse>(&mut pairs_iter)) {
-        let (key, value) = table::next<PairKey, PairResponse>(&mut pairs_iter);
+    while (vector::length(&res) < (limit as u64)
+        && table::prepare<PairKey, PairResponse>(pairs_iter)) {
+        let (key, value) = table::next<PairKey, PairResponse>(pairs_iter);
         if (&key != option::borrow(&start_after)) {
-            vector::push_back(&mut res, PairByDenomResponse {
-                coin_a: coin::metadata_to_denom(object::address_to_object(value.coin_a)),
-                coin_b: coin::metadata_to_denom(object::address_to_object(value.coin_b)),
-                liquidity_token: coin::metadata_to_denom(object::address_to_object(value.liquidity_token)),
-                weights: value.weights,
-                swap_fee_rate: value.swap_fee_rate,
-            })
+            vector::push_back(
+                &mut res,
+                PairByDenomResponse {
+                    coin_a: coin::metadata_to_denom(
+                        object::address_to_object(value.coin_a)
+                    ),
+                    coin_b: coin::metadata_to_denom(
+                        object::address_to_object(value.coin_b)
+                    ),
+                    liquidity_token: coin::metadata_to_denom(
+                        object::address_to_object(value.liquidity_token)
+                    ),
+                    weights: value.weights,
+                    swap_fee_rate: value.swap_fee_rate
+                }
+            )
         }
     };
 
@@ -1785,8 +1699,6 @@ get config
 
 
 
-
- ## Function `get_pairs` @@ -1799,15 +1711,14 @@ get config -
-Implementation +##### Implementation
public fun get_pairs(
     coin_a: address,
     coin_b: address,
     start_after: Option<address>,
-    limit: u8,
+    limit: u8
 ): vector<PairResponse> acquires ModuleStore {
     if (limit > MAX_LIMIT) {
         limit = MAX_LIMIT;
@@ -1815,31 +1726,32 @@ get config
 
     let module_store = borrow_global<ModuleStore>(@minitia_std);
 
-    let start_after = if (option::is_some(&start_after)) {
-        option::some(PairKey {
-            coin_a,
-            coin_b,
-            liquidity_token: option::extract(&mut start_after),
-        })
-    } else {
-        option::some(PairKey {
-            coin_a,
-            coin_b,
-            liquidity_token: @0x0,
-        })
-    };
+    let start_after =
+        if (option::is_some(&start_after)) {
+            option::some(
+                PairKey {
+                    coin_a,
+                    coin_b,
+                    liquidity_token: option::extract(&mut start_after)
+                }
+            )
+        } else {
+            option::some(PairKey { coin_a, coin_b, liquidity_token: @0x0 })
+        };
 
     let res = vector[];
     let pairs_iter = table::iter(
         &module_store.pairs,
         start_after,
         option::none(),
-        1,
+        1
     );
 
-    while (vector::length(&res) < (limit as u64) && table::prepare<PairKey, PairResponse>(&mut pairs_iter)) {
-        let (key, value) = table::next<PairKey, PairResponse>(&mut pairs_iter);
-        if (coin_a != key.coin_a || coin_b != key.coin_b) break;
+    while (vector::length(&res) < (limit as u64)
+        && table::prepare<PairKey, PairResponse>(pairs_iter)) {
+        let (key, value) = table::next<PairKey, PairResponse>(pairs_iter);
+        if (coin_a != key.coin_a || coin_b != key.coin_b)
+            break;
         if (&key != option::borrow(&start_after)) {
             vector::push_back(&mut res, *value)
         }
@@ -1851,8 +1763,6 @@ get config
 
 
 
-
- ## Function `get_coin_a_amount_from_pool_info_response` @@ -1864,19 +1774,18 @@ get config -
-Implementation +##### Implementation -
public fun get_coin_a_amount_from_pool_info_response(res: &PoolInfoResponse): u64 {
+
public fun get_coin_a_amount_from_pool_info_response(
+    res: &PoolInfoResponse
+): u64 {
     res.coin_a_amount
 }
 
-
- ## Function `get_coin_b_amount_from_pool_info_response` @@ -1888,19 +1797,18 @@ get config -
-Implementation +##### Implementation -
public fun get_coin_b_amount_from_pool_info_response(res: &PoolInfoResponse): u64 {
+
public fun get_coin_b_amount_from_pool_info_response(
+    res: &PoolInfoResponse
+): u64 {
     res.coin_b_amount
 }
 
-
- ## Function `get_total_share_from_pool_info_response` @@ -1912,43 +1820,41 @@ get config -
-Implementation +##### Implementation -
public fun get_total_share_from_pool_info_response(res: &PoolInfoResponse): u128 {
+
public fun get_total_share_from_pool_info_response(
+    res: &PoolInfoResponse
+): u128 {
     res.total_share
 }
 
-
- ## Function `get_swap_fee_rate_from_config_response` -
public fun get_swap_fee_rate_from_config_response(res: &dex::ConfigResponse): decimal128::Decimal128
+
public fun get_swap_fee_rate_from_config_response(res: &dex::ConfigResponse): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation -
public fun get_swap_fee_rate_from_config_response(res: &ConfigResponse): Decimal128 {
+
public fun get_swap_fee_rate_from_config_response(
+    res: &ConfigResponse
+): BigDecimal {
     res.swap_fee_rate
 }
 
-
- ## Function `get_weight_before_from_config_response` @@ -1960,19 +1866,18 @@ get config -
-Implementation +##### Implementation -
public fun get_weight_before_from_config_response(res: &ConfigResponse): Weight {
+
public fun get_weight_before_from_config_response(
+    res: &ConfigResponse
+): Weight {
     res.weights.weights_before
 }
 
-
- ## Function `get_weight_after_from_config_response` @@ -1984,8 +1889,7 @@ get config -
-Implementation +##### Implementation
public fun get_weight_after_from_config_response(res: &ConfigResponse): Weight {
@@ -1995,56 +1899,48 @@ get config
 
 
 
-
- ## Function `get_coin_a_weight_from_weight` -
public fun get_coin_a_weight_from_weight(weight: &dex::Weight): decimal128::Decimal128
+
public fun get_coin_a_weight_from_weight(weight: &dex::Weight): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation -
public fun get_coin_a_weight_from_weight(weight: &Weight): Decimal128 {
+
public fun get_coin_a_weight_from_weight(weight: &Weight): BigDecimal {
     weight.coin_a_weight
 }
 
-
- ## Function `get_coin_b_weight_from_weight` -
public fun get_coin_b_weight_from_weight(weight: &dex::Weight): decimal128::Decimal128
+
public fun get_coin_b_weight_from_weight(weight: &dex::Weight): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation -
public fun get_coin_b_weight_from_weight(weight: &Weight): Decimal128 {
+
public fun get_coin_b_weight_from_weight(weight: &Weight): BigDecimal {
     weight.coin_b_weight
 }
 
-
- ## Function `get_timestamp_from_weight` @@ -2056,35 +1952,33 @@ get config -
-Implementation +##### Implementation
public fun get_timestamp_from_weight(weight: &Weight): u64 {
-    weight.timestamp
+    weight.timestamp
 }
 
-
- ## Function `unpack_pair_response` -
public fun unpack_pair_response(pair_response: &dex::PairResponse): (address, address, address, dex::Weights, decimal128::Decimal128)
+
public fun unpack_pair_response(pair_response: &dex::PairResponse): (address, address, address, dex::Weights, bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation -
public fun unpack_pair_response(pair_response: &PairResponse): (address, address, address, Weights, Decimal128) {
+
public fun unpack_pair_response(
+    pair_response: &PairResponse
+): (address, address, address, Weights, BigDecimal) {
     (
         pair_response.coin_a,
         pair_response.coin_b,
@@ -2097,140 +1991,88 @@ get config
 
 
 
-
- ## Function `unpack_current_weight_response` -
public fun unpack_current_weight_response(current_weight_response: &dex::CurrentWeightResponse): (decimal128::Decimal128, decimal128::Decimal128)
+
public fun unpack_current_weight_response(current_weight_response: &dex::CurrentWeightResponse): (bigdecimal::BigDecimal, bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation -
public fun unpack_current_weight_response(current_weight_response: &CurrentWeightResponse): (Decimal128, Decimal128) {
-    (
-        current_weight_response.coin_a_weight,
-        current_weight_response.coin_b_weight,
-    )
+
public fun unpack_current_weight_response(
+    current_weight_response: &CurrentWeightResponse
+): (BigDecimal, BigDecimal) {
+    (current_weight_response.coin_a_weight, current_weight_response.coin_b_weight)
 }
 
-
- - - -## Function `check_chain_permission` - -Check signer is chain - - -
fun check_chain_permission(chain: &signer)
-
- - - -
-Implementation - - -
fun check_chain_permission(chain: &signer) {
-    assert!(signer::address_of(chain) == @minitia_std, error::permission_denied(EUNAUTHORIZED));
-}
-
- - - -
- - - -## Function `init_module` - - - -
fun init_module(chain: &signer)
-
- - - -
-Implementation - - -
fun init_module(chain: &signer) {
-    move_to(chain, ModuleStore {
-        pairs: table::new<PairKey, PairResponse>(),
-        pair_count: 0,
-    });
-}
-
- - - -
- ## Function `create_pair_script` -
public entry fun create_pair_script(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: decimal128::Decimal128, coin_a_weight: decimal128::Decimal128, coin_b_weight: decimal128::Decimal128, coin_a_metadata: object::Object<fungible_asset::Metadata>, coin_b_metadata: object::Object<fungible_asset::Metadata>, coin_a_amount: u64, coin_b_amount: u64)
+
public entry fun create_pair_script(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: bigdecimal::BigDecimal, coin_a_weight: bigdecimal::BigDecimal, coin_b_weight: bigdecimal::BigDecimal, coin_a_metadata: object::Object<fungible_asset::Metadata>, coin_b_metadata: object::Object<fungible_asset::Metadata>, coin_a_amount: u64, coin_b_amount: u64)
 
-
-Implementation +##### Implementation
public entry fun create_pair_script(
     creator: &signer,
     name: String,
     symbol: String,
-    swap_fee_rate: Decimal128,
-    coin_a_weight: Decimal128,
-    coin_b_weight: Decimal128,
+    swap_fee_rate: BigDecimal,
+    coin_a_weight: BigDecimal,
+    coin_b_weight: BigDecimal,
     coin_a_metadata: Object<Metadata>,
     coin_b_metadata: Object<Metadata>,
     coin_a_amount: u64,
-    coin_b_amount: u64,
+    coin_b_amount: u64
 ) acquires CoinCapabilities, Config, Pool, ModuleStore {
-    let (_, timestamp) = get_block_info();
+    let (_, timestamp) = get_block_info();
     let weights = Weights {
-        weights_before: Weight {
-            coin_a_weight,
-            coin_b_weight,
-            timestamp
-        },
-        weights_after: Weight {
-            coin_a_weight,
-            coin_b_weight,
-            timestamp
-        }
+        weights_before: Weight { coin_a_weight, coin_b_weight, timestamp },
+        weights_after: Weight { coin_a_weight, coin_b_weight, timestamp }
     };
 
-    let coin_a = coin::withdraw(creator, coin_a_metadata, coin_a_amount);
-    let coin_b = coin::withdraw(creator, coin_b_metadata, coin_b_amount);
+    let coin_a = coin::withdraw(
+        creator,
+        coin_a_metadata,
+        coin_a_amount
+    );
+    let coin_b = coin::withdraw(
+        creator,
+        coin_b_metadata,
+        coin_b_amount
+    );
 
-    let liquidity_token = create_pair(creator, name, symbol, swap_fee_rate, coin_a, coin_b, weights);
+    let liquidity_token =
+        create_pair(
+            creator,
+            name,
+            symbol,
+            swap_fee_rate,
+            coin_a,
+            coin_b,
+            weights
+        );
     coin::deposit(signer::address_of(creator), liquidity_token);
 }
 
-
- ## Function `create_lbp_pair_script` @@ -2240,59 +2082,79 @@ permission check will be done in LP coin initialize only LP struct owner can initialize -
public entry fun create_lbp_pair_script(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: decimal128::Decimal128, start_time: u64, coin_a_start_weight: decimal128::Decimal128, coin_b_start_weight: decimal128::Decimal128, end_time: u64, coin_a_end_weight: decimal128::Decimal128, coin_b_end_weight: decimal128::Decimal128, coin_a_metadata: object::Object<fungible_asset::Metadata>, coin_b_metadata: object::Object<fungible_asset::Metadata>, coin_a_amount: u64, coin_b_amount: u64)
+
public entry fun create_lbp_pair_script(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: bigdecimal::BigDecimal, start_time: u64, coin_a_start_weight: bigdecimal::BigDecimal, coin_b_start_weight: bigdecimal::BigDecimal, end_time: u64, coin_a_end_weight: bigdecimal::BigDecimal, coin_b_end_weight: bigdecimal::BigDecimal, coin_a_metadata: object::Object<fungible_asset::Metadata>, coin_b_metadata: object::Object<fungible_asset::Metadata>, coin_a_amount: u64, coin_b_amount: u64)
 
-
-Implementation +##### Implementation
public entry fun create_lbp_pair_script(
     creator: &signer,
     name: String,
     symbol: String,
-    swap_fee_rate: Decimal128,
+    swap_fee_rate: BigDecimal,
     start_time: u64,
-    coin_a_start_weight: Decimal128,
-    coin_b_start_weight: Decimal128,
+    coin_a_start_weight: BigDecimal,
+    coin_b_start_weight: BigDecimal,
     end_time: u64,
-    coin_a_end_weight: Decimal128,
-    coin_b_end_weight: Decimal128,
+    coin_a_end_weight: BigDecimal,
+    coin_b_end_weight: BigDecimal,
     coin_a_metadata: Object<Metadata>,
     coin_b_metadata: Object<Metadata>,
     coin_a_amount: u64,
-    coin_b_amount: u64,
+    coin_b_amount: u64
 ) acquires CoinCapabilities, Config, ModuleStore, Pool {
-    let (_, timestamp) = get_block_info();
-    assert!(start_time > timestamp, error::invalid_argument(ELBP_START_TIME));
-    assert!(end_time > start_time, error::invalid_argument(EWEIGHTS_TIMESTAMP));
+    let (_, timestamp) = get_block_info();
+    assert!(
+        start_time > timestamp,
+        error::invalid_argument(ELBP_START_TIME)
+    );
+    assert!(
+        end_time > start_time,
+        error::invalid_argument(EWEIGHTS_TIMESTAMP)
+    );
     let weights = Weights {
         weights_before: Weight {
             coin_a_weight: coin_a_start_weight,
             coin_b_weight: coin_b_start_weight,
-            timestamp: start_time,
+            timestamp: start_time
         },
         weights_after: Weight {
             coin_a_weight: coin_a_end_weight,
             coin_b_weight: coin_b_end_weight,
-            timestamp: end_time,
+            timestamp: end_time
         }
     };
 
-    let coin_a = coin::withdraw(creator, coin_a_metadata, coin_a_amount);
-    let coin_b = coin::withdraw(creator, coin_b_metadata, coin_b_amount);
+    let coin_a = coin::withdraw(
+        creator,
+        coin_a_metadata,
+        coin_a_amount
+    );
+    let coin_b = coin::withdraw(
+        creator,
+        coin_b_metadata,
+        coin_b_amount
+    );
 
-    let liquidity_token = create_pair(creator, name, symbol, swap_fee_rate, coin_a, coin_b, weights);
+    let liquidity_token =
+        create_pair(
+            creator,
+            name,
+            symbol,
+            swap_fee_rate,
+            coin_a,
+            coin_b,
+            weights
+        );
     coin::deposit(signer::address_of(creator), liquidity_token);
 }
 
-
- ## Function `update_swap_fee_rate` @@ -2300,25 +2162,22 @@ only LP struct owner can initialize update swap fee rate -
public entry fun update_swap_fee_rate(chain: &signer, pair: object::Object<dex::Config>, swap_fee_rate: decimal128::Decimal128)
+
public entry fun update_swap_fee_rate(chain: &signer, pair: object::Object<dex::Config>, swap_fee_rate: bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation
public entry fun update_swap_fee_rate(
-    chain: &signer,
-    pair: Object<Config>,
-    swap_fee_rate: Decimal128,
+    chain: &signer, pair: Object<Config>, swap_fee_rate: BigDecimal
 ) acquires Config, Pool, ModuleStore {
     check_chain_permission(chain);
 
-    let config = borrow_global_mut<Config>(object::object_address(pair));
+    let config = borrow_global_mut<Config>(object::object_address(&pair));
     assert!(
-        decimal128::val(&swap_fee_rate) <= MAX_FEE_RATE,
+        bigdecimal::le(swap_fee_rate, max_fee_rate()),
         error::invalid_argument(EOUT_OF_SWAP_FEE_RATE_RANGE)
     );
 
@@ -2327,10 +2186,7 @@ update swap fee rate
 
     // update PairResponse
     let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
-    let pair_response = table::borrow_mut(
-        &mut module_store.pairs,
-        pair_key,
-    );
+    let pair_response = table::borrow_mut(&mut module_store.pairs, pair_key);
 
     pair_response.swap_fee_rate = swap_fee_rate;
 
@@ -2340,16 +2196,14 @@ update swap fee rate
             coin_a: pair_key.coin_a,
             coin_b: pair_key.coin_b,
             liquidity_token: pair_key.liquidity_token,
-            swap_fee_rate,
-        },
+            swap_fee_rate
+        }
     );
 }
 
-
- ## Function `provide_liquidity_script` @@ -2362,8 +2216,7 @@ script of provide_liquidity_from_coin_store -
-Implementation +##### Implementation
public entry fun provide_liquidity_script(
@@ -2378,15 +2231,13 @@ script of provide_liquidity_from_coin_store
         pair,
         coin_a_amount_in,
         coin_b_amount_in,
-        min_liquidity,
+        min_liquidity
     );
 }
 
-
- ## Function `provide_liquidity_from_coin_store` @@ -2399,8 +2250,7 @@ Provide liquidity with 0x1::coin::CoinStore coins -
-Implementation +##### Implementation
public fun provide_liquidity_from_coin_store(
@@ -2410,39 +2260,57 @@ Provide liquidity with 0x1::coin::CoinStore coins
     coin_b_amount_in: u64,
     min_liquidity: Option<u64>
 ): (u64, u64, u64) acquires CoinCapabilities, Config, Pool {
-    let pair_addr = object::object_address(pair);
+    let pair_addr = object::object_address(&pair);
     let pool = borrow_global_mut<Pool>(pair_addr);
     let coin_a_amount = fungible_asset::balance(pool.coin_a_store);
     let coin_b_amount = fungible_asset::balance(pool.coin_b_store);
     let total_share = option::extract(&mut fungible_asset::supply(pair));
 
     // calculate the best coin amount
-    let (coin_a, coin_b) = if (total_share == 0) {
-        (
-            coin::withdraw(account, fungible_asset::store_metadata(pool.coin_a_store), coin_a_amount_in),
-            coin::withdraw(account, fungible_asset::store_metadata(pool.coin_b_store), coin_b_amount_in),
-        )
-    } else {
-        let coin_a_share_ratio = decimal128::from_ratio_u64(coin_a_amount_in, coin_a_amount);
-        let coin_b_share_ratio = decimal128::from_ratio_u64(coin_b_amount_in, coin_b_amount);
-        if (decimal128::val(&coin_a_share_ratio) > decimal128::val(&coin_b_share_ratio)) {
-            coin_a_amount_in = decimal128::mul_u64(&coin_b_share_ratio, coin_a_amount);
+    let (coin_a, coin_b) =
+        if (total_share == 0) {
+            (
+                coin::withdraw(
+                    account,
+                    fungible_asset::store_metadata(pool.coin_a_store),
+                    coin_a_amount_in
+                ),
+                coin::withdraw(
+                    account,
+                    fungible_asset::store_metadata(pool.coin_b_store),
+                    coin_b_amount_in
+                )
+            )
         } else {
-            coin_b_amount_in = decimal128::mul_u64(&coin_a_share_ratio, coin_b_amount);
+            let coin_a_share_ratio =
+                bigdecimal::from_ratio_u64(coin_a_amount_in, coin_a_amount);
+            let coin_b_share_ratio =
+                bigdecimal::from_ratio_u64(coin_b_amount_in, coin_b_amount);
+            if (bigdecimal::gt(coin_a_share_ratio, coin_b_share_ratio)) {
+                coin_a_amount_in = bigdecimal::mul_by_u64_truncate(
+                    coin_b_share_ratio, coin_a_amount
+                );
+            } else {
+                coin_b_amount_in = bigdecimal::mul_by_u64_truncate(
+                    coin_a_share_ratio, coin_b_amount
+                );
+            };
+
+            (
+                coin::withdraw(
+                    account,
+                    fungible_asset::store_metadata(pool.coin_a_store),
+                    coin_a_amount_in
+                ),
+                coin::withdraw(
+                    account,
+                    fungible_asset::store_metadata(pool.coin_b_store),
+                    coin_b_amount_in
+                )
+            )
         };
 
-        (
-            coin::withdraw(account, fungible_asset::store_metadata(pool.coin_a_store), coin_a_amount_in),
-            coin::withdraw(account, fungible_asset::store_metadata(pool.coin_b_store), coin_b_amount_in),
-        )
-    };
-
-    let liquidity_token = provide_liquidity(
-        pair,
-        coin_a,
-        coin_b,
-        min_liquidity,
-    );
+    let liquidity_token = provide_liquidity(pair, coin_a, coin_b, min_liquidity);
 
     let liquidity_token_amount = fungible_asset::amount(&liquidity_token);
     coin::deposit(signer::address_of(account), liquidity_token);
@@ -2453,8 +2321,6 @@ Provide liquidity with 0x1::coin::CoinStore coins
 
 
 
-
- ## Function `withdraw_liquidity_script` @@ -2467,8 +2333,7 @@ Withdraw liquidity with liquidity token in the token store -
-Implementation +##### Implementation
public entry fun withdraw_liquidity_script(
@@ -2476,17 +2341,26 @@ Withdraw liquidity with liquidity token in the token store
     pair: Object<Config>,
     liquidity: u64,
     min_coin_a_amount: Option<u64>,
-    min_coin_b_amount: Option<u64>,
+    min_coin_b_amount: Option<u64>
 ) acquires CoinCapabilities, Config, Pool {
-    assert!(liquidity != 0, error::invalid_argument(EZERO_LIQUIDITY));
+    assert!(
+        liquidity != 0,
+        error::invalid_argument(EZERO_LIQUIDITY)
+    );
 
     let addr = signer::address_of(account);
-    let liquidity_token = coin::withdraw(account, object::convert<Config, Metadata>(pair), liquidity);
-    let (coin_a, coin_b) = withdraw_liquidity(
-        liquidity_token,
-        min_coin_a_amount,
-        min_coin_b_amount,
-    );
+    let liquidity_token =
+        coin::withdraw(
+            account,
+            object::convert<Config, Metadata>(pair),
+            liquidity
+        );
+    let (coin_a, coin_b) =
+        withdraw_liquidity(
+            liquidity_token,
+            min_coin_a_amount,
+            min_coin_b_amount
+        );
 
     coin::deposit(addr, coin_a);
     coin::deposit(addr, coin_b);
@@ -2495,8 +2369,6 @@ Withdraw liquidity with liquidity token in the token store
 
 
 
-
- ## Function `swap_script` @@ -2509,8 +2381,7 @@ Swap with the coin in the coin store -
-Implementation +##### Implementation
public entry fun swap_script(
@@ -2518,14 +2389,21 @@ Swap with the coin in the coin store
     pair: Object<Config>,
     offer_coin: Object<Metadata>,
     offer_coin_amount: u64,
-    min_return: Option<u64>,
+    min_return: Option<u64>
 ) acquires Config, Pool {
-    let offer_coin = coin::withdraw(account, offer_coin, offer_coin_amount);
+    let offer_coin = coin::withdraw(
+        account,
+        offer_coin,
+        offer_coin_amount
+    );
     let return_coin = swap(pair, offer_coin);
 
     assert!(
-        option::is_none(&min_return) || *option::borrow(&min_return) <= fungible_asset::amount(&return_coin),
-        error::invalid_state(EMIN_RETURN),
+        option::is_none(&min_return)
+            || *option::borrow(&min_return) <= fungible_asset::amount(
+                &return_coin
+            ),
+        error::invalid_state(EMIN_RETURN)
     );
 
     coin::deposit(signer::address_of(account), return_coin);
@@ -2534,8 +2412,6 @@ Swap with the coin in the coin store
 
 
 
-
- ## Function `single_asset_provide_liquidity_script` @@ -2548,8 +2424,7 @@ Single asset provide liquidity with token in the token store -
-Implementation +##### Implementation
public entry fun single_asset_provide_liquidity_script(
@@ -2561,11 +2436,8 @@ Single asset provide liquidity with token in the token store
 ) acquires Config, CoinCapabilities, Pool {
     let addr = signer::address_of(account);
     let provide_coin = coin::withdraw(account, provide_coin, amount_in);
-    let liquidity_token = single_asset_provide_liquidity(
-        pair,
-        provide_coin,
-        min_liquidity,
-    );
+    let liquidity_token =
+        single_asset_provide_liquidity(pair, provide_coin, min_liquidity);
 
     coin::deposit(addr, liquidity_token);
 }
@@ -2573,8 +2445,6 @@ Single asset provide liquidity with token in the token store
 
 
 
-
- ## Function `withdraw_liquidity` @@ -2588,41 +2458,51 @@ CONTRACT: not allow until LBP is ended -
-Implementation +##### Implementation
public fun withdraw_liquidity(
     lp_token: FungibleAsset,
     min_coin_a_amount: Option<u64>,
-    min_coin_b_amount: Option<u64>,
+    min_coin_b_amount: Option<u64>
 ): (FungibleAsset, FungibleAsset) acquires CoinCapabilities, Config, Pool {
     let pair_addr = coin_address(&lp_token);
     let pool = borrow_global_mut<Pool>(pair_addr);
     let config = borrow_global_mut<Config>(pair_addr);
-    let total_share = option::extract(
-        &mut fungible_asset::supply(fungible_asset::metadata_from_asset(&lp_token))
-    );
+    let total_share =
+        option::extract(
+            &mut fungible_asset::supply(
+                fungible_asset::metadata_from_asset(&lp_token)
+            )
+        );
     let coin_a_amount = fungible_asset::balance(pool.coin_a_store);
     let given_token_amount = fungible_asset::amount(&lp_token);
     let coin_b_amount = fungible_asset::balance(pool.coin_b_store);
-    let given_share_ratio = decimal128::from_ratio((given_token_amount as u128), total_share);
-    let coin_a_amount_out = decimal128::mul_u64(&given_share_ratio, coin_a_amount);
-    let coin_b_amount_out = decimal128::mul_u64(&given_share_ratio, coin_b_amount);
+    let given_share_ratio =
+        bigdecimal::from_ratio_u128((given_token_amount as u128), total_share);
+    let coin_a_amount_out =
+        bigdecimal::mul_by_u64_truncate(given_share_ratio, coin_a_amount);
+    let coin_b_amount_out =
+        bigdecimal::mul_by_u64_truncate(given_share_ratio, coin_b_amount);
     check_lbp_ended(&config.weights);
 
     assert!(
-        option::is_none(&min_coin_a_amount) || *option::borrow(&min_coin_a_amount) <= coin_a_amount_out,
-        error::invalid_state(EMIN_WITHDRAW),
+        option::is_none(&min_coin_a_amount)
+            || *option::borrow(&min_coin_a_amount) <= coin_a_amount_out,
+        error::invalid_state(EMIN_WITHDRAW)
     );
     assert!(
-        option::is_none(&min_coin_b_amount) || *option::borrow(&min_coin_b_amount) <= coin_b_amount_out,
-        error::invalid_state(EMIN_WITHDRAW),
+        option::is_none(&min_coin_b_amount)
+            || *option::borrow(&min_coin_b_amount) <= coin_b_amount_out,
+        error::invalid_state(EMIN_WITHDRAW)
     );
 
     // burn liquidity token
     let liquidity_token_capabilities = borrow_global<CoinCapabilities>(pair_addr);
-    coin::burn(&liquidity_token_capabilities.burn_cap, lp_token);
+    coin::burn(
+        &liquidity_token_capabilities.burn_cap,
+        lp_token
+    );
 
     // emit events
     let pair_key = generate_pair_key(object::address_to_object<Config>(pair_addr));
@@ -2633,24 +2513,30 @@ CONTRACT: not allow until LBP is ended
             liquidity_token: pair_addr,
             coin_a_amount: coin_a_amount_out,
             coin_b_amount: coin_b_amount_out,
-            liquidity: given_token_amount,
-        },
+            liquidity: given_token_amount
+        }
     );
     let pool = borrow_global_mut<Pool>(pair_addr);
 
     // withdraw and return the coins
     let pair_signer = &object::generate_signer_for_extending(&config.extend_ref);
     (
-        fungible_asset::withdraw(pair_signer, pool.coin_a_store, coin_a_amount_out),
-        fungible_asset::withdraw(pair_signer, pool.coin_b_store, coin_b_amount_out),
+        fungible_asset::withdraw(
+            pair_signer,
+            pool.coin_a_store,
+            coin_a_amount_out
+        ),
+        fungible_asset::withdraw(
+            pair_signer,
+            pool.coin_b_store,
+            coin_b_amount_out
+        )
     )
 }
 
-
- ## Function `single_asset_provide_liquidity` @@ -2665,82 +2551,101 @@ CONTRACT: not allow until LBP is ended -
-Implementation +##### Implementation
public fun single_asset_provide_liquidity(
     pair: Object<Config>,
     provide_coin: FungibleAsset,
-    min_liquidity_amount: Option<u64>,
+    min_liquidity_amount: Option<u64>
 ): FungibleAsset acquires Config, CoinCapabilities, Pool {
-    let pair_addr = object::object_address(pair);
+    let pair_addr = object::object_address(&pair);
     let config = borrow_global<Config>(pair_addr);
     check_lbp_ended(&config.weights);
 
     // provide coin type must be one of coin a or coin b coin type
     let provide_metadata = fungible_asset::metadata_from_asset(&provide_coin);
-    let provide_address = object::object_address(provide_metadata);
+    let provide_address = object::object_address(&provide_metadata);
     let pair_key = generate_pair_key(pair);
     assert!(
         provide_address == pair_key.coin_a || provide_address == pair_key.coin_b,
-        error::invalid_argument(ECOIN_TYPE),
+        error::invalid_argument(ECOIN_TYPE)
     );
     let is_provide_a = provide_address == pair_key.coin_a;
 
     let total_share = option::extract(&mut fungible_asset::supply(pair));
-    assert!(total_share != 0, error::invalid_state(EZERO_LIQUIDITY));
+    assert!(
+        total_share != 0,
+        error::invalid_state(EZERO_LIQUIDITY)
+    );
 
     // load values for fee and increased liquidity amount calculation
     let amount_in = fungible_asset::amount(&provide_coin);
     let (coin_a_weight, coin_b_weight) = get_weight(&config.weights);
     let pool = borrow_global_mut<Pool>(pair_addr);
-    let (normalized_weight, pool_amount_in, provide_coin_addr) = if (is_provide_a) {
-        let normalized_weight = decimal128::from_ratio(
-            decimal128::val(&coin_a_weight),
-            decimal128::val(&coin_a_weight) + decimal128::val(&coin_b_weight)
-        );
-
-        let pool_amount_in = fungible_asset::balance(pool.coin_a_store);
-        fungible_asset::deposit(pool.coin_a_store, provide_coin);
-
-        (normalized_weight, pool_amount_in, pair_key.coin_a)
-    } else {
-        let normalized_weight = decimal128::from_ratio(
-            decimal128::val(&coin_b_weight),
-            decimal128::val(&coin_a_weight) + decimal128::val(&coin_b_weight)
-        );
+    let (normalized_weight, pool_amount_in, provide_coin_addr) =
+        if (is_provide_a) {
+            let normalized_weight =
+                bigdecimal::div(
+                    coin_a_weight,
+                    bigdecimal::add(coin_a_weight, coin_b_weight)
+                );
+            let pool_amount_in = fungible_asset::balance(pool.coin_a_store);
+            fungible_asset::deposit(pool.coin_a_store, provide_coin);
+
+            (normalized_weight, pool_amount_in, pair_key.coin_a)
+        } else {
+            let normalized_weight =
+                bigdecimal::div(
+                    coin_b_weight,
+                    bigdecimal::add(coin_a_weight, coin_b_weight)
+                );
 
-        let pool_amount_in = fungible_asset::balance(pool.coin_b_store);
-        fungible_asset::deposit(pool.coin_b_store, provide_coin);
+            let pool_amount_in = fungible_asset::balance(pool.coin_b_store);
+            fungible_asset::deposit(pool.coin_b_store, provide_coin);
 
-        (normalized_weight, pool_amount_in, pair_key.coin_b)
-    };
+            (normalized_weight, pool_amount_in, pair_key.coin_b)
+        };
 
     // CONTRACT: cannot provide more than the pool amount to prevent huge price impact
-    assert!(pool_amount_in > amount_in, error::invalid_argument(EPRICE_IMPACT));
+    assert!(
+        pool_amount_in > amount_in,
+        error::invalid_argument(EPRICE_IMPACT)
+    );
 
     // compute fee amount with the assumption that we will swap (1 - normalized_weight) of amount_in
-    let adjusted_swap_amount = decimal128::mul_u64(
-        &decimal128::sub(&decimal128::one(), &normalized_weight),
-        amount_in
-    );
-    let fee_amount = decimal128::mul_u64(&config.swap_fee_rate, adjusted_swap_amount);
+    let adjusted_swap_amount =
+        bigdecimal::mul_by_u64_truncate(
+            bigdecimal::sub(
+                bigdecimal::one(),
+                normalized_weight
+            ),
+            amount_in
+        );
+    let fee_amount =
+        calculate_fee_with_minimum(
+            config.swap_fee_rate,
+            adjusted_swap_amount
+        );
 
     // actual amount in after deducting fee amount
     let adjusted_amount_in = amount_in - fee_amount;
 
     // calculate new total share and new liquidity
-    let base = decimal128::from_ratio_u64(adjusted_amount_in + pool_amount_in, pool_amount_in);
-    let pool_ratio = pow(&base, &normalized_weight);
-    let new_total_share = decimal128::mul_u128(&pool_ratio, total_share);
+    let base =
+        bigdecimal::from_ratio_u64(
+            adjusted_amount_in + pool_amount_in,
+            pool_amount_in
+        );
+    let pool_ratio = pow(base, normalized_weight);
+    let new_total_share = bigdecimal::mul_by_u128_truncate(pool_ratio, total_share);
     let liquidity = (new_total_share - total_share as u64);
 
     // check min liquidity assertion
     assert!(
-        option::is_none(&min_liquidity_amount) ||
-            *option::borrow(&min_liquidity_amount) <= liquidity,
-        error::invalid_state(EMIN_LIQUIDITY),
+        option::is_none(&min_liquidity_amount)
+            || *option::borrow(&min_liquidity_amount) <= liquidity,
+        error::invalid_state(EMIN_LIQUIDITY)
     );
 
     // emit events
@@ -2752,20 +2657,21 @@ CONTRACT: not allow until LBP is ended
             liquidity_token: pair_addr,
             provide_amount: amount_in,
             fee_amount,
-            liquidity,
-        },
+            liquidity
+        }
     );
 
     // mint liquidity tokens to provider
     let liquidity_token_capabilities = borrow_global<CoinCapabilities>(pair_addr);
-    coin::mint(&liquidity_token_capabilities.mint_cap, liquidity)
+    coin::mint(
+        &liquidity_token_capabilities.mint_cap,
+        liquidity
+    )
 }
 
-
- ## Function `swap` @@ -2778,51 +2684,67 @@ Swap directly -
-Implementation +##### Implementation
public fun swap(
-    pair: Object<Config>,
-    offer_coin: FungibleAsset,
+    pair: Object<Config>, offer_coin: FungibleAsset
 ): FungibleAsset acquires Config, Pool {
     let offer_amount = fungible_asset::amount(&offer_coin);
     let offer_metadata = fungible_asset::metadata_from_asset(&offer_coin);
-    let offer_address = object::object_address(offer_metadata);
+    let offer_address = object::object_address(&offer_metadata);
     let pair_key = generate_pair_key(pair);
     assert!(
         offer_address == pair_key.coin_a || offer_address == pair_key.coin_b,
-        error::invalid_argument(ECOIN_TYPE),
+        error::invalid_argument(ECOIN_TYPE)
     );
     let is_offer_a = offer_address == pair_key.coin_a;
 
-    let (pool_a, pool_b, weight_a, weight_b, swap_fee_rate) = pool_info(pair ,true);
-    let (offer_coin_addr, return_coin_addr, offer_pool, return_pool, offer_weight, return_weight) = if (is_offer_a) {
-        (pair_key.coin_a, pair_key.coin_b, pool_a, pool_b, weight_a, weight_b)
-    } else {
-        (pair_key.coin_b, pair_key.coin_a, pool_b, pool_a, weight_b, weight_a)
-    };
-    let (return_amount, fee_amount) = swap_simulation(
+    let (pool_a, pool_b, weight_a, weight_b, swap_fee_rate) = pool_info(pair, true);
+    let (
+        offer_coin_addr,
+        return_coin_addr,
         offer_pool,
         return_pool,
         offer_weight,
-        return_weight,
-        fungible_asset::amount(&offer_coin),
-        swap_fee_rate,
-    );
+        return_weight
+    ) =
+        if (is_offer_a) {
+            (pair_key.coin_a, pair_key.coin_b, pool_a, pool_b, weight_a, weight_b)
+        } else {
+            (pair_key.coin_b, pair_key.coin_a, pool_b, pool_a, weight_b, weight_a)
+        };
+    let (return_amount, fee_amount) =
+        swap_simulation(
+            offer_pool,
+            return_pool,
+            offer_weight,
+            return_weight,
+            fungible_asset::amount(&offer_coin),
+            swap_fee_rate
+        );
 
     // apply swap result to pool
-    let pair_addr = object::object_address(pair);
+    let pair_addr = object::object_address(&pair);
     let pool = borrow_global_mut<Pool>(pair_addr);
     let config = borrow_global<Config>(pair_addr);
     let pair_signer = &object::generate_signer_for_extending(&config.extend_ref);
-    let return_coin = if (is_offer_a) {
-        fungible_asset::deposit(pool.coin_a_store, offer_coin);
-        fungible_asset::withdraw(pair_signer, pool.coin_b_store, return_amount)
-    } else {
-        fungible_asset::deposit(pool.coin_b_store, offer_coin);
-        fungible_asset::withdraw(pair_signer, pool.coin_a_store, return_amount)
-    };
+    let return_coin =
+        if (is_offer_a) {
+            fungible_asset::deposit(pool.coin_a_store, offer_coin);
+            fungible_asset::withdraw(
+                pair_signer,
+                pool.coin_b_store,
+                return_amount
+            )
+        } else {
+            fungible_asset::deposit(pool.coin_b_store, offer_coin);
+            fungible_asset::withdraw(
+                pair_signer,
+                pool.coin_a_store,
+                return_amount
+            )
+        };
 
     // emit events
     event::emit<SwapEvent>(
@@ -2832,8 +2754,8 @@ Swap directly
             liquidity_token: pair_addr,
             fee_amount,
             offer_amount,
-            return_amount,
-        },
+            return_amount
+        }
     );
 
     return_coin
@@ -2842,56 +2764,67 @@ Swap directly
 
 
 
-
- ## Function `create_pair` -
public fun create_pair(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: decimal128::Decimal128, coin_a: fungible_asset::FungibleAsset, coin_b: fungible_asset::FungibleAsset, weights: dex::Weights): fungible_asset::FungibleAsset
+
public fun create_pair(creator: &signer, name: string::String, symbol: string::String, swap_fee_rate: bigdecimal::BigDecimal, coin_a: fungible_asset::FungibleAsset, coin_b: fungible_asset::FungibleAsset, weights: dex::Weights): fungible_asset::FungibleAsset
 
-
-Implementation +##### Implementation
public fun create_pair(
     creator: &signer,
     name: String,
     symbol: String,
-    swap_fee_rate: Decimal128,
+    swap_fee_rate: BigDecimal,
     coin_a: FungibleAsset,
     coin_b: FungibleAsset,
-    weights: Weights,
+    weights: Weights
 ): FungibleAsset acquires CoinCapabilities, Config, ModuleStore, Pool {
-    let (mint_cap, burn_cap, freeze_cap, extend_ref) = coin::initialize_and_generate_extend_ref (
-        creator,
-        option::none(),
-        name,
-        symbol,
-        6,
-        string::utf8(b""),
-        string::utf8(b""),
-    );
+    let (mint_cap, burn_cap, freeze_cap, extend_ref) =
+        coin::initialize_and_generate_extend_ref(
+            creator,
+            option::none(),
+            name,
+            symbol,
+            6,
+            string::utf8(b""),
+            string::utf8(b"")
+        );
+
+    assert_weights(weights);
 
     assert!(
-        decimal128::val(&swap_fee_rate) <= MAX_FEE_RATE,
+        bigdecimal::le(swap_fee_rate, max_fee_rate()),
         error::invalid_argument(EOUT_OF_SWAP_FEE_RATE_RANGE)
     );
 
-    assert!(coin_address(&coin_a) != coin_address(&coin_b), error::invalid_argument(ESAME_COIN_TYPE));
+    assert!(
+        coin_address(&coin_a) != coin_address(&coin_b),
+        error::invalid_argument(ESAME_COIN_TYPE)
+    );
 
     let pair_signer = &object::generate_signer_for_extending(&extend_ref);
     let pair_address = signer::address_of(pair_signer);
     // transfer pair object's ownership to minitia_std
     object::transfer_raw(creator, pair_address, @minitia_std);
 
-    let coin_a_store = primary_fungible_store::create_primary_store(pair_address, fungible_asset::asset_metadata(&coin_a));
-    let coin_b_store = primary_fungible_store::create_primary_store(pair_address, fungible_asset::asset_metadata(&coin_b));
+    let coin_a_store =
+        primary_fungible_store::create_primary_store(
+            pair_address,
+            fungible_asset::asset_metadata(&coin_a)
+        );
+    let coin_b_store =
+        primary_fungible_store::create_primary_store(
+            pair_address,
+            fungible_asset::asset_metadata(&coin_b)
+        );
     let coin_a_addr = coin_address(&coin_a);
     let coin_b_addr = coin_address(&coin_b);
 
@@ -2902,7 +2835,7 @@ Swap directly
 
     move_to(
         pair_signer,
-        CoinCapabilities { mint_cap, freeze_cap, burn_cap },
+        CoinCapabilities { mint_cap, freeze_cap, burn_cap }
     );
 
     move_to(
@@ -2912,26 +2845,27 @@ Swap directly
             // temp weights for initial provide
             weights: Weights {
                 weights_before: Weight {
-                    coin_a_weight: decimal128::one(),
-                    coin_b_weight: decimal128::one(),
-                    timestamp: 0,
+                    coin_a_weight: bigdecimal::one(),
+                    coin_b_weight: bigdecimal::one(),
+                    timestamp: 0
                 },
                 weights_after: Weight {
-                    coin_a_weight: decimal128::one(),
-                    coin_b_weight: decimal128::one(),
-                    timestamp: 0,
+                    coin_a_weight: bigdecimal::one(),
+                    coin_b_weight: bigdecimal::one(),
+                    timestamp: 0
                 }
             },
-            swap_fee_rate,
+            swap_fee_rate
         }
     );
 
-    let liquidity_token = provide_liquidity(
-        object::address_to_object<Config>(pair_address),
-        coin_a,
-        coin_b,
-        option::none(),
-    );
+    let liquidity_token =
+        provide_liquidity(
+            object::address_to_object<Config>(pair_address),
+            coin_a,
+            coin_b,
+            option::none()
+        );
 
     // update weights
     let config = borrow_global_mut<Config>(pair_address);
@@ -2944,7 +2878,11 @@ Swap directly
     // let coin_a_type = type_info::type_name<CoinA>();
     // let coin_b_type = type_info::type_name<CoinB>();
     // let liquidity_token_type = type_info::type_name<LiquidityToken>();
-    let pair_key = PairKey { coin_a: coin_a_addr, coin_b: coin_b_addr, liquidity_token: pair_address};
+    let pair_key = PairKey {
+        coin_a: coin_a_addr,
+        coin_b: coin_b_addr,
+        liquidity_token: pair_address
+    };
 
     // add pair to table for queries
     table::add(
@@ -2955,8 +2893,8 @@ Swap directly
             coin_b: coin_b_addr,
             liquidity_token: pair_address,
             weights,
-            swap_fee_rate,
-        },
+            swap_fee_rate
+        }
     );
 
     // emit create pair event
@@ -2966,8 +2904,8 @@ Swap directly
             coin_b: coin_b_addr,
             liquidity_token: pair_address,
             weights,
-            swap_fee_rate,
-        },
+            swap_fee_rate
+        }
     );
 
     liquidity_token
@@ -2976,8 +2914,6 @@ Swap directly
 
 
 
-
- ## Function `provide_liquidity` @@ -2991,17 +2927,16 @@ CONTRACT: not allow until LBP is ended -
-Implementation +##### Implementation
public fun provide_liquidity(
     pair: Object<Config>,
     coin_a: FungibleAsset,
     coin_b: FungibleAsset,
-    min_liquidity_amount: Option<u64>,
+    min_liquidity_amount: Option<u64>
 ): FungibleAsset acquires Config, Pool, CoinCapabilities {
-    let pool_addr = object::object_address(pair);
+    let pool_addr = object::object_address(&pair);
     let config = borrow_global_mut<Config>(pool_addr);
     let pool = borrow_global_mut<Pool>(pool_addr);
     check_lbp_ended(&config.weights);
@@ -3012,25 +2947,33 @@ CONTRACT: not allow until LBP is ended
     let coin_b_amount = fungible_asset::balance(pool.coin_b_store);
 
     let total_share = option::extract(&mut fungible_asset::supply(pair));
-    let liquidity = if (total_share == 0) {
-        if (coin_a_amount_in > coin_b_amount_in) {
-            coin_a_amount_in
-        } else {
-            coin_b_amount_in
-        }
-    } else {
-        let coin_a_share_ratio = decimal128::from_ratio_u64(coin_a_amount_in, coin_a_amount);
-        let coin_b_share_ratio = decimal128::from_ratio_u64(coin_b_amount_in, coin_b_amount);
-        if (decimal128::val(&coin_a_share_ratio) > decimal128::val(&coin_b_share_ratio)) {
-            (decimal128::mul_u128(&coin_b_share_ratio, total_share) as u64)
+    let liquidity =
+        if (total_share == 0) {
+            if (coin_a_amount_in > coin_b_amount_in) {
+                coin_a_amount_in
+            } else {
+                coin_b_amount_in
+            }
         } else {
-            (decimal128::mul_u128(&coin_a_share_ratio, total_share) as u64)
-        }
-    };
+            let coin_a_share_ratio =
+                bigdecimal::from_ratio_u64(coin_a_amount_in, coin_a_amount);
+            let coin_b_share_ratio =
+                bigdecimal::from_ratio_u64(coin_b_amount_in, coin_b_amount);
+            if (bigdecimal::gt(coin_a_share_ratio, coin_b_share_ratio)) {
+                (
+                    bigdecimal::mul_by_u128_truncate(coin_b_share_ratio, total_share) as u64
+                )
+            } else {
+                (
+                    bigdecimal::mul_by_u128_truncate(coin_a_share_ratio, total_share) as u64
+                )
+            }
+        };
 
     assert!(
-        option::is_none(&min_liquidity_amount) || *option::borrow(&min_liquidity_amount) <= liquidity,
-        error::invalid_state(EMIN_LIQUIDITY),
+        option::is_none(&min_liquidity_amount)
+            || *option::borrow(&min_liquidity_amount) <= liquidity,
+        error::invalid_state(EMIN_LIQUIDITY)
     );
 
     event::emit<ProvideEvent>(
@@ -3040,156 +2983,23 @@ CONTRACT: not allow until LBP is ended
             liquidity_token: pool_addr,
             coin_a_amount: coin_a_amount_in,
             coin_b_amount: coin_b_amount_in,
-            liquidity,
-        },
+            liquidity
+        }
     );
 
     fungible_asset::deposit(pool.coin_a_store, coin_a);
     fungible_asset::deposit(pool.coin_b_store, coin_b);
 
     let liquidity_token_capabilities = borrow_global<CoinCapabilities>(pool_addr);
-    coin::mint(&liquidity_token_capabilities.mint_cap, liquidity)
-}
-
- - - -
- - - -## Function `coin_address` - - - -
fun coin_address(fa: &fungible_asset::FungibleAsset): address
-
- - - -
-Implementation - - -
fun coin_address(fa: &FungibleAsset): address {
-    let metadata = fungible_asset::asset_metadata(fa);
-    object::object_address(metadata)
-}
-
- - - -
- - - -## Function `check_lbp_ended` - - - -
fun check_lbp_ended(weights: &dex::Weights)
-
- - - -
-Implementation - - -
fun check_lbp_ended(weights: &Weights) {
-    let (_, timestamp) = get_block_info();
-
-    assert!(timestamp >= weights.weights_after.timestamp, error::invalid_state(ELBP_NOT_ENDED))
-}
-
- - - -
- - - -## Function `generate_pair_key` - - - -
fun generate_pair_key<T: key>(pair: object::Object<T>): dex::PairKey
-
- - - -
-Implementation - - -
fun generate_pair_key<T: key>(pair: Object<T>): PairKey acquires Pool {
-    let addr = object::object_address(pair);
-    let pool = borrow_global<Pool>(addr);
-    let coin_a_metadata = fungible_asset::store_metadata(pool.coin_a_store);
-    let coin_b_metadata = fungible_asset::store_metadata(pool.coin_b_store);
-    PairKey {
-        coin_a: object::object_address(coin_a_metadata),
-        coin_b: object::object_address(coin_b_metadata),
-        liquidity_token: addr
-    }
-}
-
- - - -
- - - -## Function `get_weight` - -return (coin_a_weight, coin_b_weight) - - -
fun get_weight(weights: &dex::Weights): (decimal128::Decimal128, decimal128::Decimal128)
-
- - - -
-Implementation - - -
fun get_weight(weights: &Weights): (Decimal128, Decimal128) {
-    let (_, timestamp) = get_block_info();
-    if (timestamp <= weights.weights_before.timestamp) {
-        (weights.weights_before.coin_a_weight, weights.weights_before.coin_b_weight)
-    } else if (timestamp < weights.weights_after.timestamp) {
-        let interval = (weights.weights_after.timestamp - weights.weights_before.timestamp as u128);
-        let time_diff_after = (weights.weights_after.timestamp - timestamp as u128);
-        let time_diff_before = (timestamp - weights.weights_before.timestamp as u128);
-
-        // when timestamp_before < timestamp < timestamp_after
-        // weight = a * timestamp + b
-        // m = (a * timestamp_before + b) * (timestamp_after - timestamp)
-        //   = a * t_b * t_a - a * t_b * t + b * t_a - b * t
-        // n = (a * timestamp_after + b) * (timestamp - timestamp_before)
-        //   = a * t_a * t - a * t_a * t_b + b * t - b * t_b
-        // l = m + n = a * t * (t_a - t_b) + b * (t_a - t_b)
-        // weight = l / (t_a - t_b)
-        let coin_a_m = decimal128::new(decimal128::val(&weights.weights_after.coin_a_weight) * time_diff_before);
-        let coin_a_n = decimal128::new(decimal128::val(&weights.weights_before.coin_a_weight) * time_diff_after);
-        let coin_a_l = decimal128::add(&coin_a_m, &coin_a_n);
-
-        let coin_b_m = decimal128::new(decimal128::val(&weights.weights_after.coin_b_weight) * time_diff_before);
-        let coin_b_n = decimal128::new(decimal128::val(&weights.weights_before.coin_b_weight) * time_diff_after);
-        let coin_b_l = decimal128::add(&coin_b_m, &coin_b_n);
-        (decimal128::div(&coin_a_l, interval), decimal128::div(&coin_b_l, interval))
-    } else {
-        (weights.weights_after.coin_a_weight, weights.weights_after.coin_b_weight)
-    }
+    coin::mint(
+        &liquidity_token_capabilities.mint_cap,
+        liquidity
+    )
 }
 
-
- ## Function `pool_info` @@ -3197,22 +3007,26 @@ return (coin_a_weight, coin_b_weight) get all pool info at once (a_amount, b_amount, a_weight, b_weight, fee_rate) -
public fun pool_info(pair: object::Object<dex::Config>, lbp_assertion: bool): (u64, u64, decimal128::Decimal128, decimal128::Decimal128, decimal128::Decimal128)
+
public fun pool_info(pair: object::Object<dex::Config>, lbp_assertion: bool): (u64, u64, bigdecimal::BigDecimal, bigdecimal::BigDecimal, bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation -
public fun pool_info(pair: Object<Config>, lbp_assertion: bool): (u64, u64, Decimal128, Decimal128, Decimal128) acquires Config, Pool {
-    let pair_addr = object::object_address(pair);
+
public fun pool_info(
+    pair: Object<Config>, lbp_assertion: bool
+): (u64, u64, BigDecimal, BigDecimal, BigDecimal) acquires Config, Pool {
+    let pair_addr = object::object_address(&pair);
     let config = borrow_global<Config>(pair_addr);
     if (lbp_assertion) {
         // assert LBP start time
-        let (_, timestamp) = get_block_info();
-        assert!(timestamp >= config.weights.weights_before.timestamp, error::invalid_state(ELBP_NOT_STARTED));
+        let (_, timestamp) = get_block_info();
+        assert!(
+            timestamp >= config.weights.weights_before.timestamp,
+            error::invalid_state(ELBP_NOT_STARTED)
+        );
     };
 
     let pool = borrow_global<Pool>(pair_addr);
@@ -3223,15 +3037,13 @@ get all pool info at once (a_amount, b_amount, a_weight, b_weight, fee_rate)
         fungible_asset::balance(pool.coin_b_store),
         coin_a_weight,
         coin_b_weight,
-        config.swap_fee_rate,
+        config.swap_fee_rate
     )
 }
 
-
- ## Function `swap_simulation` @@ -3241,69 +3053,84 @@ https://balancer.fi/whitepaper.pdf (15) return (return_amount, fee_amount) -
public fun swap_simulation(pool_amount_in: u64, pool_amount_out: u64, weight_in: decimal128::Decimal128, weight_out: decimal128::Decimal128, amount_in: u64, swap_fee_rate: decimal128::Decimal128): (u64, u64)
+
public fun swap_simulation(pool_amount_in: u64, pool_amount_out: u64, weight_in: bigdecimal::BigDecimal, weight_out: bigdecimal::BigDecimal, amount_in: u64, swap_fee_rate: bigdecimal::BigDecimal): (u64, u64)
 
-
-Implementation +##### Implementation
public fun swap_simulation(
     pool_amount_in: u64,
     pool_amount_out: u64,
-    weight_in: Decimal128,
-    weight_out: Decimal128,
+    weight_in: BigDecimal,
+    weight_out: BigDecimal,
     amount_in: u64,
-    swap_fee_rate: Decimal128,
+    swap_fee_rate: BigDecimal
 ): (u64, u64) {
-    let one = decimal128::one();
-    let exp = decimal128::from_ratio(decimal128::val(&weight_in), decimal128::val(&weight_out));
-    let fee_amount = decimal128::mul_u64(&swap_fee_rate, amount_in);
+    assert!(
+        amount_in > 0,
+        error::invalid_argument(EZERO_AMOUNT_IN)
+    );
+
+    let one = bigdecimal::one();
+    let exp = bigdecimal::div(weight_in, weight_out);
+
+    let fee_amount = calculate_fee_with_minimum(swap_fee_rate, amount_in);
     let adjusted_amount_in = amount_in - fee_amount;
-    let base = decimal128::from_ratio_u64(pool_amount_in, pool_amount_in + adjusted_amount_in);
-    let sub_amount = pow(&base, &exp);
-    (decimal128::mul_u64(&decimal128::sub(&one, &sub_amount), pool_amount_out), fee_amount)
+    let base =
+        bigdecimal::from_ratio_u64(
+            pool_amount_in,
+            pool_amount_in + adjusted_amount_in
+        );
+    let sub_amount = pow(base, exp);
+    (
+        bigdecimal::mul_by_u64_truncate(
+            bigdecimal::sub(one, sub_amount),
+            pool_amount_out
+        ),
+        fee_amount
+    )
 }
 
-
- ## Function `swap_simulation_given_out` -
public fun swap_simulation_given_out(pool_amount_in: u64, pool_amount_out: u64, weight_in: decimal128::Decimal128, weight_out: decimal128::Decimal128, amount_out: u64, swap_fee_rate: decimal128::Decimal128): (u64, u64)
+
public fun swap_simulation_given_out(pool_amount_in: u64, pool_amount_out: u64, weight_in: bigdecimal::BigDecimal, weight_out: bigdecimal::BigDecimal, amount_out: u64, swap_fee_rate: bigdecimal::BigDecimal): (u64, u64)
 
-
-Implementation +##### Implementation
public fun swap_simulation_given_out(
     pool_amount_in: u64,
     pool_amount_out: u64,
-    weight_in: Decimal128,
-    weight_out: Decimal128,
+    weight_in: BigDecimal,
+    weight_out: BigDecimal,
     amount_out: u64,
-    swap_fee_rate: Decimal128,
+    swap_fee_rate: BigDecimal
 ): (u64, u64) {
-    let one = decimal128::one();
-    let exp = decimal128::from_ratio(decimal128::val(&weight_out), decimal128::val(&weight_in));
-    let base = decimal128::from_ratio_u64(pool_amount_out, pool_amount_out - amount_out);
-    let base_exp = pow(&base, &exp);
-    let adjusted_amount_in = decimal128::val(&decimal128::sub(&base_exp, &one)) * (pool_amount_in as u128) ;
-    let sub_one_fee = decimal128::sub(&one, &swap_fee_rate);
-
-    let amount_in = ( adjusted_amount_in / decimal128::val(&sub_one_fee) as u64);
-    let fee_amount = decimal128::mul_u64(&swap_fee_rate, amount_in);
+    let one = bigdecimal::one();
+    let exp = bigdecimal::div(weight_out, weight_in);
+    let base = bigdecimal::from_ratio_u64(
+        pool_amount_out, pool_amount_out - amount_out
+    );
+    let base_exp = pow(base, exp);
+    let adjusted_amount_in =
+        bigdecimal::mul_by_u64(bigdecimal::sub(base_exp, one), pool_amount_in);
+    let sub_one_fee = bigdecimal::sub(one, swap_fee_rate);
+    let amount_in =
+        bigdecimal::truncate_u64(bigdecimal::div(adjusted_amount_in, sub_one_fee));
+    let fee_amount = calculate_fee_with_minimum(swap_fee_rate, amount_in);
 
     (amount_in, fee_amount)
 }
@@ -3311,8 +3138,6 @@ return (return_amount, fee_amount)
 
 
 
-
- ## Function `pool_metadata` @@ -3324,153 +3149,17 @@ return (return_amount, fee_amount) -
-Implementation +##### Implementation -
public fun pool_metadata(pair: Object<Config>): (Object<Metadata>, Object<Metadata>) acquires Pool {
-    let pair_addr = object::object_address(pair);
+
public fun pool_metadata(
+    pair: Object<Config>
+): (Object<Metadata>, Object<Metadata>) acquires Pool {
+    let pair_addr = object::object_address(&pair);
     let pool = borrow_global<Pool>(pair_addr);
-    (fungible_asset::store_metadata(pool.coin_a_store), fungible_asset::store_metadata(pool.coin_b_store))
-}
-
- - - -
- - - -## Function `pow` - -a^x = 1 + sigma[(k^n)/n!] -k = x * ln(a) - - -
fun pow(base: &decimal128::Decimal128, exp: &decimal128::Decimal128): decimal128::Decimal128
-
- - - -
-Implementation - - -
fun pow(base: &Decimal128, exp: &Decimal128): Decimal128 {
-    assert!(
-        decimal128::val(base) != 0 && decimal128::val(base) < 2000000000000000000,
-        error::invalid_argument(EOUT_OF_BASE_RANGE),
-    );
-
-    let res = decimal128::one();
-    let (ln_a, neg) = ln(base);
-    let k = mul_decimal128s(&ln_a, exp);
-    let comp = k;
-    let index = 1;
-    let subs: vector<Decimal128> = vector[];
-    while (decimal128::val(&comp) > PRECISION) {
-        if (index & 1 == 1 && neg) {
-            vector::push_back(&mut subs, comp)
-        } else {
-            res = decimal128::add(&res, &comp)
-        };
-
-        comp = decimal128::div(&mul_decimal128s(&comp, &k), index + 1);
-        index = index + 1;
-    };
-
-    let index = 0;
-    while (index < vector::length(&subs)) {
-        let comp = vector::borrow(&subs, index);
-        res = decimal128::sub(&res, comp);
-        index = index + 1;
-    };
-
-    res
-}
-
- - - -
- - - -## Function `ln` - -ln(1 + a) = sigma[(-1) ^ (n + 1) * (a ^ n / n)] -https://en.wikipedia.org/wiki/Taylor_series#Natural_logarithm - - -
fun ln(num: &decimal128::Decimal128): (decimal128::Decimal128, bool)
-
- - - -
-Implementation - - -
fun ln(num: &Decimal128): (Decimal128, bool) {
-    let one = decimal128::val(&decimal128::one());
-    let num_val = decimal128::val(num);
-    let (a, a_neg) = if (num_val >= one) {
-        (decimal128::sub(num, &decimal128::one()), false)
-    } else {
-        (decimal128::sub(&decimal128::one(), num), true)
-    };
-
-    let res = decimal128::zero();
-    let comp = a;
-    let index = 1;
-
-    while (decimal128::val(&comp) > PRECISION) {
-        if (index & 1 == 0 && !a_neg) {
-            res = decimal128::sub(&res, &comp);
-        } else {
-            res = decimal128::add(&res, &comp);
-        };
-
-        // comp(old) = a ^ n / n
-        // comp(new) = comp(old) * a * n / (n + 1) = a ^ (n + 1) / (n + 1)
-        comp = decimal128::div(
-            &decimal128::new(decimal128::val(&mul_decimal128s(&comp, &a)) * index), // comp * a * index
-            index + 1,
-        );
-
-        index = index + 1;
-    };
-
-    (res, a_neg)
-}
-
- - - -
- - - -## Function `mul_decimal128s` - - - -
fun mul_decimal128s(decimal128_0: &decimal128::Decimal128, decimal128_1: &decimal128::Decimal128): decimal128::Decimal128
-
- - - -
-Implementation - - -
fun mul_decimal128s(decimal128_0: &Decimal128, decimal128_1: &Decimal128): Decimal128 {
-    let one = (decimal128::val(&decimal128::one()) as u256);
-    let val_mul = (decimal128::val(decimal128_0) as u256) * (decimal128::val(decimal128_1) as u256);
-    decimal128::new((val_mul / one as u128))
+    (
+        fungible_asset::store_metadata(pool.coin_a_store),
+        fungible_asset::store_metadata(pool.coin_b_store)
+    )
 }
 
- - - -
diff --git a/minitia_stdlib/doc/dispatchable_fungible_asset.md b/minitia_stdlib/doc/dispatchable_fungible_asset.md new file mode 100644 index 0000000..d5d9ac2 --- /dev/null +++ b/minitia_stdlib/doc/dispatchable_fungible_asset.md @@ -0,0 +1,382 @@ + + + +# Module `0x1::dispatchable_fungible_asset` + +This defines the fungible asset module that can issue fungible asset of any Metadata object. The +metadata object can be any object that equipped with Metadata resource. + +The dispatchable_fungible_asset wraps the existing fungible_asset module and adds the ability for token issuer +to customize the logic for withdraw and deposit operations. For example: + +- Deflation token: a fixed percentage of token will be destructed upon transfer. +- Transfer allowlist: token can only be transfered to addresses in the allow list. +- Predicated transfer: transfer can only happen when some certain predicate has been met. +- Loyalty token: a fixed loyalty will be paid to a designated address when a fungible asset transfer happens + +The api listed here intended to be an in-place replacement for defi applications that uses fungible_asset api directly +and is safe for non-dispatchable (aka vanilla) fungible assets as well. + +See AIP-73 for further discussion + + +- [Resource `TransferRefStore`](#0x1_dispatchable_fungible_asset_TransferRefStore) +- [Constants](#@Constants_0) +- [Function `register_dispatch_functions`](#0x1_dispatchable_fungible_asset_register_dispatch_functions) +- [Function `register_derive_supply_dispatch_function`](#0x1_dispatchable_fungible_asset_register_derive_supply_dispatch_function) +- [Function `withdraw`](#0x1_dispatchable_fungible_asset_withdraw) +- [Function `deposit`](#0x1_dispatchable_fungible_asset_deposit) +- [Function `transfer`](#0x1_dispatchable_fungible_asset_transfer) +- [Function `transfer_assert_minimum_deposit`](#0x1_dispatchable_fungible_asset_transfer_assert_minimum_deposit) +- [Function `derived_balance`](#0x1_dispatchable_fungible_asset_derived_balance) +- [Function `derived_supply`](#0x1_dispatchable_fungible_asset_derived_supply) + + +
use 0x1::error;
+use 0x1::function_info;
+use 0x1::fungible_asset;
+use 0x1::object;
+use 0x1::option;
+
+ + + + + +## Resource `TransferRefStore` + + + +
struct TransferRefStore has key
+
+ + + +##### Fields + + +
+
+transfer_ref: fungible_asset::TransferRef +
+
+ +
+
+ + + + +## Constants + + + + +Feature is not activated yet on the network. + + +
const ENOT_ACTIVATED: u64 = 3;
+
+ + + + + +Recipient is not getting the guaranteed value; + + +
const EAMOUNT_MISMATCH: u64 = 2;
+
+ + + + + +Dispatch target is not loaded. + + +
const ENOT_LOADED: u64 = 4;
+
+ + + + + +TransferRefStore doesn't exist on the fungible asset type. + + +
const ESTORE_NOT_FOUND: u64 = 1;
+
+ + + + + +## Function `register_dispatch_functions` + + + +
public fun register_dispatch_functions(constructor_ref: &object::ConstructorRef, withdraw_function: option::Option<function_info::FunctionInfo>, deposit_function: option::Option<function_info::FunctionInfo>, derived_balance_function: option::Option<function_info::FunctionInfo>)
+
+ + + +##### Implementation + + +
public fun register_dispatch_functions(
+    constructor_ref: &ConstructorRef,
+    withdraw_function: Option<FunctionInfo>,
+    deposit_function: Option<FunctionInfo>,
+    derived_balance_function: Option<FunctionInfo>
+) {
+    fungible_asset::register_dispatch_functions(
+        constructor_ref,
+        withdraw_function,
+        deposit_function,
+        derived_balance_function
+    );
+    let store_obj = &object::generate_signer(constructor_ref);
+    move_to<TransferRefStore>(
+        store_obj,
+        TransferRefStore {
+            transfer_ref: fungible_asset::generate_transfer_ref(constructor_ref)
+        }
+    );
+}
+
+ + + + + +## Function `register_derive_supply_dispatch_function` + + + +
public fun register_derive_supply_dispatch_function(constructor_ref: &object::ConstructorRef, dispatch_function: option::Option<function_info::FunctionInfo>)
+
+ + + +##### Implementation + + +
public fun register_derive_supply_dispatch_function(
+    constructor_ref: &ConstructorRef, dispatch_function: Option<FunctionInfo>
+) {
+    fungible_asset::register_derive_supply_dispatch_function(
+        constructor_ref, dispatch_function
+    );
+}
+
+ + + + + +## Function `withdraw` + +Withdraw amount of the fungible asset from store by the owner. + +The semantics of deposit will be governed by the function specified in DispatchFunctionStore. + + +
public fun withdraw<T: key>(owner: &signer, store: object::Object<T>, amount: u64): fungible_asset::FungibleAsset
+
+ + + +##### Implementation + + +
public fun withdraw<T: key>(
+    owner: &signer, store: Object<T>, amount: u64
+): FungibleAsset acquires TransferRefStore {
+    fungible_asset::withdraw_sanity_check(owner, store, false);
+    let func_opt = fungible_asset::withdraw_dispatch_function(store);
+    if (option::is_some(&func_opt)) {
+        let start_balance = fungible_asset::balance(store);
+        let func = option::borrow(&func_opt);
+        function_info::load_module_from_function(func);
+        let fa = dispatchable_withdraw(
+            store,
+            amount,
+            borrow_transfer_ref(store),
+            func
+        );
+        let end_balance = fungible_asset::balance(store);
+        assert!(
+            amount <= start_balance - end_balance,
+            error::aborted(EAMOUNT_MISMATCH)
+        );
+        fa
+    } else {
+        fungible_asset::withdraw_internal(object::object_address(&store), amount)
+    }
+}
+
+ + + + + +## Function `deposit` + +Deposit amount of the fungible asset to store. + +The semantics of deposit will be governed by the function specified in DispatchFunctionStore. + + +
public fun deposit<T: key>(store: object::Object<T>, fa: fungible_asset::FungibleAsset)
+
+ + + +##### Implementation + + +
public fun deposit<T: key>(store: Object<T>, fa: FungibleAsset) acquires TransferRefStore {
+    fungible_asset::deposit_sanity_check(store, false);
+    let func_opt = fungible_asset::deposit_dispatch_function(store);
+    if (option::is_some(&func_opt)) {
+        let func = option::borrow(&func_opt);
+        function_info::load_module_from_function(func);
+        dispatchable_deposit(
+            store,
+            fa,
+            borrow_transfer_ref(store),
+            func
+        )
+    } else {
+        fungible_asset::deposit_internal(object::object_address(&store), fa)
+    }
+}
+
+ + + + + +## Function `transfer` + +Transfer an amount of fungible asset from from_store, which should be owned by sender, to receiver. +Note: it does not move the underlying object. + + +
public entry fun transfer<T: key>(sender: &signer, from: object::Object<T>, to: object::Object<T>, amount: u64)
+
+ + + +##### Implementation + + +
public entry fun transfer<T: key>(
+    sender: &signer,
+    from: Object<T>,
+    to: Object<T>,
+    amount: u64
+) acquires TransferRefStore {
+    let fa = withdraw(sender, from, amount);
+    deposit(to, fa);
+}
+
+ + + + + +## Function `transfer_assert_minimum_deposit` + +Transfer an amount of fungible asset from from_store, which should be owned by sender, to receiver. +The recipient is guranteed to receive asset greater than the expected amount. +Note: it does not move the underlying object. + + +
public entry fun transfer_assert_minimum_deposit<T: key>(sender: &signer, from: object::Object<T>, to: object::Object<T>, amount: u64, expected: u64)
+
+ + + +##### Implementation + + +
public entry fun transfer_assert_minimum_deposit<T: key>(
+    sender: &signer,
+    from: Object<T>,
+    to: Object<T>,
+    amount: u64,
+    expected: u64
+) acquires TransferRefStore {
+    let start = fungible_asset::balance(to);
+    let fa = withdraw(sender, from, amount);
+    deposit(to, fa);
+    let end = fungible_asset::balance(to);
+    assert!(end - start >= expected, error::aborted(EAMOUNT_MISMATCH));
+}
+
+ + + + + +## Function `derived_balance` + +Get the derived value of store using the overloaded hook. + +The semantics of value will be governed by the function specified in DispatchFunctionStore. + + +
#[view]
+public fun derived_balance<T: key>(store: object::Object<T>): u64
+
+ + + +##### Implementation + + +
public fun derived_balance<T: key>(store: Object<T>): u64 {
+    let func_opt = fungible_asset::derived_balance_dispatch_function(store);
+    if (option::is_some(&func_opt)) {
+        let func = option::borrow(&func_opt);
+        function_info::load_module_from_function(func);
+        dispatchable_derived_balance(store, func)
+    } else {
+        fungible_asset::balance(store)
+    }
+}
+
+ + + + + +## Function `derived_supply` + +Get the derived supply of the fungible asset using the overloaded hook. + +The semantics of supply will be governed by the function specified in DeriveSupplyDispatch. + + +
#[view]
+public fun derived_supply<T: key>(metadata: object::Object<T>): option::Option<u128>
+
+ + + +##### Implementation + + +
public fun derived_supply<T: key>(metadata: Object<T>): Option<u128> {
+    let func_opt = fungible_asset::derived_supply_dispatch_function(metadata);
+    if (option::is_some(&func_opt)) {
+        let func = option::borrow(&func_opt);
+        function_info::load_module_from_function(func);
+        dispatchable_derived_supply(metadata, func)
+    } else {
+        fungible_asset::supply(metadata)
+    }
+}
+
diff --git a/minitia_stdlib/doc/ed25519.md b/minitia_stdlib/doc/ed25519.md index 4f8891a..21787aa 100644 --- a/minitia_stdlib/doc/ed25519.md +++ b/minitia_stdlib/doc/ed25519.md @@ -17,8 +17,6 @@ Contains functions for: - [Function `signature_to_bytes`](#0x1_ed25519_signature_to_bytes) - [Function `verify`](#0x1_ed25519_verify) - [Function `batch_verify`](#0x1_ed25519_batch_verify) -- [Function `verify_internal`](#0x1_ed25519_verify_internal) -- [Function `batch_verify_internal`](#0x1_ed25519_batch_verify_internal)
use 0x1::error;
@@ -38,8 +36,7 @@ A Ed25519 public key
 
 
 
-
-Fields +##### Fields
@@ -52,8 +49,6 @@ A Ed25519 public key
-
- ## Struct `Signature` @@ -66,8 +61,7 @@ A Ed25519 signature that can be verified via verify_internal or -Fields +##### Fields
@@ -80,13 +74,21 @@ A Ed25519 signature that can be verified via verify_internal or - - ## Constants + + +The number of messages, public keys, and signatures do not match. + + +
const E_UNMATCHED_ARGS_LENGTH: u64 = 3;
+
+ + + Wrong number of bytes were given as input when deserializing an Ed25519 public key. @@ -139,14 +141,13 @@ Contructs an PublicKey struct, given 32-byte representation. -
-Implementation +##### Implementation
public fun public_key_from_bytes(bytes: vector<u8>): PublicKey {
     assert!(
         std::vector::length(&bytes) == PUBLIC_KEY_SIZE,
-        std::error::invalid_argument(PUBLIC_KEY_SIZE),
+        std::error::invalid_argument(PUBLIC_KEY_SIZE)
     );
     PublicKey { bytes }
 }
@@ -154,8 +155,6 @@ Contructs an PublicKey struct, given 32-byte representation.
 
 
 
-
- ## Function `signature_from_bytes` @@ -168,20 +167,20 @@ Constructs an Signature struct from the given 64 bytes. -
-Implementation +##### Implementation
public fun signature_from_bytes(bytes: vector<u8>): Signature {
-    assert!(std::vector::length(&bytes) == SIGNATURE_SIZE, std::error::invalid_argument(E_WRONG_SIGNATURE_SIZE));
+    assert!(
+        std::vector::length(&bytes) == SIGNATURE_SIZE,
+        std::error::invalid_argument(E_WRONG_SIGNATURE_SIZE)
+    );
     Signature { bytes }
 }
 
-
- ## Function `public_key_to_bytes` @@ -194,8 +193,7 @@ Serializes an PublicKey struct to bytes. -
-Implementation +##### Implementation
public fun public_key_to_bytes(pk: &PublicKey): vector<u8> {
@@ -205,8 +203,6 @@ Serializes an PublicKey struct to bytes.
 
 
 
-
- ## Function `signature_to_bytes` @@ -219,8 +215,7 @@ Serializes an Signature struct to bytes. -
-Implementation +##### Implementation
public fun signature_to_bytes(sig: &Signature): vector<u8> {
@@ -230,8 +225,6 @@ Serializes an Signature struct to bytes.
 
 
 
-
- ## Function `verify` @@ -244,23 +237,22 @@ Verifies a Ed25519 signature under an public_key on th -
-Implementation +##### Implementation
public fun verify(
-    message: vector<u8>,
-    public_key: &PublicKey,
-    signature: &Signature,
+    message: vector<u8>, public_key: &PublicKey, signature: &Signature
 ): bool {
-    verify_internal(message, public_key.bytes, signature.bytes)
+    verify_internal(
+        message,
+        public_key.bytes,
+        signature.bytes
+    )
 }
 
-
- ## Function `batch_verify` @@ -288,67 +280,39 @@ case. -
-Implementation +##### Implementation
public fun batch_verify(
     messages: vector<vector<u8>>,
     public_keys: vector<PublicKey>,
-    signatures: vector<Signature>,
+    signatures: vector<Signature>
 ): bool {
+    let message_length = std::vector::length(&messages);
+    let public_key_length = std::vector::length(&public_keys);
+    let signature_length = std::vector::length(&signatures);
+
+    if (message_length == 1) {
+        assert!(
+            public_key_length == signature_length,
+            std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH)
+        );
+        if (public_key_length == 0) return true;
+    } else if (public_key_length == 1) {
+        assert!(
+            message_length == signature_length,
+            std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH)
+        );
+        if (message_length == 0) return true;
+    } else {
+        assert!(
+            message_length == public_key_length
+                && public_key_length == signature_length,
+            std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH)
+        );
+        if (message_length == 0) return true;
+    };
+
     batch_verify_internal(messages, public_keys, signatures)
 }
 
- - - -
- - - -## Function `verify_internal` - - - -
fun verify_internal(message: vector<u8>, public_key: vector<u8>, signature: vector<u8>): bool
-
- - - -
-Implementation - - -
native fun verify_internal(message: vector<u8>, public_key: vector<u8>, signature: vector<u8>): bool;
-
- - - -
- - - -## Function `batch_verify_internal` - - - -
fun batch_verify_internal(messages: vector<vector<u8>>, public_keys: vector<ed25519::PublicKey>, signatures: vector<ed25519::Signature>): bool
-
- - - -
-Implementation - - -
native fun batch_verify_internal(
-    messages: vector<vector<u8>>,
-    public_keys: vector<PublicKey>,
-    signatures: vector<Signature>
-): bool;
-
- - - -
diff --git a/minitia_stdlib/doc/event.md b/minitia_stdlib/doc/event.md index b46a429..caafc44 100644 --- a/minitia_stdlib/doc/event.md +++ b/minitia_stdlib/doc/event.md @@ -6,7 +6,6 @@ - [Function `emit`](#0x1_event_emit) -- [Function `write_module_event_to_store`](#0x1_event_write_module_event_to_store)
@@ -20,43 +19,15 @@ Emit an event with payload msg by using handle_ref's key and counter. -
public fun emit<T: drop, store>(msg: T)
+
public fun emit<T: drop>(msg: T)
 
-
-Implementation +##### Implementation -
public fun emit<T: store + drop>(msg: T) {
-    write_module_event_to_store<T>(msg);
+
public fun emit<T: drop>(msg: T) {
+    emit_event<T>(&msg);
 }
 
- - - -
- - - -## Function `write_module_event_to_store` - -Log msg with the event stream identified by T - - -
fun write_module_event_to_store<T: drop, store>(msg: T)
-
- - - -
-Implementation - - -
native fun write_module_event_to_store<T: drop + store>(msg: T);
-
- - - -
diff --git a/minitia_stdlib/doc/fixed_point64.md b/minitia_stdlib/doc/fixed_point64.md index b355b2e..9da9a36 100644 --- a/minitia_stdlib/doc/fixed_point64.md +++ b/minitia_stdlib/doc/fixed_point64.md @@ -9,19 +9,39 @@ a 64-bit fractional part. - [Struct `FixedPoint64`](#0x1_fixed_point64_FixedPoint64) - [Constants](#@Constants_0) +- [Function `one`](#0x1_fixed_point64_one) +- [Function `zero`](#0x1_fixed_point64_zero) +- [Function `rev`](#0x1_fixed_point64_rev) +- [Function `sub`](#0x1_fixed_point64_sub) +- [Function `sub_u64`](#0x1_fixed_point64_sub_u64) +- [Function `sub_u128`](#0x1_fixed_point64_sub_u128) +- [Function `add`](#0x1_fixed_point64_add) +- [Function `add_u64`](#0x1_fixed_point64_add_u64) +- [Function `add_u128`](#0x1_fixed_point64_add_u128) +- [Function `multiply`](#0x1_fixed_point64_multiply) +- [Function `multiply_u64`](#0x1_fixed_point64_multiply_u64) - [Function `multiply_u128`](#0x1_fixed_point64_multiply_u128) +- [Function `divide`](#0x1_fixed_point64_divide) +- [Function `divide_u64`](#0x1_fixed_point64_divide_u64) +- [Function `divide_by_u64`](#0x1_fixed_point64_divide_by_u64) - [Function `divide_u128`](#0x1_fixed_point64_divide_u128) +- [Function `divide_by_u128`](#0x1_fixed_point64_divide_by_u128) - [Function `create_from_rational`](#0x1_fixed_point64_create_from_rational) - [Function `create_from_raw_value`](#0x1_fixed_point64_create_from_raw_value) - [Function `get_raw_value`](#0x1_fixed_point64_get_raw_value) - [Function `is_zero`](#0x1_fixed_point64_is_zero) - [Function `min`](#0x1_fixed_point64_min) - [Function `max`](#0x1_fixed_point64_max) +- [Function `less_or_equal`](#0x1_fixed_point64_less_or_equal) +- [Function `less`](#0x1_fixed_point64_less) +- [Function `greater_or_equal`](#0x1_fixed_point64_greater_or_equal) +- [Function `greater`](#0x1_fixed_point64_greater) +- [Function `equal`](#0x1_fixed_point64_equal) +- [Function `almost_equal`](#0x1_fixed_point64_almost_equal) - [Function `create_from_u128`](#0x1_fixed_point64_create_from_u128) - [Function `floor`](#0x1_fixed_point64_floor) - [Function `ceil`](#0x1_fixed_point64_ceil) - [Function `round`](#0x1_fixed_point64_round) -- [Module Specification](#@Module_Specification_1)
@@ -48,8 +68,7 @@ decimal. -
-Fields +##### Fields
@@ -62,13 +81,20 @@ decimal.
-
- ## Constants + + + + +
const MAX_U64: u128 = 18446744073709551615;
+
+ + + @@ -78,6 +104,16 @@ decimal. + + +A division by zero was encountered + + +
const EDIVISION_BY_ZERO: u64 = 65540;
+
+ + + The denominator provided was zero @@ -98,22 +134,22 @@ The quotient value would be too large to be held in a u128 - + -A division by zero was encountered +The multiplied value would be too large to be held in a u128 -
const EDIVISION_BY_ZERO: u64 = 65540;
+
const EMULTIPLICATION: u64 = 131075;
 
- + -The multiplied value would be too large to be held in a u128 +Abort code on calculation result is negative. -
const EMULTIPLICATION: u64 = 131075;
+
const ENEGATIVE_RESULT: u64 = 65542;
 
@@ -128,6 +164,259 @@ The computed ratio when converting to a + +## Function `one` + + + +
public fun one(): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun one(): FixedPoint64 {
+    create_from_raw_value(1 << 64)
+}
+
+ + + + + +## Function `zero` + + + +
public fun zero(): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun zero(): FixedPoint64 {
+    create_from_raw_value(0)
+}
+
+ + + + + +## Function `rev` + + + +
public fun rev(self: fixed_point64::FixedPoint64): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun rev(self: FixedPoint64): FixedPoint64 {
+    create_from_raw_value(((1u256 << 128) / (get_raw_value(self) as u256) as u128))
+}
+
+ + + + + +## Function `sub` + +Returns self - y. self must be not less than y. + + +
public fun sub(self: fixed_point64::FixedPoint64, y: fixed_point64::FixedPoint64): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun sub(self: FixedPoint64, y: FixedPoint64): FixedPoint64 {
+    let x_raw = get_raw_value(self);
+    let y_raw = get_raw_value(y);
+    assert!(x_raw >= y_raw, ENEGATIVE_RESULT);
+    create_from_raw_value(x_raw - y_raw)
+}
+
+ + + + + +## Function `sub_u64` + + + +
public fun sub_u64(self: fixed_point64::FixedPoint64, y: u64): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun sub_u64(self: FixedPoint64, y: u64): FixedPoint64 {
+    sub_u128(self, (y as u128))
+}
+
+ + + + + +## Function `sub_u128` + + + +
public fun sub_u128(self: fixed_point64::FixedPoint64, y: u128): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun sub_u128(self: FixedPoint64, y: u128): FixedPoint64 {
+    let x_raw = (get_raw_value(self) as u256);
+    let y_raw = (y as u256) << 64;
+    assert!(x_raw >= y_raw, ENEGATIVE_RESULT);
+    create_from_raw_value(((x_raw - y_raw) as u128))
+}
+
+ + + + + +## Function `add` + +Returns self + y. The result cannot be greater than MAX_U128. + + +
public fun add(self: fixed_point64::FixedPoint64, y: fixed_point64::FixedPoint64): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun add(self: FixedPoint64, y: FixedPoint64): FixedPoint64 {
+    let x_raw = get_raw_value(self);
+    let y_raw = get_raw_value(y);
+    let result = (x_raw as u256) + (y_raw as u256);
+    assert!(result <= MAX_U128, ERATIO_OUT_OF_RANGE);
+    create_from_raw_value((result as u128))
+}
+
+ + + + + +## Function `add_u64` + + + +
public fun add_u64(self: fixed_point64::FixedPoint64, y: u64): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun add_u64(self: FixedPoint64, y: u64): FixedPoint64 {
+    add_u128(self, (y as u128))
+}
+
+ + + + + +## Function `add_u128` + + + +
public fun add_u128(self: fixed_point64::FixedPoint64, y: u128): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun add_u128(self: FixedPoint64, y: u128): FixedPoint64 {
+    let x_raw = (get_raw_value(self) as u256);
+    let y_raw = (y as u256) << 64;
+    let result = x_raw + y_raw;
+    assert!(result <= MAX_U128, ERATIO_OUT_OF_RANGE);
+    create_from_raw_value((result as u128))
+}
+
+ + + + + +## Function `multiply` + + + +
public fun multiply(self: fixed_point64::FixedPoint64, y: fixed_point64::FixedPoint64): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun multiply(self: FixedPoint64, y: FixedPoint64): FixedPoint64 {
+    let x_raw = get_raw_value(self);
+    let y_raw = get_raw_value(y);
+    let result = ((x_raw as u256) * (y_raw as u256)) >> 64;
+    assert!(result <= MAX_U128, EMULTIPLICATION);
+    create_from_raw_value((result as u128))
+}
+
+ + + + + +## Function `multiply_u64` + + + +
public fun multiply_u64(val: u64, multiplier: fixed_point64::FixedPoint64): u64
+
+ + + +##### Implementation + + +
public fun multiply_u64(val: u64, multiplier: FixedPoint64): u64 {
+    let res = multiply_u128((val as u128), multiplier);
+    assert!(res <= MAX_U64, EMULTIPLICATION);
+    (res as u64)
+}
+
+ + + ## Function `multiply_u128` @@ -142,8 +431,7 @@ overflows. -
-Implementation +##### Implementation
public fun multiply_u128(val: u128, multiplier: FixedPoint64): u128 {
@@ -162,45 +450,79 @@ overflows.
 
 
 
-
+ -
-Specification +## Function `divide` -
pragma opaque;
-include MultiplyAbortsIf;
-ensures result == spec_multiply_u128(val, multiplier);
+
public fun divide(self: fixed_point64::FixedPoint64, divisor: fixed_point64::FixedPoint64): fixed_point64::FixedPoint64
 
+##### Implementation - - -
schema MultiplyAbortsIf {
-    val: num;
-    multiplier: FixedPoint64;
-    aborts_if spec_multiply_u128(val, multiplier) > MAX_U128 with EMULTIPLICATION;
+
public fun divide(self: FixedPoint64, divisor: FixedPoint64): FixedPoint64 {
+    // Check for division by zero.
+    assert!(divisor.value != 0, EDIVISION_BY_ZERO);
+    // Perform the division with 256 bits to avoid losing accuracy.
+    let result = ((self.value as u256) << 64) / (divisor.value as u256);
+    assert!(result <= MAX_U128, EDIVISION);
+    create_from_raw_value((result as u128))
 }
 
+ + +## Function `divide_u64` + +Divide a u64 integer by a fixed-point number, truncating any +fractional part of the quotient. This will abort if the divisor +is zero or if the quotient overflows. + + +
public fun divide_u64(val: u64, divisor: fixed_point64::FixedPoint64): u64
+
+ - +##### Implementation -
fun spec_multiply_u128(val: num, multiplier: FixedPoint64): num {
-   (val * multiplier.value) >> 64
+
+
public fun divide_u64(val: u64, divisor: FixedPoint64): u64 {
+    let res = divide_u128((val as u128), divisor);
+    assert!(res <= MAX_U64, EDIVISION);
+    (res as u64)
 }
 
-
+ + +## Function `divide_by_u64` + +Divide a fixed-point number by a u64 integer. + + +
public fun divide_by_u64(val: fixed_point64::FixedPoint64, divisor: u64): fixed_point64::FixedPoint64
+
+ + + +##### Implementation + + +
public fun divide_by_u64(val: FixedPoint64, divisor: u64): FixedPoint64 {
+    divide_by_u128(val, (divisor as u128))
+}
+
+ + @@ -216,8 +538,7 @@ is zero or if the quotient overflows. -
-Implementation +##### Implementation
public fun divide_u128(val: u128, divisor: FixedPoint64): u128 {
@@ -237,47 +558,30 @@ is zero or if the quotient overflows.
 
 
 
-
- -
-Specification - - - -
pragma opaque;
-include DivideAbortsIf;
-ensures result == spec_divide_u128(val, divisor);
-
- - + +## Function `divide_by_u128` - +Divide a fixed-point number by a u128 integer. -
schema DivideAbortsIf {
-    val: num;
-    divisor: FixedPoint64;
-    aborts_if divisor.value == 0 with EDIVISION_BY_ZERO;
-    aborts_if spec_divide_u128(val, divisor) > MAX_U128 with EDIVISION;
-}
+
public fun divide_by_u128(val: fixed_point64::FixedPoint64, divisor: u128): fixed_point64::FixedPoint64
 
- - +##### Implementation -
fun spec_divide_u128(val: num, divisor: FixedPoint64): num {
-   (val << 64) / divisor.value
+
public fun divide_by_u128(val: FixedPoint64, divisor: u128): FixedPoint64 {
+    // Check for division by zero.
+    assert!(divisor != 0, EDIVISION_BY_ZERO);
+    create_from_raw_value(get_raw_value(val) / divisor)
 }
 
-
- ## Function `create_from_rational` @@ -299,8 +603,7 @@ rounding, e.g., 0.0125 will round down to 0.012 instead of up to 0.013. -
-Implementation +##### Implementation
public fun create_from_rational(numerator: u128, denominator: u128): FixedPoint64 {
@@ -320,52 +623,6 @@ rounding, e.g., 0.0125 will round down to 0.012 instead of up to 0.013.
 
 
 
-
- -
-Specification - - - -
pragma opaque;
-pragma verify = false;
-include CreateFromRationalAbortsIf;
-ensures result == spec_create_from_rational(numerator, denominator);
-
- - - - - - - -
schema CreateFromRationalAbortsIf {
-    numerator: u128;
-    denominator: u128;
-    let scaled_numerator = (numerator as u256)<< 64;
-    let scaled_denominator = (denominator as u256);
-    let quotient = scaled_numerator / scaled_denominator;
-    aborts_if scaled_denominator == 0 with EDENOMINATOR;
-    aborts_if quotient == 0 && scaled_numerator != 0 with ERATIO_OUT_OF_RANGE;
-    aborts_if quotient > MAX_U128 with ERATIO_OUT_OF_RANGE;
-}
-
- - - - - - - -
fun spec_create_from_rational(numerator: num, denominator: num): FixedPoint64 {
-   FixedPoint64{value: (numerator << 128) / (denominator << 64)}
-}
-
- - - -
- ## Function `create_from_raw_value` @@ -378,8 +635,7 @@ Create a fixedpoint value from a raw value. -
-Implementation +##### Implementation
public fun create_from_raw_value(value: u128): FixedPoint64 {
@@ -389,22 +645,6 @@ Create a fixedpoint value from a raw value.
 
 
 
-
- -
-Specification - - - -
pragma opaque;
-aborts_if false;
-ensures result.value == value;
-
- - - -
- ## Function `get_raw_value` @@ -414,24 +654,21 @@ adding or subtracting FixedPoint64 values, can be done using the raw values directly. -
public fun get_raw_value(num: fixed_point64::FixedPoint64): u128
+
public fun get_raw_value(self: fixed_point64::FixedPoint64): u128
 
-
-Implementation +##### Implementation -
public fun get_raw_value(num: FixedPoint64): u128 {
-    num.value
+
public fun get_raw_value(self: FixedPoint64): u128 {
+    self.value
 }
 
-
- ## Function `is_zero` @@ -439,24 +676,21 @@ values directly. Returns true if the ratio is zero. -
public fun is_zero(num: fixed_point64::FixedPoint64): bool
+
public fun is_zero(self: fixed_point64::FixedPoint64): bool
 
-
-Implementation +##### Implementation -
public fun is_zero(num: FixedPoint64): bool {
-    num.value == 0
+
public fun is_zero(self: FixedPoint64): bool {
+    self.value == 0
 }
 
-
- ## Function `min` @@ -469,52 +703,17 @@ Returns the smaller of the two FixedPoint64 numbers. -
-Implementation +##### Implementation
public fun min(num1: FixedPoint64, num2: FixedPoint64): FixedPoint64 {
-    if (num1.value < num2.value) {
-        num1
-    } else {
-        num2
-    }
-}
-
- - - -
- -
-Specification - - - -
pragma opaque;
-aborts_if false;
-ensures result == spec_min(num1, num2);
-
- - - - - - - -
fun spec_min(num1: FixedPoint64, num2: FixedPoint64): FixedPoint64 {
-   if (num1.value < num2.value) {
-       num1
-   } else {
-       num2
-   }
+    if (num1.value < num2.value) { num1 }
+    else { num2 }
 }
 
-
- ## Function `max` @@ -527,305 +726,250 @@ Returns the larger of the two FixedPoint64 numbers. -
-Implementation +##### Implementation
public fun max(num1: FixedPoint64, num2: FixedPoint64): FixedPoint64 {
-    if (num1.value > num2.value) {
-        num1
-    } else {
-        num2
-    }
+    if (num1.value > num2.value) { num1 }
+    else { num2 }
 }
 
-
+ -
-Specification +## Function `less_or_equal` +Returns true if self <= num2 -
pragma opaque;
-aborts_if false;
-ensures result == spec_max(num1, num2);
+
public fun less_or_equal(self: fixed_point64::FixedPoint64, num2: fixed_point64::FixedPoint64): bool
 
- - +##### Implementation -
fun spec_max(num1: FixedPoint64, num2: FixedPoint64): FixedPoint64 {
-   if (num1.value > num2.value) {
-       num1
-   } else {
-       num2
-   }
+
public fun less_or_equal(self: FixedPoint64, num2: FixedPoint64): bool {
+    self.value <= num2.value
 }
 
-
+ - +## Function `less` -## Function `create_from_u128` - -Create a fixedpoint value from a u128 value. +Returns true if self < num2 -
public fun create_from_u128(val: u128): fixed_point64::FixedPoint64
+
public fun less(self: fixed_point64::FixedPoint64, num2: fixed_point64::FixedPoint64): bool
 
-
-Implementation +##### Implementation -
public fun create_from_u128(val: u128): FixedPoint64 {
-    let value = (val as u256) << 64;
-    assert!(value <= MAX_U128, ERATIO_OUT_OF_RANGE);
-    FixedPoint64 {value: (value as u128)}
+
public fun less(self: FixedPoint64, num2: FixedPoint64): bool {
+    self.value < num2.value
 }
 
-
- -
-Specification + +## Function `greater_or_equal` - -
pragma opaque;
-include CreateFromU64AbortsIf;
-ensures result == spec_create_from_u128(val);
-
- +Returns true if self >= num2 - - - - -
schema CreateFromU64AbortsIf {
-    val: num;
-    let scaled_value = (val as u256) << 64;
-    aborts_if scaled_value > MAX_U128;
-}
+
public fun greater_or_equal(self: fixed_point64::FixedPoint64, num2: fixed_point64::FixedPoint64): bool
 
+##### Implementation - - -
fun spec_create_from_u128(val: num): FixedPoint64 {
-   FixedPoint64 {value: val << 64}
+
public fun greater_or_equal(self: FixedPoint64, num2: FixedPoint64): bool {
+    self.value >= num2.value
 }
 
-
- - + -## Function `floor` +## Function `greater` -Returns the largest integer less than or equal to a given number. +Returns true if self > num2 -
public fun floor(num: fixed_point64::FixedPoint64): u128
+
public fun greater(self: fixed_point64::FixedPoint64, num2: fixed_point64::FixedPoint64): bool
 
-
-Implementation +##### Implementation -
public fun floor(num: FixedPoint64): u128 {
-    num.value >> 64
+
public fun greater(self: FixedPoint64, num2: FixedPoint64): bool {
+    self.value > num2.value
 }
 
-
+ -
-Specification +## Function `equal` +Returns true if self = num2 -
pragma opaque;
-aborts_if false;
-ensures result == spec_floor(num);
+
public fun equal(self: fixed_point64::FixedPoint64, num2: fixed_point64::FixedPoint64): bool
 
- - +##### Implementation -
fun spec_floor(val: FixedPoint64): u128 {
-   let fractional = val.value % (1 << 64);
-   if (fractional == 0) {
-       val.value >> 64
-   } else {
-       (val.value - fractional) >> 64
-   }
+
public fun equal(self: FixedPoint64, num2: FixedPoint64): bool {
+    self.value == num2.value
 }
 
-
+ - +## Function `almost_equal` -## Function `ceil` +Returns true if self almost equals to num2, which means abs(num1-num2) <= precision -Rounds up the given FixedPoint64 to the next largest integer. - -
public fun ceil(num: fixed_point64::FixedPoint64): u128
+
public fun almost_equal(self: fixed_point64::FixedPoint64, num2: fixed_point64::FixedPoint64, precision: fixed_point64::FixedPoint64): bool
 
-
-Implementation +##### Implementation -
public fun ceil(num: FixedPoint64): u128 {
-    let floored_num = floor(num) << 64;
-    if (num.value == floored_num) {
-        return floored_num >> 64
-    };
-    let val = ((floored_num as u256) + (1 << 64));
-    (val >> 64 as u128)
+
public fun almost_equal(
+    self: FixedPoint64, num2: FixedPoint64, precision: FixedPoint64
+): bool {
+    if (self.value > num2.value) {
+        (self.value - num2.value <= precision.value)
+    } else {
+        (num2.value - self.value <= precision.value)
+    }
 }
 
-
- -
-Specification + +## Function `create_from_u128` -TODO: worked in the past but started to time out since last z3 update +Create a fixedpoint value from a u128 value. -
pragma verify = false;
-pragma opaque;
-aborts_if false;
-ensures result == spec_ceil(num);
+
public fun create_from_u128(val: u128): fixed_point64::FixedPoint64
 
- - +##### Implementation -
fun spec_ceil(val: FixedPoint64): u128 {
-   let fractional = val.value % (1 << 64);
-   let one = 1 << 64;
-   if (fractional == 0) {
-       val.value >> 64
-   } else {
-       (val.value - fractional + one) >> 64
-   }
+
public fun create_from_u128(val: u128): FixedPoint64 {
+    let value = (val as u256) << 64;
+    assert!(value <= MAX_U128, ERATIO_OUT_OF_RANGE);
+    FixedPoint64 { value: (value as u128) }
 }
 
-
- - + -## Function `round` +## Function `floor` -Returns the value of a FixedPoint64 to the nearest integer. +Returns the largest integer less than or equal to a given number. -
public fun round(num: fixed_point64::FixedPoint64): u128
+
public fun floor(self: fixed_point64::FixedPoint64): u128
 
-
-Implementation +##### Implementation -
public fun round(num: FixedPoint64): u128 {
-    let floored_num = floor(num) << 64;
-    let boundary = floored_num + ((1 << 64) / 2);
-    if (num.value < boundary) {
-        floored_num >> 64
-    } else {
-        ceil(num)
-    }
+
public fun floor(self: FixedPoint64): u128 {
+    self.value >> 64
 }
 
-
+ -
-Specification +## Function `ceil` +Rounds up the given FixedPoint64 to the next largest integer. -
pragma opaque;
-aborts_if false;
-ensures result == spec_round(num);
+
public fun ceil(self: fixed_point64::FixedPoint64): u128
 
- - +##### Implementation -
fun spec_round(val: FixedPoint64): u128 {
-   let fractional = val.value % (1 << 64);
-   let boundary = (1 << 64) / 2;
-   let one = 1 << 64;
-   if (fractional < boundary) {
-       (val.value - fractional) >> 64
-   } else {
-       (val.value - fractional + one) >> 64
-   }
+
public fun ceil(self: FixedPoint64): u128 {
+    let floored_num = floor(self) << 64;
+    if (self.value == floored_num) {
+        return floored_num >> 64
+    };
+    let val = ((floored_num as u256) + (1 << 64));
+    (val >> 64 as u128)
 }
 
-
+ + +## Function `round` + +Returns the value of a FixedPoint64 to the nearest integer. + - +
public fun round(self: fixed_point64::FixedPoint64): u128
+
-## Module Specification +##### Implementation -
pragma aborts_if_is_strict;
+
public fun round(self: FixedPoint64): u128 {
+    let floored_num = floor(self) << 64;
+    let boundary = floored_num + ((1 << 64) / 2);
+    if (self.value < boundary) {
+        floored_num >> 64
+    } else {
+        ceil(self)
+    }
+}
 
diff --git a/minitia_stdlib/doc/from_bcs.md b/minitia_stdlib/doc/from_bcs.md index 34e36ce..1cc6479 100644 --- a/minitia_stdlib/doc/from_bcs.md +++ b/minitia_stdlib/doc/from_bcs.md @@ -64,8 +64,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_bool(v: vector<u8>): bool {
@@ -75,8 +74,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_u8` @@ -88,8 +85,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_u8(v: vector<u8>): u8 {
@@ -99,8 +95,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_u16` @@ -112,8 +106,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_u16(v: vector<u8>): u16 {
@@ -123,8 +116,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_u32` @@ -136,8 +127,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_u32(v: vector<u8>): u32 {
@@ -147,8 +137,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_u64` @@ -160,8 +148,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_u64(v: vector<u8>): u64 {
@@ -171,8 +158,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_u128` @@ -184,8 +169,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_u128(v: vector<u8>): u128 {
@@ -195,8 +179,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_u256` @@ -208,8 +190,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_u256(v: vector<u8>): u256 {
@@ -219,8 +200,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_address` @@ -232,8 +211,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_address(v: vector<u8>): address {
@@ -243,8 +221,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_bytes` @@ -256,8 +232,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_bytes(v: vector<u8>): vector<u8> {
@@ -267,8 +242,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_vector_bytes` @@ -280,8 +253,7 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_vector_bytes(v: vector<u8>): vector<vector<u8>> {
@@ -291,8 +263,6 @@ UTF8 check failed in conversion from bytes to string
 
 
 
-
- ## Function `to_vector_string` @@ -304,19 +274,26 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_vector_string(v: vector<u8>): vector<String> {
-    from_bytes<vector<String>>(v)
+    let vec_string = from_bytes<vector<String>>(v);
+    vector::for_each_ref(
+        &vec_string,
+        |s| {
+            assert!(
+                string::internal_check_utf8(string::bytes(s)),
+                EINVALID_UTF8
+            );
+        }
+    );
+    vec_string
 }
 
-
- ## Function `to_string` @@ -328,22 +305,22 @@ UTF8 check failed in conversion from bytes to string -
-Implementation +##### Implementation
public fun to_string(v: vector<u8>): String {
     // To make this safe, we need to evaluate the utf8 invariant.
     let s = from_bytes<String>(v);
-    assert!(string::internal_check_utf8(string::bytes(&s)), EINVALID_UTF8);
+    assert!(
+        string::internal_check_utf8(string::bytes(&s)),
+        EINVALID_UTF8
+    );
     s
 }
 
-
- ## Function `from_bytes` @@ -360,13 +337,8 @@ owned. -
-Implementation +##### Implementation
public(friend) native fun from_bytes<T>(bytes: vector<u8>): T;
 
- - - -
diff --git a/minitia_stdlib/doc/function_info.md b/minitia_stdlib/doc/function_info.md new file mode 100644 index 0000000..7060485 --- /dev/null +++ b/minitia_stdlib/doc/function_info.md @@ -0,0 +1,214 @@ + + + +# Module `0x1::function_info` + +The function_info module defines the FunctionInfo type which simulates a function pointer. + + +- [Struct `FunctionInfo`](#0x1_function_info_FunctionInfo) +- [Constants](#@Constants_0) +- [Function `new_function_info`](#0x1_function_info_new_function_info) +- [Function `new_function_info_from_address`](#0x1_function_info_new_function_info_from_address) +- [Function `check_dispatch_type_compatibility`](#0x1_function_info_check_dispatch_type_compatibility) +- [Function `load_module_from_function`](#0x1_function_info_load_module_from_function) + + +
use 0x1::signer;
+use 0x1::string;
+
+ + + + + +## Struct `FunctionInfo` + +A String holds a sequence of bytes which is guaranteed to be in utf8 format. + + +
struct FunctionInfo has copy, drop, store
+
+ + + +##### Fields + + +
+
+module_address: address +
+
+ +
+
+module_name: string::String +
+
+ +
+
+function_name: string::String +
+
+ +
+
+ + + + +## Constants + + + + +Function specified in the FunctionInfo doesn't exist on chain. + + +
const EINVALID_FUNCTION: u64 = 2;
+
+ + + + + +String is not a valid Move identifier + + +
const EINVALID_IDENTIFIER: u64 = 1;
+
+ + + + + +Feature hasn't been activated yet. + + +
const ENOT_ACTIVATED: u64 = 3;
+
+ + + + + +## Function `new_function_info` + +Creates a new function info from names. + + +
public fun new_function_info(module_signer: &signer, module_name: string::String, function_name: string::String): function_info::FunctionInfo
+
+ + + +##### Implementation + + +
public fun new_function_info(
+    module_signer: &signer, module_name: String, function_name: String
+): FunctionInfo {
+    new_function_info_from_address(
+        signer::address_of(module_signer),
+        module_name,
+        function_name
+    )
+}
+
+ + + + + +## Function `new_function_info_from_address` + + + +
public(friend) fun new_function_info_from_address(module_address: address, module_name: string::String, function_name: string::String): function_info::FunctionInfo
+
+ + + +##### Implementation + + +
public(friend) fun new_function_info_from_address(
+    module_address: address, module_name: String, function_name: String
+): FunctionInfo {
+    assert!(
+        is_identifier(string::bytes(&module_name)),
+        EINVALID_IDENTIFIER
+    );
+    assert!(
+        is_identifier(string::bytes(&function_name)),
+        EINVALID_IDENTIFIER
+    );
+    FunctionInfo { module_address, module_name, function_name }
+}
+
+ + + + + +## Function `check_dispatch_type_compatibility` + +Check if the dispatch target function meets the type requirements of the disptach entry point. + +framework_function is the dispatch native function defined in the minitia_std. +dispatch_target is the function passed in by the user. + +dispatch_target should have the same signature (same argument type, same generics constraint) except +that the framework_function will have a &FunctionInfo in the last argument that will instruct the VM which +function to jump to. + +dispatch_target also needs to be public so the type signature will remain unchanged. + + +
public(friend) fun check_dispatch_type_compatibility(framework_function: &function_info::FunctionInfo, dispatch_target: &function_info::FunctionInfo): bool
+
+ + + +##### Implementation + + +
public(friend) fun check_dispatch_type_compatibility(
+    framework_function: &FunctionInfo, dispatch_target: &FunctionInfo
+): bool {
+    load_function_impl(dispatch_target);
+    check_dispatch_type_compatibility_impl(framework_function, dispatch_target)
+}
+
+ + + + + +## Function `load_module_from_function` + +Load up a function into VM's loader and charge for its dependencies + +It is **critical** to make sure that this function is invoked before check_dispatch_type_compatibility +or performing any other dispatching logic to ensure: +1. We properly charge gas for the function to dispatch. +2. The function is loaded in the cache so that we can perform further type checking/dispatching logic. + +Calling check_dispatch_type_compatibility_impl or dispatch without loading up the module would yield an error +if such module isn't accessed previously in the transaction. + + +
public(friend) fun load_module_from_function(f: &function_info::FunctionInfo)
+
+ + + +##### Implementation + + +
public(friend) fun load_module_from_function(f: &FunctionInfo) {
+    load_function_impl(f)
+}
+
diff --git a/minitia_stdlib/doc/fungible_asset.md b/minitia_stdlib/doc/fungible_asset.md index 13bc6e2..df55d5d 100644 --- a/minitia_stdlib/doc/fungible_asset.md +++ b/minitia_stdlib/doc/fungible_asset.md @@ -11,9 +11,12 @@ metadata object can be any object that equipped with use 0x1::error; +
use 0x1::account;
+use 0x1::error;
 use 0x1::event;
+use 0x1::function_info;
 use 0x1::object;
 use 0x1::option;
 use 0x1::signer;
@@ -88,8 +105,7 @@ metadata object can be any object that equipped with 
 
 
-
-
 
 
 ## Resource `Metadata`
@@ -117,13 +131,12 @@ metadata object can be any object that equipped with Metadata has key
+
struct Metadata has copy, drop, key
 
-
-Fields +##### Fields
@@ -164,8 +177,6 @@ Metadata of a Fungible asset
-
- ## Resource `FungibleStore` @@ -178,8 +189,7 @@ The store object that holds fungible assets of a specific type associated with a -
-Fields +##### Fields
@@ -204,8 +214,6 @@ The store object that holds fungible assets of a specific type associated with a
-
- ## Struct `FungibleAsset` @@ -219,8 +227,7 @@ FungibleAsset is ephemeral and cannot be stored directly. It must be deposited b -
-Fields +##### Fields
@@ -239,7 +246,65 @@ FungibleAsset is ephemeral and cannot be stored directly. It must be deposited b
-
+ + +## Resource `DispatchFunctionStore` + + + +
struct DispatchFunctionStore has key
+
+ + + +##### Fields + + +
+
+withdraw_function: option::Option<function_info::FunctionInfo> +
+
+ +
+
+deposit_function: option::Option<function_info::FunctionInfo> +
+
+ +
+
+derived_balance_function: option::Option<function_info::FunctionInfo> +
+
+ +
+
+ + + + +## Resource `DeriveSupply` + + + +
struct DeriveSupply has key
+
+ + + +##### Fields + + +
+
+dispatch_function: option::Option<function_info::FunctionInfo> +
+
+ +
+
+ @@ -253,8 +318,7 @@ MintRef can be used to mint the fungible asset into an account's store. -
-Fields +##### Fields
@@ -267,8 +331,6 @@ MintRef can be used to mint the fungible asset into an account's store.
-
- ## Struct `TransferRef` @@ -282,8 +344,7 @@ and allow the holder of TransferRef to transfer fungible assets from any account -
-Fields +##### Fields
@@ -296,8 +357,6 @@ and allow the holder of TransferRef to transfer fungible assets from any account
-
- ## Struct `BurnRef` @@ -310,8 +369,7 @@ BurnRef can be used to burn fungible assets from a given holder account. -
-Fields +##### Fields
@@ -324,7 +382,30 @@ BurnRef can be used to burn fungible assets from a given holder account.
-
+ + +## Struct `MutateMetadataRef` + +MutateMetadataRef can be used to directly modify the fungible asset's Metadata. + + +
struct MutateMetadataRef has drop, store
+
+ + + +##### Fields + + +
+
+metadata: object::Object<fungible_asset::Metadata> +
+
+ +
+
+ @@ -339,8 +420,7 @@ Emitted when fungible assets are deposited into a store. -
-Fields +##### Fields
@@ -365,8 +445,6 @@ Emitted when fungible assets are deposited into a store.
-
- ## Struct `WithdrawEvent` @@ -380,8 +458,7 @@ Emitted when fungible assets are withdrawn from a store. -
-Fields +##### Fields
@@ -406,8 +483,6 @@ Emitted when fungible assets are withdrawn from a store.
-
- ## Struct `FrozenEvent` @@ -421,8 +496,7 @@ Emitted when a store's frozen status is updated. -
-Fields +##### Fields
@@ -447,8 +521,6 @@ Emitted when a store's frozen status is updated.
-
- ## Struct `BurnEvent` @@ -462,8 +534,7 @@ Emitted when fungible assets are burnt. -
-Fields +##### Fields
@@ -482,8 +553,6 @@ Emitted when fungible assets are burnt.
-
- ## Struct `MintEvent` @@ -497,8 +566,7 @@ Emitted when fungible assets are minted. -
-Fields +##### Fields
@@ -517,8 +585,6 @@ Emitted when fungible assets are minted.
-
- ## Constants @@ -534,6 +600,16 @@ Maximum possible coin supply. + + +Trying to re-register dispatch hook on a fungible asset. + + +
const EALREADY_REGISTERED: u64 = 29;
+
+ + + Cannot destroy non-empty fungible assets. @@ -544,6 +620,16 @@ Cannot destroy non-empty fungible assets. + + +Cannot register dispatch hook for APT. + + +
const EAPT_NOT_DISPATCHABLE: u64 = 31;
+
+ + + Cannot destroy fungible stores with a non-zero balance. @@ -574,6 +660,26 @@ Burn ref and store do not match. + + +Deposit to a blocked account is not allowed._ + + +
const ECANNOT_DEPOSIT_TO_BLOCKED_ACCOUNT: u64 = 92;
+
+ + + + + +Module account store cannot be manipulated. + + +
const ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE: u64 = 91;
+
+ + + Decimals is over the maximum of 32 @@ -584,6 +690,36 @@ Decimals is over the maximum of 32 + + +Provided deposit function type doesn't meet the signature requirement. + + +
const EDEPOSIT_FUNCTION_SIGNATURE_MISMATCH: u64 = 26;
+
+ + + + + +Provided derived_balance function type doesn't meet the signature requirement. + + +
const EDERIVED_BALANCE_FUNCTION_SIGNATURE_MISMATCH: u64 = 27;
+
+ + + + + +Provided derived_supply function type doesn't meet the signature requirement. + + +
const EDERIVED_SUPPLY_FUNCTION_SIGNATURE_MISMATCH: u64 = 33;
+
+ + + Fungible asset and store do not match. @@ -604,6 +740,26 @@ Fungible asset do not match when merging. + + +Fungible metadata does not exist on this account. + + +
const EFUNGIBLE_METADATA_EXISTENCE: u64 = 30;
+
+ + + + + +Flag for the existence of fungible store. + + +
const EFUNGIBLE_STORE_EXISTENCE: u64 = 23;
+
+ + + Insufficient balance to withdraw or transfer. @@ -614,6 +770,17 @@ Insufficient balance to withdraw or transfer. + + +Invalid withdraw/deposit on dispatchable token. The specified token has a dispatchable function hook. +Need to invoke dispatchable_fungible_asset::withdraw/deposit to perform transfer. + + +
const EINVALID_DISPATCHABLE_OPERATIONS: u64 = 28;
+
+ + + The fungible asset's supply has exceeded maximum. @@ -644,6 +811,16 @@ Name of the fungible asset metadata is too long + + +Account is not the owner of metadata object. + + +
const ENOT_METADATA_OWNER: u64 = 24;
+
+ + + Account is not the store's owner. @@ -734,6 +911,16 @@ URI for the icon of the fungible asset metadata is too long + + +Provided withdraw function type doesn't meet the signature requirement. + + +
const EWITHDRAW_FUNCTION_SIGNATURE_MISMATCH: u64 = 25;
+
+ + + @@ -788,8 +975,7 @@ maximum_supply defines the behavior of maximum supply when monitoring: -
-Implementation +##### Implementation
public fun add_fungibility(
@@ -799,34 +985,47 @@ maximum_supply defines the behavior of maximum supply when monitoring:
     symbol: String,
     decimals: u8,
     icon_uri: String,
-    project_uri: String,
+    project_uri: String
 ): Object<Metadata> {
-    assert!(!object::can_generate_delete_ref(constructor_ref), error::invalid_argument(EOBJECT_IS_DELETABLE));
+    assert!(
+        !object::can_generate_delete_ref(constructor_ref),
+        error::invalid_argument(EOBJECT_IS_DELETABLE)
+    );
     let metadata_object_signer = &object::generate_signer(constructor_ref);
 
     // metadata validations
-    assert!(string::length(&name) <= MAX_NAME_LENGTH, error::out_of_range(ENAME_TOO_LONG));
-    assert!(string::length(&symbol) <= MAX_SYMBOL_LENGTH, error::out_of_range(ESYMBOL_TOO_LONG));
-    assert!(decimals <= MAX_DECIMALS, error::out_of_range(EDECIMALS_TOO_LARGE));
-    assert!(string::length(&icon_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
-    assert!(string::length(&project_uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
+    assert!(
+        string::length(&name) <= MAX_NAME_LENGTH,
+        error::out_of_range(ENAME_TOO_LONG)
+    );
+    assert!(
+        string::length(&symbol) <= MAX_SYMBOL_LENGTH,
+        error::out_of_range(ESYMBOL_TOO_LONG)
+    );
+    assert!(
+        decimals <= MAX_DECIMALS,
+        error::out_of_range(EDECIMALS_TOO_LARGE)
+    );
+    assert!(
+        string::length(&icon_uri) <= MAX_URI_LENGTH,
+        error::out_of_range(EURI_TOO_LONG)
+    );
+    assert!(
+        string::length(&project_uri) <= MAX_URI_LENGTH,
+        error::out_of_range(EURI_TOO_LONG)
+    );
 
     // store metadata
-    move_to(metadata_object_signer,
-        Metadata {
-            name,
-            symbol,
-            decimals,
-            icon_uri,
-            project_uri,
-        }
+    move_to(
+        metadata_object_signer,
+        Metadata { name, symbol, decimals, icon_uri, project_uri }
     );
 
     // store supply
-    move_to(metadata_object_signer, Supply {
-        current: 0,
-        maximum: maximum_supply
-    });
+    move_to(
+        metadata_object_signer,
+        Supply { current: 0, maximum: maximum_supply }
+    );
 
     // return metadata object
     object::object_from_constructor_ref<Metadata>(constructor_ref)
@@ -835,7 +1034,169 @@ maximum_supply defines the behavior of maximum supply when monitoring:
 
 
 
-
+ + +## Function `register_dispatch_functions` + +Create a fungible asset store whose transfer rule would be overloaded by the provided function. + + +
public(friend) fun register_dispatch_functions(constructor_ref: &object::ConstructorRef, withdraw_function: option::Option<function_info::FunctionInfo>, deposit_function: option::Option<function_info::FunctionInfo>, derived_balance_function: option::Option<function_info::FunctionInfo>)
+
+ + + +##### Implementation + + +
public(friend) fun register_dispatch_functions(
+    constructor_ref: &ConstructorRef,
+    withdraw_function: Option<FunctionInfo>,
+    deposit_function: Option<FunctionInfo>,
+    derived_balance_function: Option<FunctionInfo>
+) {
+    // Verify that caller type matches callee type so wrongly typed function cannot be registered.
+    option::for_each_ref(
+        &withdraw_function,
+        |withdraw_function| {
+            let dispatcher_withdraw_function_info =
+                function_info::new_function_info_from_address(
+                    @minitia_std,
+                    string::utf8(b"dispatchable_fungible_asset"),
+                    string::utf8(b"dispatchable_withdraw")
+                );
+
+            assert!(
+                function_info::check_dispatch_type_compatibility(
+                    &dispatcher_withdraw_function_info,
+                    withdraw_function
+                ),
+                error::invalid_argument(EWITHDRAW_FUNCTION_SIGNATURE_MISMATCH)
+            );
+        }
+    );
+
+    option::for_each_ref(
+        &deposit_function,
+        |deposit_function| {
+            let dispatcher_deposit_function_info =
+                function_info::new_function_info_from_address(
+                    @minitia_std,
+                    string::utf8(b"dispatchable_fungible_asset"),
+                    string::utf8(b"dispatchable_deposit")
+                );
+            // Verify that caller type matches callee type so wrongly typed function cannot be registered.
+            assert!(
+                function_info::check_dispatch_type_compatibility(
+                    &dispatcher_deposit_function_info,
+                    deposit_function
+                ),
+                error::invalid_argument(EDEPOSIT_FUNCTION_SIGNATURE_MISMATCH)
+            );
+        }
+    );
+
+    option::for_each_ref(
+        &derived_balance_function,
+        |balance_function| {
+            let dispatcher_derived_balance_function_info =
+                function_info::new_function_info_from_address(
+                    @minitia_std,
+                    string::utf8(b"dispatchable_fungible_asset"),
+                    string::utf8(b"dispatchable_derived_balance")
+                );
+            // Verify that caller type matches callee type so wrongly typed function cannot be registered.
+            assert!(
+                function_info::check_dispatch_type_compatibility(
+                    &dispatcher_derived_balance_function_info,
+                    balance_function
+                ),
+                error::invalid_argument(
+                    EDERIVED_BALANCE_FUNCTION_SIGNATURE_MISMATCH
+                )
+            );
+        }
+    );
+    register_dispatch_function_sanity_check(constructor_ref);
+    assert!(
+        !exists<DispatchFunctionStore>(
+            object::address_from_constructor_ref(constructor_ref)
+        ),
+        error::already_exists(EALREADY_REGISTERED)
+    );
+
+    let store_obj = &object::generate_signer(constructor_ref);
+
+    // Store the overload function hook.
+    move_to<DispatchFunctionStore>(
+        store_obj,
+        DispatchFunctionStore {
+            withdraw_function,
+            deposit_function,
+            derived_balance_function
+        }
+    );
+}
+
+ + + + + +## Function `register_derive_supply_dispatch_function` + +Define the derived supply dispatch with the provided function. + + +
public(friend) fun register_derive_supply_dispatch_function(constructor_ref: &object::ConstructorRef, dispatch_function: option::Option<function_info::FunctionInfo>)
+
+ + + +##### Implementation + + +
public(friend) fun register_derive_supply_dispatch_function(
+    constructor_ref: &ConstructorRef, dispatch_function: Option<FunctionInfo>
+) {
+    // Verify that caller type matches callee type so wrongly typed function cannot be registered.
+    option::for_each_ref(
+        &dispatch_function,
+        |supply_function| {
+            let function_info =
+                function_info::new_function_info_from_address(
+                    @minitia_std,
+                    string::utf8(b"dispatchable_fungible_asset"),
+                    string::utf8(b"dispatchable_derived_supply")
+                );
+            // Verify that caller type matches callee type so wrongly typed function cannot be registered.
+            assert!(
+                function_info::check_dispatch_type_compatibility(
+                    &function_info,
+                    supply_function
+                ),
+                error::invalid_argument(
+                    EDERIVED_SUPPLY_FUNCTION_SIGNATURE_MISMATCH
+                )
+            );
+        }
+    );
+    register_dispatch_function_sanity_check(constructor_ref);
+    assert!(
+        !exists<DeriveSupply>(
+            object::address_from_constructor_ref(constructor_ref)
+        ),
+        error::already_exists(EALREADY_REGISTERED)
+    );
+
+    let store_obj = &object::generate_signer(constructor_ref);
+
+    // Store the overload function hook.
+    move_to<DeriveSupply>(store_obj, DeriveSupply { dispatch_function });
+}
+
+ + @@ -850,8 +1211,7 @@ This can only be called at object creation time as constructor_ref is only avail -
-Implementation +##### Implementation
public fun generate_mint_ref(constructor_ref: &ConstructorRef): MintRef {
@@ -862,8 +1222,6 @@ This can only be called at object creation time as constructor_ref is only avail
 
 
 
-
- ## Function `generate_burn_ref` @@ -877,8 +1235,7 @@ This can only be called at object creation time as constructor_ref is only avail -
-Implementation +##### Implementation
public fun generate_burn_ref(constructor_ref: &ConstructorRef): BurnRef {
@@ -889,8 +1246,6 @@ This can only be called at object creation time as constructor_ref is only avail
 
 
 
-
- ## Function `generate_transfer_ref` @@ -905,8 +1260,7 @@ This can only be called at object creation time as constructor_ref is only avail -
-Implementation +##### Implementation
public fun generate_transfer_ref(constructor_ref: &ConstructorRef): TransferRef {
@@ -917,7 +1271,32 @@ This can only be called at object creation time as constructor_ref is only avail
 
 
 
-
+ + +## Function `generate_mutate_metadata_ref` + +Creates a mutate metadata ref that can be used to change the metadata information of fungible assets from the +given fungible object's constructor ref. +This can only be called at object creation time as constructor_ref is only available then. + + +
public fun generate_mutate_metadata_ref(constructor_ref: &object::ConstructorRef): fungible_asset::MutateMetadataRef
+
+ + + +##### Implementation + + +
public fun generate_mutate_metadata_ref(
+    constructor_ref: &ConstructorRef
+): MutateMetadataRef {
+    let metadata = object::object_from_constructor_ref<Metadata>(constructor_ref);
+    MutateMetadataRef { metadata }
+}
+
+ + @@ -932,8 +1311,7 @@ Retrun true if given address has Metadata else return false -
-Implementation +##### Implementation
public fun is_fungible_asset(metadata_addr: address): bool {
@@ -943,8 +1321,6 @@ Retrun true if given address has Metadata else return false
 
 
 
-
- ## Function `supply` @@ -958,12 +1334,11 @@ Get the current supply from the metadata object. -
-Implementation +##### Implementation
public fun supply<T: key>(metadata: Object<T>): Option<u128> acquires Supply {
-    let metadata_address = object::object_address(metadata);
+    let metadata_address = object::object_address(&metadata);
     if (exists<Supply>(metadata_address)) {
         let supply = borrow_global<Supply>(metadata_address);
         option::some(supply.current)
@@ -975,8 +1350,6 @@ Get the current supply from the metadata object.
 
 
 
-
- ## Function `maximum` @@ -990,12 +1363,11 @@ Get the maximum supply from the metadata object. -
-Implementation +##### Implementation
public fun maximum<T: key>(metadata: Object<T>): Option<u128> acquires Supply {
-    let metadata_address = object::object_address(metadata);
+    let metadata_address = object::object_address(&metadata);
     if (exists<Supply>(metadata_address)) {
         let supply = borrow_global<Supply>(metadata_address);
         supply.maximum
@@ -1007,8 +1379,6 @@ Get the maximum supply from the metadata object.
 
 
 
-
- ## Function `name` @@ -1022,19 +1392,16 @@ Get the name of the fungible asset from the metadata object. -
-Implementation +##### Implementation
public fun name<T: key>(metadata: Object<T>): String acquires Metadata {
-    borrow_fungible_metadata(metadata).name
+    borrow_fungible_metadata(&metadata).name
 }
 
-
- ## Function `symbol` @@ -1048,48 +1415,111 @@ Get the symbol of the fungible asset from the metadata object. -
-Implementation +##### Implementation
public fun symbol<T: key>(metadata: Object<T>): String acquires Metadata {
-    borrow_fungible_metadata(metadata).symbol
+    borrow_fungible_metadata(&metadata).symbol
 }
 
-
+ - - -## Function `decimals` +## Function `icon_uri` -Get the decimals from the metadata object. +Get the icon uri from the metadata object.
#[view]
-public fun decimals<T: key>(metadata: object::Object<T>): u8
+public fun icon_uri<T: key>(metadata: object::Object<T>): string::String
 
-
-Implementation +##### Implementation -
public fun decimals<T: key>(metadata: Object<T>): u8 acquires Metadata {
-    borrow_fungible_metadata(metadata).decimals
+
public fun icon_uri<T: key>(metadata: Object<T>): String acquires Metadata {
+    borrow_fungible_metadata(&metadata).icon_uri
 }
 
-
+ - +## Function `project_uri` -## Function `store_exists` +Get the project uri from the metadata object. + + +
#[view]
+public fun project_uri<T: key>(metadata: object::Object<T>): string::String
+
+ + + +##### Implementation + + +
public fun project_uri<T: key>(metadata: Object<T>): String acquires Metadata {
+    borrow_fungible_metadata(&metadata).project_uri
+}
+
+ + + + + +## Function `metadata` + +Get the metadata struct from the metadata object. + + +
#[view]
+public fun metadata<T: key>(metadata: object::Object<T>): fungible_asset::Metadata
+
+ + + +##### Implementation + + +
public fun metadata<T: key>(metadata: Object<T>): Metadata acquires Metadata {
+    *borrow_fungible_metadata(&metadata)
+}
+
+ + + + + +## Function `decimals` + +Get the decimals from the metadata object. + + +
#[view]
+public fun decimals<T: key>(metadata: object::Object<T>): u8
+
+ + + +##### Implementation + + +
public fun decimals<T: key>(metadata: Object<T>): u8 acquires Metadata {
+    borrow_fungible_metadata(&metadata).decimals
+}
+
+ + + + + +## Function `store_exists` Return whether the provided address has a store initialized. @@ -1100,8 +1530,7 @@ Return whether the provided address has a store initialized. -
-Implementation +##### Implementation
public fun store_exists(store: address): bool {
@@ -1111,8 +1540,6 @@ Return whether the provided address has a store initialized.
 
 
 
-
- ## Function `metadata_from_asset` @@ -1125,8 +1552,7 @@ Return the underlying metadata object -
-Implementation +##### Implementation
public fun metadata_from_asset(fa: &FungibleAsset): Object<Metadata> {
@@ -1136,8 +1562,6 @@ Return the underlying metadata object
 
 
 
-
- ## Function `store_metadata` @@ -1151,19 +1575,16 @@ Return the underlying metadata object. -
-Implementation +##### Implementation
public fun store_metadata<T: key>(store: Object<T>): Object<Metadata> acquires FungibleStore {
-    borrow_store_resource(store).metadata
+    borrow_store_resource(&store).metadata
 }
 
-
- ## Function `amount` @@ -1176,8 +1597,7 @@ Return the amount of a given fungible asset. -
-Implementation +##### Implementation
public fun amount(fa: &FungibleAsset): u64 {
@@ -1187,8 +1607,6 @@ Return the amount of a given fungible asset.
 
 
 
-
- ## Function `balance` @@ -1202,23 +1620,18 @@ Get the balance of a given store. -
-Implementation +##### Implementation
public fun balance<T: key>(store: Object<T>): u64 acquires FungibleStore {
-    if (store_exists(object::object_address(store))) {
-        borrow_store_resource(store).balance
-    } else {
-        0
-    }
+    if (store_exists(object::object_address(&store))) {
+        borrow_store_resource(&store).balance
+    } else { 0 }
 }
 
-
- ## Function `is_frozen` @@ -1234,18 +1647,156 @@ If the store has not been created, we default to returning false so deposits can -
-Implementation +##### Implementation
public fun is_frozen<T: key>(store: Object<T>): bool acquires FungibleStore {
-    store_exists(object::object_address(store)) && borrow_store_resource(store).frozen
+    store_exists(object::object_address(&store))
+        && borrow_store_resource(&store).frozen
+}
+
+ + + + + +## Function `is_store_dispatchable` + +Return whether a fungible asset type is dispatchable. + + +
#[view]
+public fun is_store_dispatchable<T: key>(store: object::Object<T>): bool
+
+ + + +##### Implementation + + +
public fun is_store_dispatchable<T: key>(store: Object<T>): bool acquires FungibleStore {
+    let fa_store = borrow_store_resource(&store);
+    let metadata_addr = object::object_address(&fa_store.metadata);
+    exists<DispatchFunctionStore>(metadata_addr)
+}
+
+ + + + + +## Function `deposit_dispatch_function` + + + +
public fun deposit_dispatch_function<T: key>(store: object::Object<T>): option::Option<function_info::FunctionInfo>
+
+ + + +##### Implementation + + +
public fun deposit_dispatch_function<T: key>(
+    store: Object<T>
+): Option<FunctionInfo> acquires FungibleStore, DispatchFunctionStore {
+    let fa_store = borrow_store_resource(&store);
+    let metadata_addr = object::object_address(&fa_store.metadata);
+    if (exists<DispatchFunctionStore>(metadata_addr)) {
+        borrow_global<DispatchFunctionStore>(metadata_addr).deposit_function
+    } else {
+        option::none()
+    }
+}
+
+ + + + + +## Function `withdraw_dispatch_function` + + + +
public fun withdraw_dispatch_function<T: key>(store: object::Object<T>): option::Option<function_info::FunctionInfo>
+
+ + + +##### Implementation + + +
public fun withdraw_dispatch_function<T: key>(
+    store: Object<T>
+): Option<FunctionInfo> acquires FungibleStore, DispatchFunctionStore {
+    let fa_store = borrow_store_resource(&store);
+    let metadata_addr = object::object_address(&fa_store.metadata);
+    if (exists<DispatchFunctionStore>(metadata_addr)) {
+        borrow_global<DispatchFunctionStore>(metadata_addr).withdraw_function
+    } else {
+        option::none()
+    }
 }
 
-
+ + +## Function `derived_balance_dispatch_function` + + + +
public(friend) fun derived_balance_dispatch_function<T: key>(store: object::Object<T>): option::Option<function_info::FunctionInfo>
+
+ + + +##### Implementation + + +
public(friend) fun derived_balance_dispatch_function<T: key>(
+    store: Object<T>
+): Option<FunctionInfo> acquires FungibleStore, DispatchFunctionStore {
+    let fa_store = borrow_store_resource(&store);
+    let metadata_addr = object::object_address(&fa_store.metadata);
+    if (exists<DispatchFunctionStore>(metadata_addr)) {
+        borrow_global<DispatchFunctionStore>(metadata_addr).derived_balance_function
+    } else {
+        option::none()
+    }
+}
+
+ + + + + +## Function `derived_supply_dispatch_function` + + + +
public(friend) fun derived_supply_dispatch_function<T: key>(metadata: object::Object<T>): option::Option<function_info::FunctionInfo>
+
+ + + +##### Implementation + + +
public(friend) fun derived_supply_dispatch_function<T: key>(
+    metadata: Object<T>
+): Option<FunctionInfo> acquires DeriveSupply {
+    let metadata_addr = object::object_address(&metadata);
+    if (exists<DeriveSupply>(metadata_addr)) {
+        borrow_global<DeriveSupply>(metadata_addr).dispatch_function
+    } else {
+        option::none()
+    }
+}
+
+ + @@ -1258,8 +1809,7 @@ If the store has not been created, we default to returning false so deposits can -
-Implementation +##### Implementation
public fun asset_metadata(fa: &FungibleAsset): Object<Metadata> {
@@ -1269,8 +1819,6 @@ If the store has not been created, we default to returning false so deposits can
 
 
 
-
- ## Function `mint_ref_metadata` @@ -1283,8 +1831,7 @@ Get the underlying metadata object from the mint_ref_metadata(ref: &MintRef): Object<Metadata> { @@ -1294,8 +1841,6 @@ Get the underlying metadata object from the ## Function `transfer_ref_metadata` @@ -1308,8 +1853,7 @@ Get the underlying metadata object from the transfer_ref_metadata(ref: &TransferRef): Object<Metadata> { @@ -1319,8 +1863,6 @@ Get the underlying metadata object from the ## Function `burn_ref_metadata` @@ -1333,8 +1875,7 @@ Get the underlying metadata object from the burn_ref_metadata(ref: &BurnRef): Object<Metadata> { @@ -1344,7 +1885,27 @@ Get the underlying metadata object from the + +## Function `object_from_metadata_ref` + +Get the underlying metadata object from the MutateMetadataRef. + + +
public fun object_from_metadata_ref(ref: &fungible_asset::MutateMetadataRef): object::Object<fungible_asset::Metadata>
+
+ + + +##### Implementation + + +
public fun object_from_metadata_ref(ref: &MutateMetadataRef): Object<Metadata> {
+    ref.metadata
+}
+
+ + @@ -1359,16 +1920,15 @@ Note: it does not move the underlying object. -
-Implementation +##### Implementation
public entry fun transfer<T: key>(
     sender: &signer,
     from: Object<T>,
     to: Object<T>,
-    amount: u64,
-) acquires FungibleStore {
+    amount: u64
+) acquires FungibleStore, DispatchFunctionStore {
     let fa = withdraw(sender, from, amount);
     deposit(to, fa);
 }
@@ -1376,8 +1936,6 @@ Note: it does not move the underlying object.
 
 
 
-
- ## Function `create_store` @@ -1391,20 +1949,17 @@ Applications can use this to create multiple stores for isolating fungible asset -
-Implementation +##### Implementation
public fun create_store<T: key>(
-    constructor_ref: &ConstructorRef,
-    metadata: Object<T>,
+    constructor_ref: &ConstructorRef, metadata: Object<T>
 ): Object<FungibleStore> {
     let store_obj = &object::generate_signer(constructor_ref);
-    move_to(store_obj, FungibleStore {
-        metadata: object::convert(metadata),
-        balance: 0,
-        frozen: false,
-    });
+    move_to(
+        store_obj,
+        FungibleStore { metadata: object::convert(metadata), balance: 0, frozen: false }
+    );
 
     object::object_from_constructor_ref<FungibleStore>(constructor_ref)
 }
@@ -1412,8 +1967,6 @@ Applications can use this to create multiple stores for isolating fungible asset
 
 
 
-
- ## Function `create_store_with_extend_ref` @@ -1427,20 +1980,17 @@ Applications can use this to create multiple stores for isolating fungible asset -
-Implementation +##### Implementation
public fun create_store_with_extend_ref<T: key>(
-    extend_ref: &ExtendRef,
-    metadata: Object<T>,
+    extend_ref: &ExtendRef, metadata: Object<T>
 ): Object<FungibleStore> {
     let store_obj = &object::generate_signer_for_extending(extend_ref);
-    move_to(store_obj, FungibleStore {
-        metadata: object::convert(metadata),
-        balance: 0,
-        frozen: false,
-    });
+    move_to(
+        store_obj,
+        FungibleStore { metadata: object::convert(metadata), balance: 0, frozen: false }
+    );
 
     let obj_addr = object::address_from_extend_ref(extend_ref);
     object::address_to_object<FungibleStore>(obj_addr)
@@ -1449,8 +1999,6 @@ Applications can use this to create multiple stores for isolating fungible asset
 
 
 
-
- ## Function `remove_store` @@ -1463,22 +2011,92 @@ Used to delete a store. Requires the store to be completely empty prior to remo -
-Implementation +##### Implementation
public fun remove_store(delete_ref: &DeleteRef) acquires FungibleStore {
     let store = object::object_from_delete_ref<FungibleStore>(delete_ref);
-    let addr = object::object_address(store);
-    let FungibleStore { metadata: _, balance, frozen: _ }
-        = move_from<FungibleStore>(addr);
-    assert!(balance == 0, error::permission_denied(EBALANCE_IS_NOT_ZERO));
+    let addr = object::object_address(&store);
+    let FungibleStore { metadata: _, balance, frozen: _ } =
+        move_from<FungibleStore>(addr);
+    assert!(
+        balance == 0,
+        error::permission_denied(EBALANCE_IS_NOT_ZERO)
+    );
+}
+
+ + + + + +## Function `withdraw_sanity_check` + +Check the permission for withdraw operation. + + +
public(friend) fun withdraw_sanity_check<T: key>(owner: &signer, store: object::Object<T>, abort_on_dispatch: bool)
+
+ + + +##### Implementation + + +
public(friend) fun withdraw_sanity_check<T: key>(
+    owner: &signer, store: Object<T>, abort_on_dispatch: bool
+) acquires FungibleStore, DispatchFunctionStore {
+    assert!(
+        object::owns(store, signer::address_of(owner)),
+        error::permission_denied(ENOT_STORE_OWNER)
+    );
+    let fa_store = borrow_store_resource(&store);
+    assert!(
+        !abort_on_dispatch || !has_withdraw_dispatch_function(fa_store.metadata),
+        error::invalid_argument(EINVALID_DISPATCHABLE_OPERATIONS)
+    );
+    assert!(!fa_store.frozen, error::permission_denied(ESTORE_IS_FROZEN));
 }
 
-
+ + +## Function `deposit_sanity_check` + +Deposit amount of the fungible asset to store. + + +
public fun deposit_sanity_check<T: key>(store: object::Object<T>, abort_on_dispatch: bool)
+
+ + + +##### Implementation + + +
public fun deposit_sanity_check<T: key>(
+    store: Object<T>, abort_on_dispatch: bool
+) acquires FungibleStore, DispatchFunctionStore {
+    let fa_store = borrow_store_resource(&store);
+    assert!(
+        !abort_on_dispatch || !has_deposit_dispatch_function(fa_store.metadata),
+        error::invalid_argument(EINVALID_DISPATCHABLE_OPERATIONS)
+    );
+
+    assert!(!fa_store.frozen, error::permission_denied(ESTORE_IS_FROZEN));
+
+    // cannot deposit to blocked account
+    let store_addr = object::object_address(&store);
+    assert!(
+        !is_blocked_store_addr(store_addr),
+        error::invalid_argument(ECANNOT_DEPOSIT_TO_BLOCKED_ACCOUNT)
+    );
+}
+
+ + @@ -1492,25 +2110,19 @@ Withdraw amount of the fungible asset from store by th -
-Implementation +##### Implementation
public fun withdraw<T: key>(
-    owner: &signer,
-    store: Object<T>,
-    amount: u64,
-): FungibleAsset acquires FungibleStore {
-    assert!(object::owns(store, signer::address_of(owner)), error::permission_denied(ENOT_STORE_OWNER));
-    assert!(!is_frozen(store), error::invalid_argument(ESTORE_IS_FROZEN));
-    withdraw_internal(object::object_address(store), amount)
+    owner: &signer, store: Object<T>, amount: u64
+): FungibleAsset acquires FungibleStore, DispatchFunctionStore {
+    withdraw_sanity_check(owner, store, true);
+    withdraw_internal(object::object_address(&store), amount)
 }
 
-
- ## Function `deposit` @@ -1523,20 +2135,19 @@ Deposit amount of the fungible asset to store. -
-Implementation +##### Implementation -
public fun deposit<T: key>(store: Object<T>, fa: FungibleAsset) acquires FungibleStore {
-    assert!(!is_frozen(store), error::invalid_argument(ESTORE_IS_FROZEN));
-    deposit_internal(store, fa);
+
public fun deposit<T: key>(
+    store: Object<T>, fa: FungibleAsset
+) acquires FungibleStore, DispatchFunctionStore {
+    deposit_sanity_check(store, true);
+    deposit_internal(object::object_address(&store), fa);
 }
 
-
- ## Function `mint` @@ -1549,8 +2160,7 @@ Mint the specified amount of the fungible asset. -
-Implementation +##### Implementation
public fun mint(ref: &MintRef, amount: u64): FungibleAsset acquires Supply {
@@ -1560,20 +2170,15 @@ Mint the specified amount of the fungible asset.
     increase_supply(metadata, amount);
 
     // emit event
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
     event::emit(MintEvent { metadata_addr, amount });
 
-    FungibleAsset {
-        metadata,
-        amount
-    }
+    FungibleAsset { metadata, amount }
 }
 
-
- ## Function `mint_to` @@ -1586,20 +2191,19 @@ Mint the specified amount of the fungible asset to a destination st -
-Implementation +##### Implementation -
public fun mint_to<T: key>(ref: &MintRef, store: Object<T>, amount: u64)
-acquires FungibleStore, Supply {
-    deposit(store, mint(ref, amount));
+
public fun mint_to<T: key>(
+    ref: &MintRef, store: Object<T>, amount: u64
+) acquires FungibleStore, Supply, DispatchFunctionStore {
+    deposit_sanity_check(store, false);
+    deposit_internal(object::object_address(&store), mint(ref, amount));
 }
 
-
- ## Function `set_frozen_flag` @@ -1612,22 +2216,26 @@ Enable/disable a store's ability to do direct transfers of the fungible asset. -
-Implementation +##### Implementation
public fun set_frozen_flag<T: key>(
-    ref: &TransferRef,
-    store: Object<T>,
-    frozen: bool,
+    ref: &TransferRef, store: Object<T>, frozen: bool
 ) acquires FungibleStore {
     assert!(
         ref.metadata == store_metadata(store),
-        error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH),
+        error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH)
+    );
+
+    let metadata_addr = object::object_address(&ref.metadata);
+    let store_addr = object::object_address(&store);
+
+    // cannot freeze module account store
+    assert!(
+        !is_module_account_store_addr(store_addr),
+        error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE)
     );
 
-    let metadata_addr = object::object_address(ref.metadata);
-    let store_addr = object::object_address(store);
     borrow_global_mut<FungibleStore>(store_addr).frozen = frozen;
 
     // emit event
@@ -1637,8 +2245,6 @@ Enable/disable a store's ability to do direct transfers of the fungible asset.
 
 
 
-
- ## Function `burn` @@ -1651,28 +2257,25 @@ Burns a fungible asset -
-Implementation +##### Implementation
public fun burn(ref: &BurnRef, fa: FungibleAsset) acquires Supply {
-    let FungibleAsset {
-        metadata,
-        amount,
-    } = fa;
-    assert!(ref.metadata == metadata, error::invalid_argument(EBURN_REF_AND_FUNGIBLE_ASSET_MISMATCH));
+    let FungibleAsset { metadata, amount } = fa;
+    assert!(
+        ref.metadata == metadata,
+        error::invalid_argument(EBURN_REF_AND_FUNGIBLE_ASSET_MISMATCH)
+    );
     decrease_supply(metadata, amount);
 
     // emit event
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
     event::emit(BurnEvent { metadata_addr, amount });
 }
 
-
- ## Function `burn_from` @@ -1685,27 +2288,32 @@ Burn the amount of the fungible asset from the given store. -
-Implementation +##### Implementation
public fun burn_from<T: key>(
-    ref: &BurnRef,
-    store: Object<T>,
-    amount: u64
+    ref: &BurnRef, store: Object<T>, amount: u64
 ) acquires FungibleStore, Supply {
     let metadata = ref.metadata;
-    assert!(metadata == store_metadata(store), error::invalid_argument(EBURN_REF_AND_STORE_MISMATCH));
+    assert!(
+        metadata == store_metadata(store),
+        error::invalid_argument(EBURN_REF_AND_STORE_MISMATCH)
+    );
+
+    let store_addr = object::object_address(&store);
+
+    // cannot burn module account funds
+    assert!(
+        !is_module_account_store_addr(store_addr),
+        error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE)
+    );
 
-    let store_addr = object::object_address(store);
     burn(ref, withdraw_internal(store_addr, amount));
 }
 
-
- ## Function `withdraw_with_ref` @@ -1718,28 +2326,30 @@ Withdraw amount of the fungible asset from the store i -
-Implementation +##### Implementation
public fun withdraw_with_ref<T: key>(
-    ref: &TransferRef,
-    store: Object<T>,
-    amount: u64
+    ref: &TransferRef, store: Object<T>, amount: u64
 ): FungibleAsset acquires FungibleStore {
     assert!(
         ref.metadata == store_metadata(store),
-        error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH),
+        error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH)
     );
 
-    withdraw_internal(object::object_address(store), amount)
+    // cannot withdraw module account funds
+    let store_addr = object::object_address(&store);
+    assert!(
+        !is_module_account_store_addr(store_addr),
+        error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE)
+    );
+
+    withdraw_internal(object::object_address(&store), amount)
 }
 
-
- ## Function `deposit_with_ref` @@ -1752,27 +2362,30 @@ Deposit the fungible asset into the store ignoring frozen -Implementation +##### Implementation
public fun deposit_with_ref<T: key>(
-    ref: &TransferRef,
-    store: Object<T>,
-    fa: FungibleAsset
+    ref: &TransferRef, store: Object<T>, fa: FungibleAsset
 ) acquires FungibleStore {
     assert!(
         ref.metadata == fa.metadata,
         error::invalid_argument(ETRANSFER_REF_AND_FUNGIBLE_ASSET_MISMATCH)
     );
-    deposit_internal(store, fa);
+
+    // cannot deposit to blocked account
+    let store_addr = object::object_address(&store);
+    assert!(
+        !is_blocked_store_addr(store_addr),
+        error::invalid_argument(ECANNOT_DEPOSIT_TO_BLOCKED_ACCOUNT)
+    );
+
+    deposit_internal(object::object_address(&store), fa);
 }
 
- - ## Function `transfer_with_ref` @@ -1785,15 +2398,14 @@ Transfer amount of the fungible asset with transfer_with_ref<T: key>( transfer_ref: &TransferRef, from: Object<T>, to: Object<T>, - amount: u64, + amount: u64 ) acquires FungibleStore { let fa = withdraw_with_ref(transfer_ref, from, amount); deposit_with_ref(transfer_ref, to, fa); @@ -1802,341 +2414,292 @@ Transfer amount of the fungible asset with - +## Function `mutate_metadata` -## Function `zero` - -Create a fungible asset with zero amount. -This can be useful when starting a series of computations where the initial value is 0. +Mutate specified fields of the fungible asset's Metadata. -
public fun zero<T: key>(metadata: object::Object<T>): fungible_asset::FungibleAsset
+
public fun mutate_metadata(metadata_ref: &fungible_asset::MutateMetadataRef, name: option::Option<string::String>, symbol: option::Option<string::String>, decimals: option::Option<u8>, icon_uri: option::Option<string::String>, project_uri: option::Option<string::String>)
 
-
-Implementation +##### Implementation -
public fun zero<T: key>(metadata: Object<T>): FungibleAsset {
-    FungibleAsset {
-        metadata: object::convert(metadata),
-        amount: 0,
-    }
+
public fun mutate_metadata(
+    metadata_ref: &MutateMetadataRef,
+    name: Option<String>,
+    symbol: Option<String>,
+    decimals: Option<u8>,
+    icon_uri: Option<String>,
+    project_uri: Option<String>
+) acquires Metadata {
+    let metadata_address = object::object_address(&metadata_ref.metadata);
+    let mutable_metadata = borrow_global_mut<Metadata>(metadata_address);
+
+    if (option::is_some(&name)) {
+        mutable_metadata.name = option::extract(&mut name);
+    };
+    if (option::is_some(&symbol)) {
+        mutable_metadata.symbol = option::extract(&mut symbol);
+    };
+    if (option::is_some(&decimals)) {
+        mutable_metadata.decimals = option::extract(&mut decimals);
+    };
+    if (option::is_some(&icon_uri)) {
+        mutable_metadata.icon_uri = option::extract(&mut icon_uri);
+    };
+    if (option::is_some(&project_uri)) {
+        mutable_metadata.project_uri = option::extract(&mut project_uri);
+    };
 }
 
-
+ - +## Function `sudo_transfer` -## Function `extract` +Transfer an amount of fungible asset from from_store, which should be owned by sender, to receiver. +Note: it does not move the underlying object. -Extract a given amount from the given fungible asset and return a new one. +This function is only callable by the chain. -
public fun extract(fungible_asset: &mut fungible_asset::FungibleAsset, amount: u64): fungible_asset::FungibleAsset
+
public(friend) fun sudo_transfer<T: key>(sender: &signer, from: object::Object<T>, to: object::Object<T>, amount: u64)
 
-
-Implementation +##### Implementation -
public fun extract(fungible_asset: &mut FungibleAsset, amount: u64): FungibleAsset {
-    assert!(fungible_asset.amount >= amount, error::invalid_argument(EINSUFFICIENT_BALANCE));
-    fungible_asset.amount = fungible_asset.amount - amount;
-    FungibleAsset {
-        metadata: fungible_asset.metadata,
-        amount,
-    }
+
public(friend) fun sudo_transfer<T: key>(
+    sender: &signer,
+    from: Object<T>,
+    to: Object<T>,
+    amount: u64
+) acquires FungibleStore, DispatchFunctionStore {
+    let fa = withdraw(sender, from, amount);
+    sudo_deposit(to, fa);
 }
 
-
+ - +## Function `sudo_deposit` -## Function `merge` +Deposit amount of the fungible asset to store. -"Merges" the two given fungible assets. The fungible asset passed in as dst_fungible_asset will have a value -equal to the sum of the two (dst_fungible_asset and src_fungible_asset). +This function is only callable by the chain. -
public fun merge(dst_fungible_asset: &mut fungible_asset::FungibleAsset, src_fungible_asset: fungible_asset::FungibleAsset)
+
public(friend) fun sudo_deposit<T: key>(store: object::Object<T>, fa: fungible_asset::FungibleAsset)
 
-
-Implementation +##### Implementation -
public fun merge(dst_fungible_asset: &mut FungibleAsset, src_fungible_asset: FungibleAsset) {
-    let FungibleAsset { metadata, amount } = src_fungible_asset;
-    assert!(metadata == dst_fungible_asset.metadata, error::invalid_argument(EFUNGIBLE_ASSET_MISMATCH));
-    dst_fungible_asset.amount = dst_fungible_asset.amount + amount;
+
public(friend) fun sudo_deposit<T: key>(
+    store: Object<T>, fa: FungibleAsset
+) acquires FungibleStore {
+    assert!(
+        !is_frozen(store),
+        error::invalid_argument(ESTORE_IS_FROZEN)
+    );
+
+    deposit_internal(object::object_address(&store), fa);
 }
 
-
- - + -## Function `destroy_zero` +## Function `zero` -Destroy an empty fungible asset. +Create a fungible asset with zero amount. +This can be useful when starting a series of computations where the initial value is 0. -
public fun destroy_zero(fungible_asset: fungible_asset::FungibleAsset)
+
public fun zero<T: key>(metadata: object::Object<T>): fungible_asset::FungibleAsset
 
-
-Implementation +##### Implementation -
public fun destroy_zero(fungible_asset: FungibleAsset) {
-    let FungibleAsset { amount, metadata: _ } = fungible_asset;
-    assert!(amount == 0, error::invalid_argument(EAMOUNT_IS_NOT_ZERO));
+
public fun zero<T: key>(metadata: Object<T>): FungibleAsset {
+    FungibleAsset { metadata: object::convert(metadata), amount: 0 }
 }
 
-
- - + -## Function `deposit_internal` +## Function `extract` +Extract a given amount from the given fungible asset and return a new one. -
fun deposit_internal<T: key>(store: object::Object<T>, fa: fungible_asset::FungibleAsset)
+
public fun extract(fungible_asset: &mut fungible_asset::FungibleAsset, amount: u64): fungible_asset::FungibleAsset
 
-
-Implementation - - -
fun deposit_internal<T: key>(store: Object<T>, fa: FungibleAsset) acquires FungibleStore {
-    let FungibleAsset { metadata, amount } = fa;
-    if (amount == 0) return;
-
-    let store_metadata = store_metadata(store);
-    assert!(metadata == store_metadata, error::invalid_argument(EFUNGIBLE_ASSET_AND_STORE_MISMATCH));
-    let metadata_addr = object::object_address(store_metadata);
-    let store_addr = object::object_address(store);
-    let store = borrow_global_mut<FungibleStore>(store_addr);
-    store.balance = store.balance + amount;
+##### Implementation
 
 
-    // emit event
-    event::emit(DepositEvent { store_addr, metadata_addr, amount });
+
public fun extract(fungible_asset: &mut FungibleAsset, amount: u64): FungibleAsset {
+    assert!(
+        fungible_asset.amount >= amount,
+        error::invalid_argument(EINSUFFICIENT_BALANCE)
+    );
+    fungible_asset.amount = fungible_asset.amount - amount;
+    FungibleAsset { metadata: fungible_asset.metadata, amount }
 }
 
-
- - + -## Function `withdraw_internal` +## Function `merge` -Extract amount of the fungible asset from store. +"Merges" the two given fungible assets. The fungible asset passed in as dst_fungible_asset will have a value +equal to the sum of the two (dst_fungible_asset and src_fungible_asset). -
fun withdraw_internal(store_addr: address, amount: u64): fungible_asset::FungibleAsset
+
public fun merge(dst_fungible_asset: &mut fungible_asset::FungibleAsset, src_fungible_asset: fungible_asset::FungibleAsset)
 
-
-Implementation +##### Implementation -
fun withdraw_internal(
-    store_addr: address,
-    amount: u64,
-): FungibleAsset acquires FungibleStore {
-    let store = borrow_global_mut<FungibleStore>(store_addr);
-    let metadata = store.metadata;
-    if (amount == 0) return zero(metadata);
-
-    assert!(store.balance >= amount, error::invalid_argument(EINSUFFICIENT_BALANCE));
-    store.balance = store.balance - amount;
-
-    // emit event
-    let metadata_addr = object::object_address(metadata);
-    event::emit(WithdrawEvent { store_addr, metadata_addr, amount });
-
-    FungibleAsset { metadata, amount }
+
public fun merge(
+    dst_fungible_asset: &mut FungibleAsset, src_fungible_asset: FungibleAsset
+) {
+    let FungibleAsset { metadata, amount } = src_fungible_asset;
+    assert!(
+        metadata == dst_fungible_asset.metadata,
+        error::invalid_argument(EFUNGIBLE_ASSET_MISMATCH)
+    );
+    dst_fungible_asset.amount = dst_fungible_asset.amount + amount;
 }
 
-
- - + -## Function `increase_supply` +## Function `destroy_zero` -Increase the supply of a fungible asset by minting. +Destroy an empty fungible asset. -
fun increase_supply<T: key>(metadata: object::Object<T>, amount: u64)
+
public fun destroy_zero(fungible_asset: fungible_asset::FungibleAsset)
 
-
-Implementation - +##### Implementation -
fun increase_supply<T: key>(metadata: Object<T>, amount: u64) acquires Supply {
-    if (amount == 0) return;
 
-    let metadata_address = object::object_address(metadata);
-    assert!(exists<Supply>(metadata_address), error::not_found(ESUPPLY_NOT_FOUND));
-    let supply = borrow_global_mut<Supply>(metadata_address);
-    if (option::is_some(&supply.maximum)) {
-        let max = *option::borrow_mut(&mut supply.maximum);
-        assert!(
-            max - supply.current >= (amount as u128),
-            error::out_of_range(EMAX_SUPPLY_EXCEEDED)
-        )
-    };
-    supply.current = supply.current + (amount as u128);
+
public fun destroy_zero(fungible_asset: FungibleAsset) {
+    let FungibleAsset { amount, metadata: _ } = fungible_asset;
+    assert!(
+        amount == 0,
+        error::invalid_argument(EAMOUNT_IS_NOT_ZERO)
+    );
 }
 
-
- - + -## Function `decrease_supply` +## Function `deposit_internal` -Decrease the supply of a fungible asset by burning. -
fun decrease_supply<T: key>(metadata: object::Object<T>, amount: u64)
+
public(friend) fun deposit_internal(store_addr: address, fa: fungible_asset::FungibleAsset)
 
-
-Implementation - +##### Implementation -
fun decrease_supply<T: key>(metadata: Object<T>, amount: u64) acquires Supply {
-    if (amount == 0) return;
 
-    let metadata_address = object::object_address(metadata);
-    assert!(exists<Supply>(metadata_address), error::not_found(ESUPPLY_NOT_FOUND));
-    let supply = borrow_global_mut<Supply>(metadata_address);
+
public(friend) fun deposit_internal(
+    store_addr: address, fa: FungibleAsset
+) acquires FungibleStore {
+    let FungibleAsset { metadata, amount } = fa;
     assert!(
-        supply.current >= (amount as u128),
-        error::invalid_state(ESUPPLY_UNDERFLOW)
+        exists<FungibleStore>(store_addr),
+        error::not_found(EFUNGIBLE_STORE_EXISTENCE)
+    );
+    let store = borrow_global_mut<FungibleStore>(store_addr);
+    assert!(
+        metadata == store.metadata,
+        error::invalid_argument(EFUNGIBLE_ASSET_AND_STORE_MISMATCH)
     );
-    supply.current = supply.current - (amount as u128);
-}
-
- - - -
- - - -## Function `borrow_fungible_metadata` - - - -
fun borrow_fungible_metadata<T: key>(metadata: object::Object<T>): &fungible_asset::Metadata
-
- - -
-Implementation + if (amount == 0) return; + store.balance = store.balance + amount; -
inline fun borrow_fungible_metadata<T: key>(
-    metadata: Object<T>
-): &Metadata acquires Metadata {
-    let addr = object::object_address(metadata);
-    borrow_global<Metadata>(addr)
+    // emit event
+    let metadata_addr = object::object_address(&metadata);
+    event::emit(DepositEvent { store_addr, metadata_addr, amount });
 }
 
-
- - - -## Function `borrow_fungible_metadata_mut` - - - -
fun borrow_fungible_metadata_mut<T: key>(metadata: object::Object<T>): &mut fungible_asset::Metadata
-
- + +## Function `withdraw_internal` -
-Implementation +Extract amount of the fungible asset from store. -
inline fun borrow_fungible_metadata_mut<T: key>(
-    metadata: Object<T>
-): &mut Metadata acquires Metadata {
-    let addr = object::object_address(metadata);
-    borrow_global_mut<Metadata>(addr)
-}
+
public(friend) fun withdraw_internal(store_addr: address, amount: u64): fungible_asset::FungibleAsset
 
-
- - - -## Function `borrow_store_resource` - - - -
fun borrow_store_resource<T: key>(store: object::Object<T>): &fungible_asset::FungibleStore
-
+##### Implementation +
public(friend) fun withdraw_internal(
+    store_addr: address, amount: u64
+): FungibleAsset acquires FungibleStore {
+    let store = borrow_global_mut<FungibleStore>(store_addr);
+    let metadata = store.metadata;
+    if (amount == 0) return zero(metadata);
 
-
-Implementation + assert!( + store.balance >= amount, + error::invalid_argument(EINSUFFICIENT_BALANCE) + ); + store.balance = store.balance - amount; + // emit event + let metadata_addr = object::object_address(&metadata); + event::emit(WithdrawEvent { store_addr, metadata_addr, amount }); -
inline fun borrow_store_resource<T: key>(store: Object<T>): &FungibleStore acquires FungibleStore {
-    borrow_global<FungibleStore>(object::object_address(store))
+    FungibleAsset { metadata, amount }
 }
 
- - - -
diff --git a/minitia_stdlib/doc/hex.md b/minitia_stdlib/doc/hex.md index a598eef..348ce33 100644 --- a/minitia_stdlib/doc/hex.md +++ b/minitia_stdlib/doc/hex.md @@ -5,13 +5,55 @@ +- [Constants](#@Constants_0) - [Function `encode_to_string`](#0x1_hex_encode_to_string) +- [Function `encode_to_string_with_option`](#0x1_hex_encode_to_string_with_option) - [Function `decode_string`](#0x1_hex_decode_string) -- [Function `encode_to_char`](#0x1_hex_encode_to_char) -- [Function `decode_char`](#0x1_hex_decode_char) -
use 0x1::string;
+
use 0x1::error;
+use 0x1::string;
+
+ + + + + +## Constants + + + + + + +
const ENOT_HEXSTRING: u64 = 1;
+
+ + + + + + + +
const LOWERA: u8 = 97;
+
+ + + + + + + +
const UPPERA: u8 = 65;
+
+ + + + + + + +
const ZERO: u8 = 48;
 
@@ -27,15 +69,14 @@ -
-Implementation +##### Implementation
public fun encode_to_string(bz: &vector<u8>): String {
     let vec: vector<u8> = vector[];
     let len = vector::length(bz);
     let index = 0;
-    while(index < len) {
+    while (index < len) {
         let val = *vector::borrow(bz, index);
         let h = val / 0x10;
         let l = val % 0x10;
@@ -50,110 +91,88 @@
 
 
 
-
+ - - -## Function `decode_string` +## Function `encode_to_string_with_option` -
public fun decode_string(str: &string::String): vector<u8>
+
public fun encode_to_string_with_option(bz: &vector<u8>, is_upper: bool): string::String
 
-
-Implementation +##### Implementation -
public fun decode_string(str: &String): vector<u8> {
+
public fun encode_to_string_with_option(
+    bz: &vector<u8>, is_upper: bool
+): String {
     let vec: vector<u8> = vector[];
-
-    let bz = string::bytes(str);
     let len = vector::length(bz);
-    if (len == 0) {
-        return vec
-    };
-
-    let index = if (len % 2 == 1) {
-        let l = decode_char(*vector::borrow(bz, 0));
-        vector::push_back(&mut vec, l);
-
-        1
-    } else {
-        0
-    };
-
-    while(index < len) {
-        let h = decode_char(*vector::borrow(bz, index));
-        let l = decode_char(*vector::borrow(bz, index+1));
-
-        vector::push_back(&mut vec, l + (h << 4));
-
-        index = index + 2
+    let index = 0;
+    while (index < len) {
+        let val = *vector::borrow(bz, index);
+        vector::push_back(
+            &mut vec,
+            encode_to_char_with_option(val / 0x10, is_upper)
+        );
+        vector::push_back(
+            &mut vec,
+            encode_to_char_with_option(val % 0x10, is_upper)
+        );
+        index = index + 1;
     };
 
-    vec
+    string::utf8(vec)
 }
 
-
- - - -## Function `encode_to_char` - - - -
fun encode_to_char(num: u8): u8
-
- + +## Function `decode_string` -
-Implementation -
fun encode_to_char(num: u8): u8 {
-    if (num < 10) {
-        0x30 + num
-    } else {
-        0x57 + num
-    }
-}
+
public fun decode_string(str: &string::String): vector<u8>
 
-
- - - -## Function `decode_char` +##### Implementation +
public fun decode_string(str: &String): vector<u8> {
+    assert!(
+        is_hex_string(str),
+        error::invalid_argument(ENOT_HEXSTRING)
+    );
 
-
fun decode_char(num: u8): u8
-
+ let vec: vector<u8> = vector[]; + let bz = string::bytes(str); + let len = vector::length(bz); + if (len == 0) { + return vec + }; + let index = + if (len % 2 == 1) { + let l = decode_char(*vector::borrow(bz, 0)); + vector::push_back(&mut vec, l); + 1 + } else { 0 }; -
-Implementation + while (index < len) { + let h = decode_char(*vector::borrow(bz, index)); + let l = decode_char(*vector::borrow(bz, index + 1)); + vector::push_back(&mut vec, (h << 4) + l); + index = index + 2 + }; -
fun decode_char(num: u8): u8 {
-    if (num < 0x3a) {
-        num - 0x30
-    } else {
-        num - 0x57
-    }
+    vec
 }
 
- - - -
diff --git a/minitia_stdlib/doc/initia_nft.md b/minitia_stdlib/doc/initia_nft.md index fa8ba3e..1985614 100644 --- a/minitia_stdlib/doc/initia_nft.md +++ b/minitia_stdlib/doc/initia_nft.md @@ -21,30 +21,24 @@ The key features are: - [Function `create_collection_object`](#0x1_initia_nft_create_collection_object) - [Function `mint`](#0x1_initia_nft_mint) - [Function `mint_nft_object`](#0x1_initia_nft_mint_nft_object) -- [Function `mint_internal`](#0x1_initia_nft_mint_internal) -- [Function `borrow`](#0x1_initia_nft_borrow) - [Function `is_mutable_description`](#0x1_initia_nft_is_mutable_description) - [Function `is_mutable_uri`](#0x1_initia_nft_is_mutable_uri) -- [Function `authorized_borrow`](#0x1_initia_nft_authorized_borrow) - [Function `burn`](#0x1_initia_nft_burn) - [Function `set_description`](#0x1_initia_nft_set_description) - [Function `set_uri`](#0x1_initia_nft_set_uri) -- [Function `collection_object`](#0x1_initia_nft_collection_object) -- [Function `borrow_collection`](#0x1_initia_nft_borrow_collection) - [Function `is_mutable_collection_description`](#0x1_initia_nft_is_mutable_collection_description) - [Function `is_mutable_collection_royalty`](#0x1_initia_nft_is_mutable_collection_royalty) - [Function `is_mutable_collection_uri`](#0x1_initia_nft_is_mutable_collection_uri) - [Function `is_mutable_collection_nft_description`](#0x1_initia_nft_is_mutable_collection_nft_description) - [Function `is_mutable_collection_nft_uri`](#0x1_initia_nft_is_mutable_collection_nft_uri) -- [Function `authorized_borrow_collection`](#0x1_initia_nft_authorized_borrow_collection) - [Function `set_collection_description`](#0x1_initia_nft_set_collection_description) - [Function `set_collection_royalties`](#0x1_initia_nft_set_collection_royalties) - [Function `set_collection_royalties_call`](#0x1_initia_nft_set_collection_royalties_call) - [Function `set_collection_uri`](#0x1_initia_nft_set_collection_uri) -
use 0x1::collection;
-use 0x1::decimal128;
+
use 0x1::bigdecimal;
+use 0x1::collection;
 use 0x1::error;
 use 0x1::nft;
 use 0x1::object;
@@ -68,8 +62,7 @@ Storage state for managing the no-code Collection.
 
 
 
-
-Fields +##### Fields
@@ -112,8 +105,6 @@ Storage state for managing the no-code Collection.
-
- ## Resource `InitiaNft` @@ -126,8 +117,7 @@ Storage state for managing the no-code Nft. -
-Fields +##### Fields
@@ -146,8 +136,6 @@ Storage state for managing the no-code Nft.
-
- ## Constants @@ -220,13 +208,12 @@ The provided signer is not the owner Create a new collection -
public entry fun create_collection(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_uri: bool, royalty: decimal128::Decimal128)
+
public entry fun create_collection(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_uri: bool, royalty: bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation
public entry fun create_collection(
@@ -240,7 +227,7 @@ Create a new collection
     mutable_uri: bool,
     mutable_nft_description: bool,
     mutable_nft_uri: bool,
-    royalty: Decimal128,
+    royalty: BigDecimal
 ) {
     create_collection_object(
         creator,
@@ -253,28 +240,25 @@ Create a new collection
         mutable_uri,
         mutable_nft_description,
         mutable_nft_uri,
-        royalty,
+        royalty
     );
 }
 
-
- ## Function `create_collection_object` -
public fun create_collection_object(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_uri: bool, royalty: decimal128::Decimal128): (object::Object<initia_nft::InitiaNftCollection>, object::ExtendRef)
+
public fun create_collection_object(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_uri: bool, royalty: bigdecimal::BigDecimal): (object::Object<initia_nft::InitiaNftCollection>, object::ExtendRef)
 
-
-Implementation +##### Implementation
public fun create_collection_object(
@@ -288,41 +272,48 @@ Create a new collection
     mutable_uri: bool,
     mutable_nft_description: bool,
     mutable_nft_uri: bool,
-    royalty: Decimal128,
+    royalty: BigDecimal
 ): (Object<InitiaNftCollection>, ExtendRef) {
     let creator_addr = signer::address_of(creator);
     let royalty = royalty::create(royalty, creator_addr);
-    let constructor_ref = if (option::is_some(&max_supply)) {
-        collection::create_fixed_collection(
-            creator,
-            description,
-            option::extract(&mut max_supply),
-            name,
-            option::some(royalty),
-            uri,
-        )
-    } else {
-        collection::create_unlimited_collection(
-            creator,
-            description,
-            name,
-            option::some(royalty),
-            uri,
-        )
-    };
+    let constructor_ref =
+        if (option::is_some(&max_supply)) {
+            collection::create_fixed_collection(
+                creator,
+                description,
+                option::extract(&mut max_supply),
+                name,
+                option::some(royalty),
+                uri
+            )
+        } else {
+            collection::create_unlimited_collection(
+                creator,
+                description,
+                name,
+                option::some(royalty),
+                uri
+            )
+        };
 
     let object_signer = object::generate_signer(&constructor_ref);
-    let mutator_ref = if (mutable_description || mutable_uri) {
-        option::some(collection::generate_mutator_ref(&constructor_ref))
-    } else {
-        option::none()
-    };
-
-    let royalty_mutator_ref = if (mutable_royalty) {
-        option::some(royalty::generate_mutator_ref(object::generate_extend_ref(&constructor_ref)))
-    } else {
-        option::none()
-    };
+    let mutator_ref =
+        if (mutable_description || mutable_uri) {
+            option::some(collection::generate_mutator_ref(&constructor_ref))
+        } else {
+            option::none()
+        };
+
+    let royalty_mutator_ref =
+        if (mutable_royalty) {
+            option::some(
+                royalty::generate_mutator_ref(
+                    object::generate_extend_ref(&constructor_ref)
+                )
+            )
+        } else {
+            option::none()
+        };
 
     let extend_ref = object::generate_extend_ref(&constructor_ref);
 
@@ -332,7 +323,7 @@ Create a new collection
         mutable_description,
         mutable_uri,
         mutable_nft_description,
-        mutable_nft_uri,
+        mutable_nft_uri
     };
     move_to(&object_signer, initia_nft_collection);
     (object::object_from_constructor_ref(&constructor_ref), extend_ref)
@@ -341,8 +332,6 @@ Create a new collection
 
 
 
-
- ## Function `mint` @@ -355,8 +344,7 @@ With an existing collection, directly mint a viable nft into the creators accoun -
-Implementation +##### Implementation
public entry fun mint(
@@ -366,19 +354,29 @@ With an existing collection, directly mint a viable nft into the creators accoun
     token_id: String,
     uri: String,
     can_burn: bool,
-    to: Option<address>,
+    to: Option<address>
 ) acquires InitiaNftCollection {
-    let (nft_object, _) = mint_nft_object(creator, collection, description, token_id, uri, can_burn);
+    let (nft_object, _) =
+        mint_nft_object(
+            creator,
+            collection,
+            description,
+            token_id,
+            uri,
+            can_burn
+        );
     if (option::is_some(&to)) {
-        object::transfer(creator, nft_object, option::extract(&mut to));
+        object::transfer(
+            creator,
+            nft_object,
+            option::extract(&mut to)
+        );
     }
 }
 
-
- ## Function `mint_nft_object` @@ -391,8 +389,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun mint_nft_object(
@@ -401,121 +398,25 @@ Mint a nft into an existing collection, and retrieve the object / address of the
     description: String,
     token_id: String,
     uri: String,
-    can_burn: bool,
+    can_burn: bool
 ): (Object<InitiaNft>, ExtendRef) acquires InitiaNftCollection {
-    let constructor_ref = mint_internal(
-        creator,
-        collection,
-        description,
-        token_id,
-        uri,
-        can_burn,
-    );
-    let extend_ref = object::generate_extend_ref(&constructor_ref);
-
-    (object::object_from_constructor_ref(&constructor_ref), extend_ref)
-}
-
- - - -
- - - -## Function `mint_internal` - - - -
fun mint_internal(creator: &signer, collection: string::String, description: string::String, token_id: string::String, uri: string::String, can_burn: bool): object::ConstructorRef
-
- - - -
-Implementation - - -
fun mint_internal(
-    creator: &signer,
-    collection: String,
-    description: String,
-    token_id: String,
-    uri: String,
-    can_burn: bool,
-): ConstructorRef acquires InitiaNftCollection {
-    let constructor_ref = nft::create(
+    let constructor_ref =
+        mint_internal(
             creator,
             collection,
             description,
             token_id,
-            option::none(),
             uri,
+            can_burn
         );
+    let extend_ref = object::generate_extend_ref(&constructor_ref);
 
-    let object_signer = object::generate_signer(&constructor_ref);
-
-    let collection_obj = collection_object(creator, &collection);
-    let collection = borrow_collection(collection_obj);
-
-    let mutator_ref = if (
-        collection.mutable_nft_description
-            || collection.mutable_nft_uri
-    ) {
-        option::some(nft::generate_mutator_ref(&constructor_ref))
-    } else {
-        option::none()
-    };
-
-    let burn_ref = if (can_burn) {
-        option::some(nft::generate_burn_ref(&constructor_ref))
-    } else {
-        option::none()
-    };
-
-    let initia_nft = InitiaNft {
-        burn_ref,
-        mutator_ref,
-    };
-    move_to(&object_signer, initia_nft);
-
-    constructor_ref
-}
-
- - - -
- - - -## Function `borrow` - - - -
fun borrow<T: key>(nft: object::Object<T>): &initia_nft::InitiaNft
-
- - - -
-Implementation - - -
inline fun borrow<T: key>(nft: Object<T>): &InitiaNft {
-    let nft_address = object::object_address(nft);
-    assert!(
-        exists<InitiaNft>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-    borrow_global<InitiaNft>(nft_address)
+    (object::object_from_constructor_ref(&constructor_ref), extend_ref)
 }
 
-
- ## Function `is_mutable_description` @@ -528,8 +429,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_description<T: key>(nft: Object<T>): bool acquires InitiaNftCollection {
@@ -539,8 +439,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_uri` @@ -553,8 +451,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_uri<T: key>(nft: Object<T>): bool acquires InitiaNftCollection {
@@ -564,42 +461,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- - - -## Function `authorized_borrow` - - - -
fun authorized_borrow<T: key>(nft: object::Object<T>, creator: &signer): &initia_nft::InitiaNft
-
- - - -
-Implementation - - -
inline fun authorized_borrow<T: key>(nft: Object<T>, creator: &signer): &InitiaNft {
-    let nft_address = object::object_address(nft);
-    assert!(
-        exists<InitiaNft>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-
-    assert!(
-        nft::creator(nft) == signer::address_of(creator),
-        error::permission_denied(ENOT_CREATOR),
-    );
-    borrow_global<InitiaNft>(nft_address)
-}
-
- - - -
- ## Function `burn` @@ -611,35 +472,32 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun burn<T: key>(owner: &signer, nft: Object<T>) acquires InitiaNft {
-    let nft_address = object::object_address(nft);
+    let nft_address = object::object_address(&nft);
     assert!(
         exists<InitiaNft>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
+        error::not_found(ENFT_DOES_NOT_EXIST)
     );
     assert!(
         object::owns(nft, signer::address_of(owner)),
-        error::permission_denied(ENOT_OWNER),
+        error::permission_denied(ENOT_OWNER)
     );
 
-    let initia_nft = move_from<InitiaNft>(object::object_address(nft));
-    assert!(option::is_some(&initia_nft.burn_ref), error::invalid_state(ECAN_NOT_BURN));
-    let InitiaNft {
-        burn_ref,
-        mutator_ref: _,
-    } = initia_nft;
+    let initia_nft = move_from<InitiaNft>(object::object_address(&nft));
+    assert!(
+        option::is_some(&initia_nft.burn_ref),
+        error::invalid_state(ECAN_NOT_BURN)
+    );
+    let InitiaNft { burn_ref, mutator_ref: _ } = initia_nft;
     nft::burn(option::extract(&mut burn_ref));
 }
 
-
- ## Function `set_description` @@ -651,28 +509,26 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_description<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    description: String,
+    creator: &signer, nft: Object<T>, description: String
 ) acquires InitiaNftCollection, InitiaNft {
     assert!(
         is_mutable_description(nft),
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
     );
     let initia_nft = authorized_borrow(nft, creator);
-    nft::set_description(option::borrow(&initia_nft.mutator_ref), description);
+    nft::set_description(
+        option::borrow(&initia_nft.mutator_ref),
+        description
+    );
 }
 
-
- ## Function `set_uri` @@ -684,18 +540,15 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_uri<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    uri: String,
+    creator: &signer, nft: Object<T>, uri: String
 ) acquires InitiaNftCollection, InitiaNft {
     assert!(
         is_mutable_uri(nft),
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
     );
     let initia_nft = authorized_borrow(nft, creator);
     nft::set_uri(option::borrow(&initia_nft.mutator_ref), uri);
@@ -704,62 +557,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- - - -## Function `collection_object` - - - -
fun collection_object(creator: &signer, name: &string::String): object::Object<initia_nft::InitiaNftCollection>
-
- - - -
-Implementation - - -
inline fun collection_object(creator: &signer, name: &String): Object<InitiaNftCollection> {
-    let collection_addr = collection::create_collection_address(signer::address_of(creator), name);
-    object::address_to_object<InitiaNftCollection>(collection_addr)
-}
-
- - - -
- - - -## Function `borrow_collection` - - - -
fun borrow_collection<T: key>(nft: object::Object<T>): &initia_nft::InitiaNftCollection
-
- - - -
-Implementation - - -
inline fun borrow_collection<T: key>(nft: Object<T>): &InitiaNftCollection {
-    let collection_address = object::object_address(nft);
-    assert!(
-        exists<InitiaNftCollection>(collection_address),
-        error::not_found(ECOLLECTION_DOES_NOT_EXIST),
-    );
-    borrow_global<InitiaNftCollection>(collection_address)
-}
-
- - - -
- ## Function `is_mutable_collection_description` @@ -771,12 +568,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_description<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires InitiaNftCollection {
     borrow_collection(collection).mutable_description
 }
@@ -784,8 +580,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_royalty` @@ -797,12 +591,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_royalty<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires InitiaNftCollection {
     option::is_some(&borrow_collection(collection).royalty_mutator_ref)
 }
@@ -810,8 +603,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_uri` @@ -823,12 +614,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_uri<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires InitiaNftCollection {
     borrow_collection(collection).mutable_uri
 }
@@ -836,8 +626,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_nft_description` @@ -849,12 +637,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_description<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires InitiaNftCollection {
     borrow_collection(collection).mutable_nft_description
 }
@@ -862,8 +649,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_nft_uri` @@ -875,12 +660,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_uri<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires InitiaNftCollection {
     borrow_collection(collection).mutable_nft_uri
 }
@@ -888,41 +672,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- - - -## Function `authorized_borrow_collection` - - - -
fun authorized_borrow_collection<T: key>(collection: object::Object<T>, creator: &signer): &initia_nft::InitiaNftCollection
-
- - - -
-Implementation - - -
inline fun authorized_borrow_collection<T: key>(collection: Object<T>, creator: &signer): &InitiaNftCollection {
-    let collection_address = object::object_address(collection);
-    assert!(
-        exists<InitiaNftCollection>(collection_address),
-        error::not_found(ECOLLECTION_DOES_NOT_EXIST),
-    );
-    assert!(
-        collection::creator(collection) == signer::address_of(creator),
-        error::permission_denied(ENOT_CREATOR),
-    );
-    borrow_global<InitiaNftCollection>(collection_address)
-}
-
- - - -
- ## Function `set_collection_description` @@ -934,28 +683,26 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_collection_description<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    description: String,
+    creator: &signer, collection: Object<T>, description: String
 ) acquires InitiaNftCollection {
     let initia_nft_collection = authorized_borrow_collection(collection, creator);
     assert!(
         initia_nft_collection.mutable_description,
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
+    );
+    collection::set_description(
+        option::borrow(&initia_nft_collection.mutator_ref),
+        description
     );
-    collection::set_description(option::borrow(&initia_nft_collection.mutator_ref), description);
 }
 
-
- ## Function `set_collection_royalties` @@ -967,48 +714,45 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun set_collection_royalties<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    royalty: royalty::Royalty,
+    creator: &signer, collection: Object<T>, royalty: royalty::Royalty
 ) acquires InitiaNftCollection {
     let initia_nft_collection = authorized_borrow_collection(collection, creator);
     assert!(
         option::is_some(&initia_nft_collection.royalty_mutator_ref),
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
+    );
+    royalty::update(
+        option::borrow(&initia_nft_collection.royalty_mutator_ref),
+        royalty
     );
-    royalty::update(option::borrow(&initia_nft_collection.royalty_mutator_ref), royalty);
 }
 
-
- ## Function `set_collection_royalties_call` -
public fun set_collection_royalties_call<T: key>(creator: &signer, collection: object::Object<T>, royalty: decimal128::Decimal128, payee_address: address)
+
public fun set_collection_royalties_call<T: key>(creator: &signer, collection: object::Object<T>, royalty: bigdecimal::BigDecimal, payee_address: address)
 
-
-Implementation +##### Implementation
public fun set_collection_royalties_call<T: key>(
     creator: &signer,
     collection: Object<T>,
-    royalty: Decimal128,
-    payee_address: address,
+    royalty: BigDecimal,
+    payee_address: address
 ) acquires InitiaNftCollection {
     let royalty = royalty::create(royalty, payee_address);
     set_collection_royalties(creator, collection, royalty);
@@ -1017,8 +761,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `set_collection_uri` @@ -1030,24 +772,20 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_collection_uri<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    uri: String,
+    creator: &signer, collection: Object<T>, uri: String
 ) acquires InitiaNftCollection {
     let initia_nft_collection = authorized_borrow_collection(collection, creator);
     assert!(
         initia_nft_collection.mutable_uri,
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
+    );
+    collection::set_uri(
+        option::borrow(&initia_nft_collection.mutator_ref),
+        uri
     );
-    collection::set_uri(option::borrow(&initia_nft_collection.mutator_ref), uri);
 }
 
- - - -
diff --git a/minitia_stdlib/doc/json.md b/minitia_stdlib/doc/json.md index 39789ce..9d4de2a 100644 --- a/minitia_stdlib/doc/json.md +++ b/minitia_stdlib/doc/json.md @@ -5,2027 +5,79 @@ -- [Struct `JsonIndex`](#0x1_json_JsonIndex) -- [Struct `JsonElem`](#0x1_json_JsonElem) -- [Struct `JsonObject`](#0x1_json_JsonObject) -- [Struct `Number`](#0x1_json_Number) -- [Struct `JsonValue`](#0x1_json_JsonValue) -- [Struct `NativeArrayValue`](#0x1_json_NativeArrayValue) -- [Struct `NativeObjectValue`](#0x1_json_NativeObjectValue) -- [Struct `KeyValue`](#0x1_json_KeyValue) -- [Constants](#@Constants_0) -- [Function `empty`](#0x1_json_empty) -- [Function `data`](#0x1_json_data) -- [Function `stringify`](#0x1_json_stringify) -- [Function `stringify_internal`](#0x1_json_stringify_internal) -- [Function `parse`](#0x1_json_parse) -- [Function `parse_internal`](#0x1_json_parse_internal) -- [Function `start_index`](#0x1_json_start_index) -- [Function `get_next_index`](#0x1_json_get_next_index) -- [Function `get_prev_index`](#0x1_json_get_prev_index) -- [Function `get_index_last`](#0x1_json_get_index_last) -- [Function `get_depth`](#0x1_json_get_depth) -- [Function `borrow`](#0x1_json_borrow) -- [Function `borrow_mut`](#0x1_json_borrow_mut) -- [Function `find`](#0x1_json_find) -- [Function `is_null_index`](#0x1_json_is_null_index) -- [Function `set_elem`](#0x1_json_set_elem) -- [Function `set_bool`](#0x1_json_set_bool) -- [Function `set_number`](#0x1_json_set_number) -- [Function `set_int_raw`](#0x1_json_set_int_raw) -- [Function `set_int_string`](#0x1_json_set_int_string) -- [Function `set_dec_string`](#0x1_json_set_dec_string) -- [Function `set_string`](#0x1_json_set_string) -- [Function `set_array`](#0x1_json_set_array) -- [Function `set_object`](#0x1_json_set_object) -- [Function `new_bool`](#0x1_json_new_bool) -- [Function `new_number`](#0x1_json_new_number) -- [Function `new_int`](#0x1_json_new_int) -- [Function `new_dec`](#0x1_json_new_dec) -- [Function `new_string`](#0x1_json_new_string) -- [Function `new_array`](#0x1_json_new_array) -- [Function `new_object`](#0x1_json_new_object) -- [Function `is_null`](#0x1_json_is_null) -- [Function `is_bool`](#0x1_json_is_bool) -- [Function `is_number`](#0x1_json_is_number) -- [Function `is_string`](#0x1_json_is_string) -- [Function `is_array`](#0x1_json_is_array) -- [Function `is_object`](#0x1_json_is_object) -- [Function `as_bool`](#0x1_json_as_bool) -- [Function `as_number`](#0x1_json_as_number) -- [Function `as_int`](#0x1_json_as_int) -- [Function `as_dec`](#0x1_json_as_dec) -- [Function `as_string`](#0x1_json_as_string) -- [Function `unpack_elem`](#0x1_json_unpack_elem) -- [Function `get_child_length`](#0x1_json_get_child_length) -- [Function `set_child_length`](#0x1_json_set_child_length) -- [Function `get_type`](#0x1_json_get_type) -- [Function `parse_bool`](#0x1_json_parse_bool) -- [Function `parse_number`](#0x1_json_parse_number) -- [Function `parse_string`](#0x1_json_parse_string) -- [Function `parse_array`](#0x1_json_parse_array) -- [Function `parse_object`](#0x1_json_parse_object) -- [Function `stringify_bool`](#0x1_json_stringify_bool) -- [Function `stringify_number`](#0x1_json_stringify_number) -- [Function `stringify_string`](#0x1_json_stringify_string) -- [Function `stringify_array`](#0x1_json_stringify_array) -- [Function `stringify_object`](#0x1_json_stringify_object) +- [Function `marshal`](#0x1_json_marshal) +- [Function `marshal_to_string`](#0x1_json_marshal_to_string) +- [Function `unmarshal`](#0x1_json_unmarshal) -
use 0x1::decimal256;
-use 0x1::error;
-use 0x1::option;
-use 0x1::simple_map;
-use 0x1::string;
-use 0x1::vector;
+
use 0x1::string;
 
- + -## Struct `JsonIndex` +## Function `marshal` +Marshal data to JSON bytes. +NOTE: key _type_ is converted to @type +NOTE: key _move_ is converted to move -
struct JsonIndex has copy, drop, store
-
- - - -
-Fields - - -
-
-data: vector<u64> -
-
- -
-
- - -
- - - -## Struct `JsonElem` - - - -
struct JsonElem has copy, drop, store
-
- - - -
-Fields - - -
-
-key: option::Option<string::String> -
-
- -
-
-value: json::JsonValue -
-
- -
-
- - -
- - - -## Struct `JsonObject` - - - -
struct JsonObject has copy, drop
-
- - - -
-Fields - - -
-
-data: simple_map::SimpleMap<json::JsonIndex, json::JsonElem> -
-
- -
-
- - -
- - - -## Struct `Number` - - - -
struct Number has copy, drop, store
-
- - - -
-Fields - - -
-
-type: u8 -
-
- -
-
-value: u256 -
-
- -
-
-is_positive: bool -
-
- -
-
- - -
- - - -## Struct `JsonValue` - - - -
struct JsonValue has copy, drop, store
-
- - - -
-Fields - - -
-
-type: u8 -
-
- -
-
-value_bool: option::Option<bool> -
-
- -
-
-value_number: option::Option<json::Number> -
-
- -
-
-value_string: option::Option<string::String> -
-
- -
-
-child_length: u64 -
-
- -
-
- - -
- - - -## Struct `NativeArrayValue` - - - -
struct NativeArrayValue has copy, drop, store
-
- - - -
-Fields - - -
-
-type: u8 -
-
- -
-
-value: string::String -
-
- -
-
- - -
- - - -## Struct `NativeObjectValue` - - - -
struct NativeObjectValue has copy, drop, store
-
- - - -
-Fields - - -
-
-type: u8 -
-
- -
-
-key: string::String -
-
- -
-
-value: string::String -
-
- -
-
- - -
- - - -## Struct `KeyValue` - - - -
struct KeyValue has copy, drop, store
-
- - - -
-Fields - - -
-
-key: string::String -
-
- -
-
-value: string::String -
-
- -
-
- - -
- - - -## Constants - - - - - - -
const EKEY_NOT_FOUND: u64 = 7;
-
- - - - - - - -
const EOUT_OF_RANGE: u64 = 3;
-
- - - - - - - -
const EDUPLICATED_INDEX: u64 = 5;
-
- - - - - - - -
const EINVALID_ARGS: u64 = 2;
-
- - - - - - - -
const ENOT_SUPPORTED_TYPE: u64 = 6;
-
- - - - - - - -
const ESERDE_DESERIALIZE: u64 = 1;
-
- - - - - - - -
const ETYPE_MISMATCH: u64 = 4;
-
- - - - - - - -
const JSON_VALUE_TYPE_ARRAY: u8 = 4;
-
- - - - - - - -
const JSON_VALUE_TYPE_BOOL: u8 = 1;
-
- - - - - - - -
const JSON_VALUE_TYPE_NULL: u8 = 0;
-
- - - - - - - -
const JSON_VALUE_TYPE_NUMBER: u8 = 2;
-
- - - - - - - -
const JSON_VALUE_TYPE_OBJECT: u8 = 5;
-
- - - - - - - -
const JSON_VALUE_TYPE_STRING: u8 = 3;
-
- - - - - - - -
const JSON_VALUE_TYPE_UNKNOWN: u8 = 255;
-
- - - - - - - -
const NUMBER_TYPE_DEC: u8 = 1;
-
- - - - - - - -
const NUMBER_TYPE_INT: u8 = 0;
-
- - - - - -## Function `empty` - - - -
public fun empty(): json::JsonObject
-
- - - -
-Implementation - - -
public fun empty(): JsonObject{
-    JsonObject {
-        data: simple_map::create<JsonIndex, JsonElem>(),
-    }
-}
-
- - - -
- - - -## Function `data` - - - -
public fun data(json_obj: &json::JsonObject): &simple_map::SimpleMap<json::JsonIndex, json::JsonElem>
-
- - - -
-Implementation - - -
public fun data(json_obj: &JsonObject): &SimpleMap<JsonIndex, JsonElem>{
-    &json_obj.data
-}
-
- - - -
- - - -## Function `stringify` - - - -
public fun stringify(json_obj: &json::JsonObject): string::String
-
- - - -
-Implementation - - -
public fun stringify(json_obj: &JsonObject): String {
-    let index = start_index();
-    let (_, json_string) = stringify_internal(json_obj, index);
-    json_string
-}
-
- - - -
- - - -## Function `stringify_internal` - - - -
fun stringify_internal(json_obj: &json::JsonObject, current_index: json::JsonIndex): (option::Option<string::String>, string::String)
-
- - - -
-Implementation - - -
fun stringify_internal(json_obj: &JsonObject, current_index: JsonIndex): (Option<String>, String) {
-    let json_elem = borrow(json_obj, ¤t_index);
-    let type = json_elem.value.type;
-
-    assert!(type != JSON_VALUE_TYPE_NULL, ENOT_SUPPORTED_TYPE);
-
-    if(type == JSON_VALUE_TYPE_BOOL) {
-        (json_elem.key, stringify_bool(as_bool(json_elem.value)))
-    } else if(type == JSON_VALUE_TYPE_NUMBER) {
-        (json_elem.key, stringify_number(as_number(json_elem.value)))
-    } else if(type == JSON_VALUE_TYPE_STRING) {
-        (json_elem.key, stringify_string(as_string(json_elem.value)))
-    } else if(type == JSON_VALUE_TYPE_ARRAY) {
-        let values = vector::empty<String>();
-        let i =0;
-        while(i < json_elem.value.child_length) {
-            let next_index = get_next_index(¤t_index, i);
-            let (_, value) = stringify_internal(json_obj, next_index);
-            vector::push_back(&mut values, value);
-            i = i + 1;
-        };
-        (json_elem.key, stringify_array(values))
-    } else if(type == JSON_VALUE_TYPE_OBJECT) {
-        let values = vector::empty<KeyValue>();
-        let i =0;
-        while(i < json_elem.value.child_length) {
-            let next_index = get_next_index(¤t_index, i);
-            let (key, value) = stringify_internal(json_obj, next_index);
-            vector::push_back(&mut values, KeyValue{
-                key: *option::borrow(&key),
-                value: value,
-            });
-            i = i + 1;
-        };
-        (json_elem.key, stringify_object(values))
-    } else {
-        abort(ENOT_SUPPORTED_TYPE)
-    }
-}
-
- - - -
- - - -## Function `parse` - - - -
public fun parse(json_string: string::String): json::JsonObject
-
- - - -
-Implementation - - -
public fun parse(json_string: String): JsonObject {
-    let json_obj = empty();
-    let index = start_index();
-    let type = get_type(&json_string);
-    parse_internal(&mut json_obj, type, option::none<String>(),json_string, index);
-
-    json_obj
-}
-
- - - -
- - - -## Function `parse_internal` - - - -
fun parse_internal(json_obj: &mut json::JsonObject, type: u8, key: option::Option<string::String>, json_string: string::String, current_index: json::JsonIndex)
-
- - - -
-Implementation - - -
fun parse_internal(json_obj: &mut JsonObject, type: u8, key: Option<String>, json_string: String, current_index: JsonIndex) {
-    assert!(type != JSON_VALUE_TYPE_NULL, ENOT_SUPPORTED_TYPE);
-
-    if(type == JSON_VALUE_TYPE_BOOL) {
-        set_bool(json_obj, current_index, key, parse_bool(json_string));
-    } else if(type == JSON_VALUE_TYPE_NUMBER) {
-        set_number(json_obj, current_index, key, parse_number(json_string));
-    } else if(type == JSON_VALUE_TYPE_STRING) {
-        let string_value = parse_string(json_string);
-        // number can be wrapped into string (e.g. "\"12.3456\"" -> "12.3456")
-        let type = get_type(&string_value);
-        if(type == JSON_VALUE_TYPE_NUMBER){
-            set_number(json_obj, current_index, key, parse_number(string_value));
-        } else {
-            set_string(json_obj, current_index, key, string_value);
-        }
-    } else if(type == JSON_VALUE_TYPE_ARRAY) {
-        let value = parse_array(json_string);
-        vector::reverse(&mut value);
-        let len = vector::length(&value);
-
-        set_array(json_obj, current_index, key, len);
-
-        let i = 0;
-        while( i < len) {
-            let array_value = vector::pop_back(&mut value);
-            let index = get_next_index(¤t_index, i);
-            parse_internal(json_obj, array_value.type, option::none<String>(), array_value.value, index);
-            i = i + 1;
-        };
-    } else if(type == JSON_VALUE_TYPE_OBJECT) {
-        let value = parse_object(json_string);
-        vector::reverse(&mut value);
-        let len = vector::length(&value);
-
-        set_object(json_obj, current_index, key, len);
-
-        let i = 0;
-        while( i < len) {
-            let object_value = vector::pop_back(&mut value);
-            let index = get_next_index(¤t_index, i);
-            parse_internal(json_obj, object_value.type, option::some(object_value.key), object_value.value, index);
-            i = i + 1;
-        };
-    } else {
-        abort(ENOT_SUPPORTED_TYPE)
-    };
-}
-
- - - -
- - - -## Function `start_index` - - - -
public fun start_index(): json::JsonIndex
-
- - - -
-Implementation - - -
public fun start_index(): JsonIndex  {
-    JsonIndex {
-        data: vector::singleton<u64>(0)
-    }
-}
-
- - - -
- - - -## Function `get_next_index` - - - -
public fun get_next_index(current: &json::JsonIndex, idx: u64): json::JsonIndex
-
- - - -
-Implementation - - -
public fun get_next_index(current: &JsonIndex, idx: u64): JsonIndex  {
-    let index = *current;
-    vector::push_back(&mut index.data, idx);
-    index
-}
-
- - - -
- - - -## Function `get_prev_index` - - - -
public fun get_prev_index(current: &json::JsonIndex): (json::JsonIndex, u64)
-
- - - -
-Implementation - - -
public fun get_prev_index(current: &JsonIndex): (JsonIndex, u64) {
-    let index = *current;
-    let last = vector::pop_back(&mut index.data);
-    (index, last)
-}
-
- - - -
- - - -## Function `get_index_last` - - - -
public fun get_index_last(index: &json::JsonIndex): u64
-
- - - -
-Implementation - - -
public fun get_index_last(index: &JsonIndex): u64 {
-    let length = vector::length(&index.data);
-    *vector::borrow(&index.data, length-1)
-}
-
- - - -
- - - -## Function `get_depth` - - - -
public fun get_depth(index: &json::JsonIndex): u64
-
- - - -
-Implementation - - -
public fun get_depth(index: &JsonIndex): u64 {
-    vector::length(&index.data)
-}
-
- - - -
- - - -## Function `borrow` - - - -
public fun borrow(obj: &json::JsonObject, index: &json::JsonIndex): &json::JsonElem
-
- - - -
-Implementation - - -
public fun borrow(obj: &JsonObject, index: &JsonIndex): &JsonElem{
-    simple_map::borrow(&obj.data, index)
-}
-
- - - -
- - - -## Function `borrow_mut` - - - -
public fun borrow_mut(obj: &mut json::JsonObject, index: &json::JsonIndex): &mut json::JsonElem
-
- - - -
-Implementation - - -
public fun borrow_mut(obj: &mut JsonObject, index: &JsonIndex): &mut JsonElem{
-    simple_map::borrow_mut(&mut obj.data, index)
-}
-
- - - -
- - - -## Function `find` - - - -
public fun find(obj: &json::JsonObject, index: &json::JsonIndex, key: &string::String): json::JsonIndex
-
- - - -
-Implementation - - -
public fun find(obj: &JsonObject, index: &JsonIndex, key: &String): JsonIndex {
-    let i = 0;
-    let elem = borrow(obj, index);
-
-    while (i < elem.value.child_length) {
-        let next_index = get_next_index(index, i);
-        let child_elem = borrow(obj, &next_index);
-        if ( *string::bytes(option::borrow(&child_elem.key)) == *string::bytes(key)) {
-            break
-        };
-        i = i + 1;
-    };
-
-    if( i >= elem.value.child_length) {
-        JsonIndex {
-            data: vector::empty(),
-        }
-    } else {
-        get_next_index(index, i)
-    }
-}
-
- - - -
- - - -## Function `is_null_index` - - - -
public fun is_null_index(index: &json::JsonIndex): bool
-
- - - -
-Implementation - - -
public fun is_null_index(index: &JsonIndex): bool {
-    if( vector::length(&index.data) == 0) {
-        true
-    } else {
-        false
-    }
-}
-
- - - -
- - - -## Function `set_elem` - - - -
fun set_elem(object: &mut json::JsonObject, index: json::JsonIndex, elem: json::JsonElem)
-
- - - -
-Implementation - - -
fun set_elem(object: &mut JsonObject, index: JsonIndex, elem: JsonElem) {
-    assert!(!simple_map::contains_key(&object.data, &index), EDUPLICATED_INDEX);
-    simple_map::add(&mut object.data, index, elem);
-}
-
- - - -
- - - -## Function `set_bool` - - - -
public fun set_bool(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, value: bool)
-
- - - -
-Implementation - - -
public fun set_bool(object: &mut JsonObject, index: JsonIndex, key: Option<String>, value: bool) {
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_bool(value),
-    });
-}
-
- - - -
- - - -## Function `set_number` - - - -
fun set_number(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, value: json::Number)
-
- - - -
-Implementation - - -
fun set_number(object: &mut JsonObject, index: JsonIndex, key: Option<String>, value: Number) {
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_number(value),
-    });
-}
-
- - - -
- - - -## Function `set_int_raw` - - - -
public fun set_int_raw(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, is_positive: bool, value: u256)
-
- - - -
-Implementation - - -
public fun set_int_raw(object:&mut JsonObject, index: JsonIndex, key: Option<String>, is_positive: bool, value: u256) {
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_int(is_positive, value),
-    });
-}
-
- - - -
- - - -## Function `set_int_string` - - - -
public fun set_int_string(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, is_positive: bool, value: u256)
-
- - - -
-Implementation - - -
public fun set_int_string(object:&mut JsonObject, index: JsonIndex, key: Option<String>, is_positive: bool, value: u256) {
-    let int_number = new_int(is_positive, value);
-    let int_string = stringify_number(as_number(int_number));
-
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_string(int_string),
-    });
-}
-
- - - -
- - - -## Function `set_dec_string` - - - -
public fun set_dec_string(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, is_positive: bool, value: decimal256::Decimal256)
-
- - - -
-Implementation - - -
public fun set_dec_string(object:&mut JsonObject, index: JsonIndex, key: Option<String>, is_positive: bool, value: Decimal256) {
-    let dec_number = new_dec(is_positive, value);
-    let dec_string = stringify_number(as_number(dec_number));
-
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_string(dec_string),
-    });
-}
-
- - - -
- - - -## Function `set_string` - - - -
public fun set_string(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, value: string::String)
-
- - - -
-Implementation - - -
public fun set_string(object: &mut JsonObject, index: JsonIndex, key: Option<String>, value: String) {
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_string(value),
-    });
-}
-
- - - -
- - - -## Function `set_array` - - - -
public fun set_array(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, child_length: u64)
-
- - - -
-Implementation - - -
public fun set_array(object: &mut JsonObject, index: JsonIndex, key: Option<String>, child_length: u64) {
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_array(child_length),
-    });
-}
-
- - - -
- - - -## Function `set_object` - - - -
public fun set_object(object: &mut json::JsonObject, index: json::JsonIndex, key: option::Option<string::String>, child_length: u64)
-
- - - -
-Implementation - - -
public fun set_object(object: &mut JsonObject, index: JsonIndex, key: Option<String>, child_length: u64) {
-    set_elem(object, index, JsonElem {
-        key: key,
-        value: new_object(child_length),
-    });
-}
-
- - - -
- - - -## Function `new_bool` - - - -
public fun new_bool(value: bool): json::JsonValue
-
- - - -
-Implementation - - -
public fun new_bool(value: bool): JsonValue {
-    JsonValue {
-        type: JSON_VALUE_TYPE_BOOL,
-        value_bool: option::some<bool>(value),
-        value_number: option::none<Number>(),
-        value_string: option::none<String>(),
-        child_length: 0,
-    }
-}
-
- - - -
- - - -## Function `new_number` - - - -
fun new_number(value: json::Number): json::JsonValue
-
- - - -
-Implementation - - -
fun new_number(value: Number): JsonValue {
-    JsonValue {
-        type: JSON_VALUE_TYPE_NUMBER,
-        value_bool: option::none<bool>(),
-        value_number: option::some<Number>(value),
-        value_string: option::none<String>(),
-        child_length: 0,
-    }
-}
-
- - - -
- - - -## Function `new_int` - - - -
public fun new_int(is_positive: bool, value: u256): json::JsonValue
-
- - - -
-Implementation - - -
public fun new_int(is_positive: bool, value:u256): JsonValue {
-    new_number(Number {
-        type: NUMBER_TYPE_INT,
-        value: value,
-        is_positive,
-    })
-}
-
- - - -
- - - -## Function `new_dec` - - - -
public fun new_dec(is_positive: bool, value: decimal256::Decimal256): json::JsonValue
-
- - - -
-Implementation - - -
public fun new_dec(is_positive: bool, value:Decimal256): JsonValue {
-    new_number(Number {
-        type: NUMBER_TYPE_DEC,
-        value: decimal256::val(&value),
-        is_positive,
-    })
-}
-
- - - -
- - - -## Function `new_string` - - - -
public fun new_string(value: string::String): json::JsonValue
-
- - - -
-Implementation - - -
public fun new_string(value: String): JsonValue {
-    JsonValue {
-        type: JSON_VALUE_TYPE_STRING,
-        value_bool: option::none<bool>(),
-        value_number: option::none<Number>(),
-        value_string: option::some<String>(value),
-        child_length: 0,
-    }
-}
-
- - - -
- - - -## Function `new_array` - - - -
public fun new_array(length: u64): json::JsonValue
-
- - - -
-Implementation - - -
public fun new_array(length: u64): JsonValue {
-    JsonValue {
-        type: JSON_VALUE_TYPE_ARRAY,
-        value_bool: option::none<bool>(),
-        value_number: option::none<Number>(),
-        value_string: option::none<String>(),
-        child_length: length,
-    }
-}
-
- - - -
- - - -## Function `new_object` - - - -
public fun new_object(length: u64): json::JsonValue
-
- - - -
-Implementation - - -
public fun new_object(length: u64): JsonValue {
-    JsonValue {
-        type: JSON_VALUE_TYPE_OBJECT,
-        value_bool: option::none<bool>(),
-        value_number: option::none<Number>(),
-        value_string: option::none<String>(),
-        child_length: length,
-    }
-}
-
- - - -
- - - -## Function `is_null` - - - -
public fun is_null(json_string: &string::String): bool
-
- - - -
-Implementation - - -
public fun is_null(json_string: &String): bool {
-    get_type(json_string) == JSON_VALUE_TYPE_NULL
-}
-
- - - -
- - - -## Function `is_bool` - - - -
public fun is_bool(json_string: &string::String): bool
-
- - - -
-Implementation - - -
public fun is_bool(json_string: &String): bool {
-    get_type(json_string) == JSON_VALUE_TYPE_BOOL
-}
-
- - - -
- - - -## Function `is_number` - - - -
public fun is_number(json_string: &string::String): bool
-
- - - -
-Implementation - - -
public fun is_number(json_string: &String): bool {
-    get_type(json_string) == JSON_VALUE_TYPE_NUMBER
-}
-
- - - -
- - - -## Function `is_string` - - - -
public fun is_string(json_string: &string::String): bool
-
- - - -
-Implementation - - -
public fun is_string(json_string: &String): bool {
-    get_type(json_string) == JSON_VALUE_TYPE_STRING
-}
-
- - - -
- - - -## Function `is_array` - - - -
public fun is_array(json_string: &string::String): bool
-
- - - -
-Implementation - - -
public fun is_array(json_string: &String): bool {
-    get_type(json_string) == JSON_VALUE_TYPE_ARRAY
-}
-
- - - -
- - - -## Function `is_object` - - - -
public fun is_object(json_string: &string::String): bool
-
- - -
-Implementation - - -
public fun is_object(json_string: &String): bool {
-    get_type(json_string) == JSON_VALUE_TYPE_OBJECT
-}
-
- - - -
- - - -## Function `as_bool` - - - -
public fun as_bool(json_value: json::JsonValue): bool
-
- - - -
-Implementation - - -
public fun as_bool(json_value: JsonValue): bool {
-    assert!(json_value.type == JSON_VALUE_TYPE_BOOL, ETYPE_MISMATCH);
-    *option::borrow(&json_value.value_bool)
-}
-
- - - -
- - - -## Function `as_number` - - - -
fun as_number(json_value: json::JsonValue): json::Number
-
- - - -
-Implementation - - -
fun as_number(json_value: JsonValue): Number {
-    assert!(json_value.type == JSON_VALUE_TYPE_NUMBER, ETYPE_MISMATCH);
-    *option::borrow(&json_value.value_number)
-}
-
- - - -
- - - -## Function `as_int` - - - -
public fun as_int(json_value: json::JsonValue): (bool, u256)
-
- - - -
-Implementation - - -
public fun as_int(json_value: JsonValue): (bool, u256) {// (signed, abs_val)
-    let number = as_number(json_value);
-    assert!(number.type == NUMBER_TYPE_INT, error::invalid_argument(ETYPE_MISMATCH));
-    (number.is_positive, number.value)
-}
-
- - - -
- - - -## Function `as_dec` - - - -
public fun as_dec(json_value: json::JsonValue): (bool, decimal256::Decimal256)
-
- - - -
-Implementation - - -
public fun as_dec(json_value: JsonValue): (bool, Decimal256) {// (signed, abs_val)
-    let number = as_number(json_value);
-    assert!(number.type == NUMBER_TYPE_DEC, error::invalid_argument(ETYPE_MISMATCH));
-    (number.is_positive, decimal256::new(number.value))
-}
-
- - - -
- - - -## Function `as_string` - - - -
public fun as_string(json_value: json::JsonValue): string::String
-
- - - -
-Implementation - - -
public fun as_string(json_value: JsonValue): String {
-    assert!(json_value.type == JSON_VALUE_TYPE_STRING, ETYPE_MISMATCH);
-    *option::borrow(&json_value.value_string)
-}
-
- - - -
- - - -## Function `unpack_elem` - - - -
public fun unpack_elem(elem: &json::JsonElem): (option::Option<string::String>, json::JsonValue)
-
- - - -
-Implementation - - -
public fun unpack_elem(elem: &JsonElem): (Option<String>, JsonValue) {
-    (elem.key, elem.value)
-}
-
- - - -
- - - -## Function `get_child_length` - - - -
public(friend) fun get_child_length(elem: &json::JsonElem): u64
-
- - - -
-Implementation - - -
public(friend) fun get_child_length(elem: &JsonElem): u64 {
-    elem.value.child_length
-}
-
- - - -
- - - -## Function `set_child_length` - - - -
public(friend) fun set_child_length(elem: &mut json::JsonElem, length: u64)
-
- - - -
-Implementation - - -
public(friend) fun set_child_length(elem: &mut JsonElem, length: u64) {
-    elem.value.child_length = length;
-}
-
- - - -
- - - -## Function `get_type` - - - -
public fun get_type(value: &string::String): u8
-
- - - -
-Implementation - - -
public native fun get_type(value: &String): u8;
-
- - - -
- - - -## Function `parse_bool` - - - -
fun parse_bool(value: string::String): bool
-
- - - -
-Implementation - - -
native fun parse_bool(value: String): bool;
-
- - - -
- - - -## Function `parse_number` - - - -
fun parse_number(value: string::String): json::Number
-
- - - -
-Implementation - - -
native fun parse_number(value: String): Number;
-
- - - -
- - - -## Function `parse_string` - - - -
fun parse_string(value: string::String): string::String
-
- - - -
-Implementation - - -
native fun parse_string(value: String): String;
-
- - - -
- - - -## Function `parse_array` - - - -
fun parse_array(value: string::String): vector<json::NativeArrayValue>
-
- - - -
-Implementation - - -
native fun parse_array(value: String): vector<NativeArrayValue>;
-
- - - -
- - - -## Function `parse_object` - - - -
fun parse_object(value: string::String): vector<json::NativeObjectValue>
-
- - - -
-Implementation - - -
native fun parse_object(value: String): vector<NativeObjectValue>;
-
- - - -
- - - -## Function `stringify_bool` - - - -
fun stringify_bool(value: bool): string::String
-
- - - -
-Implementation - - -
native fun stringify_bool(value: bool): String;
-
- - - -
- - - -## Function `stringify_number` - - - -
fun stringify_number(value: json::Number): string::String
-
- - - -
-Implementation - - -
native fun stringify_number(value: Number): String;
-
- - - -
- - - -## Function `stringify_string` - - - -
fun stringify_string(value: string::String): string::String
+
public fun marshal<T: drop>(value: &T): vector<u8>
 
-
-Implementation +##### Implementation -
native fun stringify_string(value: String): String;
+
native public fun marshal<T: drop>(value: &T): vector<u8>;
 
-
+ - +## Function `marshal_to_string` -## Function `stringify_array` +Marshal data to JSON string. +NOTE: key _type_ is converted to @type +NOTE: key _move_ is converted to move -
fun stringify_array(value: vector<string::String>): string::String
+
public fun marshal_to_string<T: drop>(value: &T): string::String
 
-
-Implementation +##### Implementation -
native fun stringify_array(value: vector<String>): String;
+
native public fun marshal_to_string<T: drop>(value: &T): String;
 
-
+ - +## Function `unmarshal` -## Function `stringify_object` +Unmarshal JSON bytes to the given struct. +NOTE: key @type is converted to _type_ +NOTE: key move is converted to _move_ -
fun stringify_object(value: vector<json::KeyValue>): string::String
+
public fun unmarshal<T: drop>(json: vector<u8>): T
 
-
-Implementation +##### Implementation -
native fun stringify_object(value: vector<KeyValue>): String;
+
native public fun unmarshal<T: drop>(json: vector<u8>): T;
 
- - - -
diff --git a/minitia_stdlib/doc/keccak.md b/minitia_stdlib/doc/keccak.md new file mode 100644 index 0000000..e1b4f62 --- /dev/null +++ b/minitia_stdlib/doc/keccak.md @@ -0,0 +1,36 @@ + + + +# Module `0x1::keccak` + +Cryptographic hashes: +- Keccak-256: see https://keccak.team/keccak.html + +In addition, SHA2-256 and SHA3-256 are available in std::hash. Note that SHA3-256 is a variant of Keccak: it is +NOT the same as Keccak-256. + + +- [Function `keccak256`](#0x1_keccak_keccak256) + + +
+ + + + + +## Function `keccak256` + +Returns the Keccak-256 hash of bytes. + + +
public fun keccak256(byte: vector<u8>): vector<u8>
+
+ + + +##### Implementation + + +
native public fun keccak256(byte: vector<u8>): vector<u8>;
+
diff --git a/minitia_stdlib/doc/managed_coin.md b/minitia_stdlib/doc/managed_coin.md index 50748ed..892ff61 100644 --- a/minitia_stdlib/doc/managed_coin.md +++ b/minitia_stdlib/doc/managed_coin.md @@ -10,9 +10,11 @@ By utilizing this current module, a developer can create his own coin and care l - [Resource `Capabilities`](#0x1_managed_coin_Capabilities) - [Constants](#@Constants_0) +- [Function `sudo_mint`](#0x1_managed_coin_sudo_mint) - [Function `initialize`](#0x1_managed_coin_initialize) - [Function `burn`](#0x1_managed_coin_burn) - [Function `mint`](#0x1_managed_coin_mint) +- [Function `mint_to`](#0x1_managed_coin_mint_to)
use 0x1::coin;
@@ -39,8 +41,7 @@ The resource is stored on the account that initialized coin CoinType
-Fields
+##### Fields
 
 
 
@@ -65,8 +66,6 @@ The resource is stored on the account that initialized coin CoinType - - ## Constants @@ -92,6 +91,49 @@ Metadata has no capabilities (burn/mint). + + +## Function `sudo_mint` + +Create new metadata coins and deposit them into dst_addr's account. + + +
public entry fun sudo_mint(account: &signer, dst_addr: address, metadata: object::Object<fungible_asset::Metadata>, amount: u64)
+
+ + + +##### Implementation + + +
public entry fun sudo_mint(
+    account: &signer,
+    dst_addr: address,
+    metadata: Object<Metadata>,
+    amount: u64
+) acquires Capabilities {
+    check_sudo(account);
+
+    let account_addr = signer::address_of(account);
+    assert!(
+        object::is_owner(metadata, account_addr),
+        error::not_found(EUNAUTHORIZED)
+    );
+
+    let object_addr = object::object_address(&metadata);
+    assert!(
+        exists<Capabilities>(object_addr),
+        error::not_found(ENO_CAPABILITIES)
+    );
+
+    let capabilities = borrow_global<Capabilities>(object_addr);
+    let fa = coin::mint(&capabilities.mint_cap, amount);
+    coin::sudo_deposit(dst_addr, fa);
+}
+
+ + + ## Function `initialize` @@ -105,8 +147,7 @@ Mint and Burn Capabilities will be stored under metadata in < -
-Implementation +##### Implementation
public entry fun initialize(
@@ -116,31 +157,29 @@ Mint and Burn Capabilities will be stored under metadata in <
     symbol: String,
     decimals: u8,
     icon_uri: String,
-    project_uri: String,
+    project_uri: String
 ) {
-    let (mint_cap, burn_cap, freeze_cap, extend_ref) = coin::initialize_and_generate_extend_ref (
-        account,
-        maximum_supply,
-        name,
-        symbol,
-        decimals,
-        icon_uri,
-        project_uri,
-    );
+    let (mint_cap, burn_cap, freeze_cap, extend_ref) =
+        coin::initialize_and_generate_extend_ref(
+            account,
+            maximum_supply,
+            name,
+            symbol,
+            decimals,
+            icon_uri,
+            project_uri
+        );
 
     let metadata_signer = object::generate_signer_for_extending(&extend_ref);
-    move_to(&metadata_signer, Capabilities {
-        mint_cap,
-        burn_cap,
-        freeze_cap,
-    });
+    move_to(
+        &metadata_signer,
+        Capabilities { mint_cap, burn_cap, freeze_cap }
+    );
 }
 
-
- ## Function `burn` @@ -153,26 +192,23 @@ Withdraw an amount of metadata coin from burn( - account: &signer, - metadata: Object<Metadata>, - amount: u64, + account: &signer, metadata: Object<Metadata>, amount: u64 ) acquires Capabilities { let account_addr = signer::address_of(account); assert!( object::is_owner(metadata, account_addr), - error::not_found(EUNAUTHORIZED), + error::not_found(EUNAUTHORIZED) ); - let object_addr = object::object_address(metadata); + let object_addr = object::object_address(&metadata); assert!( exists<Capabilities>(object_addr), - error::not_found(ENO_CAPABILITIES), + error::not_found(ENO_CAPABILITIES) ); let capabilities = borrow_global<Capabilities>(object_addr); @@ -184,48 +220,67 @@ Withdraw an amount of metadata coin from ## Function `mint` -Create new metadata coins and deposit them into dst_addr's account. +Create new metadata coins. -
public entry fun mint(account: &signer, dst_addr: address, metadata: object::Object<fungible_asset::Metadata>, amount: u64)
+
public fun mint(account: &signer, metadata: object::Object<fungible_asset::Metadata>, amount: u64): fungible_asset::FungibleAsset
 
-
-Implementation +##### Implementation -
public entry fun mint(
-    account: &signer,
-    dst_addr: address,
-    metadata: Object<Metadata>,
-    amount: u64,
-) acquires Capabilities {
+
public fun mint(
+    account: &signer, metadata: Object<Metadata>, amount: u64
+): FungibleAsset acquires Capabilities {
     let account_addr = signer::address_of(account);
 
     assert!(
         object::is_owner(metadata, account_addr),
-        error::not_found(EUNAUTHORIZED),
+        error::not_found(EUNAUTHORIZED)
     );
 
-    let object_addr = object::object_address(metadata);
+    let object_addr = object::object_address(&metadata);
     assert!(
         exists<Capabilities>(object_addr),
-        error::not_found(ENO_CAPABILITIES),
+        error::not_found(ENO_CAPABILITIES)
     );
 
     let capabilities = borrow_global<Capabilities>(object_addr);
-    coin::mint_to(&capabilities.mint_cap, dst_addr, amount);
+    coin::mint(&capabilities.mint_cap, amount)
 }
 
-
+ + +## Function `mint_to` + +Create new metadata coins and deposit them into dst_addr's account. + + +
public entry fun mint_to(account: &signer, dst_addr: address, metadata: object::Object<fungible_asset::Metadata>, amount: u64)
+
+ + + +##### Implementation + + +
public entry fun mint_to(
+    account: &signer,
+    dst_addr: address,
+    metadata: Object<Metadata>,
+    amount: u64
+) acquires Capabilities {
+    let fa = mint(account, metadata, amount);
+
+    coin::deposit(dst_addr, fa);
+}
+
diff --git a/minitia_stdlib/doc/math128.md b/minitia_stdlib/doc/math128.md index 73bf758..c625ed3 100644 --- a/minitia_stdlib/doc/math128.md +++ b/minitia_stdlib/doc/math128.md @@ -63,8 +63,7 @@ Return the largest of two numbers. -
-Implementation +##### Implementation
public fun max(a: u128, b: u128): u128 {
@@ -74,8 +73,6 @@ Return the largest of two numbers.
 
 
 
-
- ## Function `min` @@ -88,8 +85,7 @@ Return the smallest of two numbers. -
-Implementation +##### Implementation
public fun min(a: u128, b: u128): u128 {
@@ -99,8 +95,6 @@ Return the smallest of two numbers.
 
 
 
-
- ## Function `average` @@ -113,8 +107,7 @@ Return the average of two. -
-Implementation +##### Implementation
public fun average(a: u128, b: u128): u128 {
@@ -128,8 +121,6 @@ Return the average of two.
 
 
 
-
- ## Function `mul_div` @@ -142,8 +133,7 @@ Returns a * b / c going through u128 to prevent intermediate overflow -
-Implementation +##### Implementation
public fun mul_div(a: u128, b: u128, c: u128): u128 {
@@ -153,8 +143,6 @@ Returns a * b / c going through u128 to prevent intermediate overflow
 
 
 
-
- ## Function `clamp` @@ -167,8 +155,7 @@ Return x clamped to the interval [lower, upper]. -
-Implementation +##### Implementation
public fun clamp(x: u128, lower: u128, upper: u128): u128 {
@@ -178,8 +165,6 @@ Return x clamped to the interval [lower, upper].
 
 
 
-
- ## Function `pow` @@ -192,14 +177,12 @@ Return the value of n raised to power e -
-Implementation +##### Implementation
public fun pow(n: u128, e: u128): u128 {
-    if (e == 0) {
-        1
-    } else {
+    if (e == 0) { 1 }
+    else {
         let p = 1;
         while (e > 1) {
             if (e % 2 == 1) {
@@ -215,8 +198,6 @@ Return the value of n raised to power e
 
 
 
-
- ## Function `floor_log2` @@ -229,13 +210,15 @@ Returns floor(log2(x)) -
-Implementation +##### Implementation
public fun floor_log2(x: u128): u8 {
     let res = 0;
-    assert!(x != 0, std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2));
+    assert!(
+        x != 0,
+        std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2)
+    );
     // Effectively the position of the most significant set bit
     let n = 64;
     while (n > 0) {
@@ -251,8 +234,6 @@ Returns floor(log2(x))
 
 
 
-
- ## Function `log2` @@ -264,8 +245,7 @@ Returns floor(log2(x)) -
-Implementation +##### Implementation
public fun log2(x: u128): FixedPoint32 {
@@ -284,17 +264,18 @@ Returns floor(log2(x))
         x = (x * x) >> 32;
         // x is now in [1, 4)
         // if x in [2, 4) then log x = 1 + log (x / 2)
-        if (x >= (2 << 32)) { frac = frac + delta; x = x >> 1; };
+        if (x >= (2 << 32)) {
+            frac = frac + delta;
+            x = x >> 1;
+        };
         delta = delta >> 1;
     };
-    fixed_point32::create_from_raw_value (((integer_part as u64) << 32) + frac)
+    fixed_point32::create_from_raw_value(((integer_part as u64) << 32) + frac)
 }
 
-
- ## Function `log2_64` @@ -306,8 +287,7 @@ Returns floor(log2(x)) -
-Implementation +##### Implementation
public fun log2_64(x: u128): FixedPoint64 {
@@ -326,17 +306,18 @@ Returns floor(log2(x))
         x = (x * x) >> 63;
         // x is now in [1, 4)
         // if x in [2, 4) then log x = 1 + log (x / 2)
-        if (x >= (2 << 63)) { frac = frac + delta; x = x >> 1; };
+        if (x >= (2 << 63)) {
+            frac = frac + delta;
+            x = x >> 1;
+        };
         delta = delta >> 1;
     };
-    fixed_point64::create_from_raw_value (((integer_part as u128) << 64) + frac)
+    fixed_point64::create_from_raw_value(((integer_part as u128) << 64) + frac)
 }
 
-
- ## Function `sqrt` @@ -349,8 +330,7 @@ Returns square root of x, precisely floor(sqrt(x)) -
-Implementation +##### Implementation
public fun sqrt(x: u128): u128 {
@@ -375,8 +355,6 @@ Returns square root of x, precisely floor(sqrt(x))
 
 
 
-
- ## Function `ceil_div` @@ -388,8 +366,7 @@ Returns square root of x, precisely floor(sqrt(x)) -
-Implementation +##### Implementation
public fun ceil_div(x: u128, y: u128): u128 {
@@ -398,11 +375,6 @@ Returns square root of x, precisely floor(sqrt(x))
     if (x == 0) {
         assert!(y != 0, EDIVISION_BY_ZERO);
         0
-    }
-    else (x - 1) / y + 1
+    } else (x - 1) / y + 1
 }
 
- - - -
diff --git a/minitia_stdlib/doc/math64.md b/minitia_stdlib/doc/math64.md index b9884bb..6d866ba 100644 --- a/minitia_stdlib/doc/math64.md +++ b/minitia_stdlib/doc/math64.md @@ -34,7 +34,7 @@ Standard math utilities missing in the Move Language. -
const EDIVISION_BY_ZERO: u64 = 1;
+
const EDIVISION_BY_ZERO: u64 = 2;
 
@@ -61,8 +61,7 @@ Return the largest of two numbers. -
-Implementation +##### Implementation
public fun max(a: u64, b: u64): u64 {
@@ -72,8 +71,6 @@ Return the largest of two numbers.
 
 
 
-
- ## Function `min` @@ -86,8 +83,7 @@ Return the smallest of two numbers. -
-Implementation +##### Implementation
public fun min(a: u64, b: u64): u64 {
@@ -97,8 +93,6 @@ Return the smallest of two numbers.
 
 
 
-
- ## Function `average` @@ -111,8 +105,7 @@ Return the average of two. -
-Implementation +##### Implementation
public fun average(a: u64, b: u64): u64 {
@@ -126,8 +119,6 @@ Return the average of two.
 
 
 
-
- ## Function `mul_div` @@ -140,8 +131,7 @@ Returns a * b / c going through u128 to prevent intermediate overflow -
-Implementation +##### Implementation
public fun mul_div(a: u64, b: u64, c: u64): u64 {
@@ -151,8 +141,6 @@ Returns a * b / c going through u128 to prevent intermediate overflow
 
 
 
-
- ## Function `clamp` @@ -165,8 +153,7 @@ Return x clamped to the interval [lower, upper]. -
-Implementation +##### Implementation
public fun clamp(x: u64, lower: u64, upper: u64): u64 {
@@ -176,8 +163,6 @@ Return x clamped to the interval [lower, upper].
 
 
 
-
- ## Function `pow` @@ -190,14 +175,12 @@ Return the value of n raised to power e -
-Implementation +##### Implementation
public fun pow(n: u64, e: u64): u64 {
-    if (e == 0) {
-        1
-    } else {
+    if (e == 0) { 1 }
+    else {
         let p = 1;
         while (e > 1) {
             if (e % 2 == 1) {
@@ -213,8 +196,6 @@ Return the value of n raised to power e
 
 
 
-
- ## Function `floor_log2` @@ -227,13 +208,15 @@ Returns floor(lg2(x)) -
-Implementation +##### Implementation
public fun floor_log2(x: u64): u8 {
     let res = 0;
-    assert!(x != 0, std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2));
+    assert!(
+        x != 0,
+        std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2)
+    );
     // Effectively the position of the most significant set bit
     let n = 32;
     while (n > 0) {
@@ -249,8 +232,6 @@ Returns floor(lg2(x))
 
 
 
-
- ## Function `log2` @@ -262,18 +243,19 @@ Returns floor(lg2(x)) -
-Implementation +##### Implementation
public fun log2(x: u64): FixedPoint32 {
     let integer_part = floor_log2(x);
     // Normalize x to [1, 2) in fixed point 32.
-    let y = (if (x >= 1 << 32) {
-        x >> (integer_part - 32)
-    } else {
-        x << (32 - integer_part)
-    } as u128);
+    let y = (
+        if (x >= 1 << 32) {
+            x >> (integer_part - 32)
+        } else {
+            x << (32 - integer_part)
+        } as u128
+    );
     let frac = 0;
     let delta = 1 << 31;
     while (delta != 0) {
@@ -282,17 +264,18 @@ Returns floor(lg2(x))
         y = (y * y) >> 32;
         // x is now in [1, 4)
         // if x in [2, 4) then log x = 1 + log (x / 2)
-        if (y >= (2 << 32)) { frac = frac + delta; y = y >> 1; };
+        if (y >= (2 << 32)) {
+            frac = frac + delta;
+            y = y >> 1;
+        };
         delta = delta >> 1;
     };
-    fixed_point32::create_from_raw_value (((integer_part as u64) << 32) + frac)
+    fixed_point32::create_from_raw_value(((integer_part as u64) << 32) + frac)
 }
 
-
- ## Function `sqrt` @@ -305,8 +288,7 @@ Returns square root of x, precisely floor(sqrt(x)) -
-Implementation +##### Implementation
public fun sqrt(x: u64): u64 {
@@ -330,8 +312,6 @@ Returns square root of x, precisely floor(sqrt(x))
 
 
 
-
- ## Function `ceil_div` @@ -343,8 +323,7 @@ Returns square root of x, precisely floor(sqrt(x)) -
-Implementation +##### Implementation
public fun ceil_div(x: u64, y: u64): u64 {
@@ -353,11 +332,6 @@ Returns square root of x, precisely floor(sqrt(x))
     if (x == 0) {
         assert!(y != 0, EDIVISION_BY_ZERO);
         0
-    }
-    else (x - 1) / y + 1
+    } else (x - 1) / y + 1
 }
 
- - - -
diff --git a/minitia_stdlib/doc/multisig.md b/minitia_stdlib/doc/multisig.md index 6e11339..0a881a7 100644 --- a/minitia_stdlib/doc/multisig.md +++ b/minitia_stdlib/doc/multisig.md @@ -21,16 +21,10 @@ - [Function `get_config`](#0x1_multisig_get_config) - [Function `create_multisig_account`](#0x1_multisig_create_multisig_account) - [Function `create_proposal`](#0x1_multisig_create_proposal) +- [Function `create_proposal_with_json`](#0x1_multisig_create_proposal_with_json) - [Function `vote_proposal`](#0x1_multisig_vote_proposal) - [Function `execute_proposal`](#0x1_multisig_execute_proposal) - [Function `update_config`](#0x1_multisig_update_config) -- [Function `is_proposal_expired`](#0x1_multisig_is_proposal_expired) -- [Function `vote`](#0x1_multisig_vote) -- [Function `yes_vote_count`](#0x1_multisig_yes_vote_count) -- [Function `proposal_to_proposal_response`](#0x1_multisig_proposal_to_proposal_response) -- [Function `assert_member`](#0x1_multisig_assert_member) -- [Function `assert_config_version`](#0x1_multisig_assert_config_version) -- [Function `assert_proposal`](#0x1_multisig_assert_proposal)
use 0x1::block;
@@ -53,8 +47,8 @@
 ## Struct `Period`
 
 Period represents a time period with optional expiry conditions.
-If both height and timestamp are None, the period is considered to never expire.
-If both height and timestamp are set, and only one of them has expired, the period is considered expired.
+If both height and timestamp are None, the period is considered to never expire.
+If both height and timestamp are set, and only one of them has expired, the period is considered expired.
 
 
 
struct Period has copy, drop, store
@@ -62,8 +56,7 @@ If both height and timestamp are set, and only one of
 
 
 
-
-Fields +##### Fields
@@ -74,7 +67,7 @@ If both height and timestamp are set, and only one of
-timestamp: option::Option<u64> +timestamp: option::Option<u64>
@@ -82,8 +75,6 @@ If both height and timestamp are set, and only one of
-
- ## Resource `MultisigWallet` @@ -95,8 +86,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -139,8 +129,6 @@ If both height and timestamp are set, and only one of
-
- ## Struct `Proposal` @@ -152,8 +140,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -217,10 +204,20 @@ If both height and timestamp are set, and only one of
-
+
+is_json: bool +
+
+
+
+json_args: vector<string::String> +
+
+ +
+
- @@ -234,8 +231,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -266,8 +262,6 @@ If both height and timestamp are set, and only one of
-
- ## Struct `CreateProposalEvent` @@ -280,8 +274,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -336,8 +329,6 @@ If both height and timestamp are set, and only one of
-
- ## Struct `VoteProposalEvent` @@ -350,8 +341,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -382,8 +372,6 @@ If both height and timestamp are set, and only one of
-
- ## Struct `ExecuteProposalEvent` @@ -396,8 +384,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -422,8 +409,6 @@ If both height and timestamp are set, and only one of
-
- ## Struct `UpdateConfigEvent` @@ -436,8 +421,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -468,8 +452,6 @@ If both height and timestamp are set, and only one of
-
- ## Struct `ProposalResponse` @@ -481,8 +463,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -558,10 +539,20 @@ If both height and timestamp are set, and only one of
-
+
+is_json: bool +
+
+
+
+json_args: vector<string::String> +
+
+ +
+
- @@ -574,8 +565,7 @@ If both height and timestamp are set, and only one of -
-Fields +##### Fields
@@ -612,8 +602,6 @@ If both height and timestamp are set, and only one of
-
- ## Constants @@ -695,7 +683,7 @@ If both height and timestamp are set, and only one of -
const EPROPOSAL_NOT_FOUND: u64 = 8;
+
const EPROPOSAL_NOT_FOUND: u64 = 9;
 
@@ -730,21 +718,25 @@ If both height and timestamp are set, and only one of -
-Implementation +##### Implementation -
public fun get_proposal(multisig_addr: address, proposal_id: u64): ProposalResponse acquires MultisigWallet {
+
public fun get_proposal(
+    multisig_addr: address, proposal_id: u64
+): ProposalResponse acquires MultisigWallet {
     let multisig_wallet = borrow_global<MultisigWallet>(multisig_addr);
     let proposal = table::borrow(&multisig_wallet.proposals, proposal_id);
-    proposal_to_proposal_response(multisig_wallet, multisig_addr, proposal_id, proposal)
+    proposal_to_proposal_response(
+        multisig_wallet,
+        multisig_addr,
+        proposal_id,
+        proposal
+    )
 }
 
-
- ## Function `get_proposals` @@ -757,19 +749,36 @@ If both height and timestamp are set, and only one of -
-Implementation +##### Implementation -
public fun get_proposals(multisig_addr: address, start_after: Option<u64>, limit: u8): vector<ProposalResponse> acquires MultisigWallet {
-    if (limit > MAX_LIMIT) { limit = MAX_LIMIT };
+
public fun get_proposals(
+    multisig_addr: address, start_after: Option<u64>, limit: u8
+): vector<ProposalResponse> acquires MultisigWallet {
+    if (limit > MAX_LIMIT) {
+        limit = MAX_LIMIT
+    };
     let res: vector<ProposalResponse> = vector[];
     let multisig_wallet = borrow_global<MultisigWallet>(multisig_addr);
-    let iter = table::iter(&multisig_wallet.proposals, option::none(), start_after, 2);
+    let iter = table::iter(
+        &multisig_wallet.proposals,
+        option::none(),
+        start_after,
+        2
+    );
 
-    while (vector::length(&res) < (limit as u64) && table::prepare<u64, Proposal>(&mut iter)) {
-        let (proposal_id, proposal) = table::next<u64, Proposal>(&mut iter);
-        vector::push_back(&mut res, proposal_to_proposal_response(multisig_wallet, multisig_addr, proposal_id, proposal));
+    while (vector::length(&res) < (limit as u64)
+        && table::prepare<u64, Proposal>(iter)) {
+        let (proposal_id, proposal) = table::next<u64, Proposal>(iter);
+        vector::push_back(
+            &mut res,
+            proposal_to_proposal_response(
+                multisig_wallet,
+                multisig_addr,
+                proposal_id,
+                proposal
+            )
+        );
     };
 
     res
@@ -778,8 +787,6 @@ If both height and timestamp are set, and only one of
 
 
 
-
- ## Function `get_config` @@ -792,8 +799,7 @@ If both height and timestamp are set, and only one of -
-Implementation +##### Implementation
public fun get_config(multisig_addr: address): ConfigResponse acquires MultisigWallet {
@@ -804,15 +810,13 @@ If both height and timestamp are set, and only one of
         config_version: multisig_wallet.config_version,
         members: multisig_wallet.members,
         threshold: multisig_wallet.threshold,
-        max_voting_period: multisig_wallet.max_voting_period,
+        max_voting_period: multisig_wallet.max_voting_period
     }
 }
 
-
- ## Function `create_multisig_account` @@ -825,8 +829,7 @@ Create new multisig account -
-Implementation +##### Implementation
public entry fun create_multisig_account(
@@ -835,36 +838,47 @@ Create new multisig account
     members: vector<address>,
     threshold: u64,
     max_voting_period_height: Option<u64>,
-    max_voting_period_timestamp: Option<u64>,
+    max_voting_period_timestamp: Option<u64>
 ) {
     assert_member(&members, &signer::address_of(account));
-    assert!(vector::length(&members) >= threshold, error::invalid_argument(EINVALID_THRESHOLD));
-    let constructor_ref = object::create_named_object(account, *string::bytes(&name), false);
+    assert!(
+        vector::length(&members) >= threshold,
+        error::invalid_argument(EINVALID_THRESHOLD)
+    );
+    let constructor_ref = object::create_named_object(
+        account, *string::bytes(&name)
+    );
     let extend_ref = object::generate_extend_ref(&constructor_ref);
     let multisig_signer = object::generate_signer(&constructor_ref);
     let multisig_addr = signer::address_of(&multisig_signer);
     let max_voting_period = Period {
         height: max_voting_period_height,
-        timestamp: max_voting_period_timestamp,
+        timestamp: max_voting_period_timestamp
     };
     let members_map = simple_map::create<address, bool>();
-    vector::for_each(members, |member| simple_map::add(&mut members_map, member, true)); // just for check uniqueness
-
-    move_to(&multisig_signer, MultisigWallet {
-        extend_ref,
-        config_version: 1,
+    vector::for_each(
         members,
-        threshold,
-        max_voting_period,
-        proposals: table::new(),
-    });
+        |member| simple_map::add(&mut members_map, member, true)
+    ); // just for check uniqueness
+
+    move_to(
+        &multisig_signer,
+        MultisigWallet {
+            extend_ref,
+            config_version: 1,
+            members,
+            threshold,
+            max_voting_period,
+            proposals: table::new()
+        }
+    );
 
     event::emit<CreateMultisigAccountEvent>(
         CreateMultisigAccountEvent {
             multisig_addr,
             members,
             threshold,
-            max_voting_period,
+            max_voting_period
         }
     )
 }
@@ -872,8 +886,6 @@ Create new multisig account
 
 
 
-
- ## Function `create_proposal` @@ -886,8 +898,7 @@ Create new proposal -
-Implementation +##### Implementation
public entry fun create_proposal(
@@ -897,50 +908,64 @@ Create new proposal
     module_name: String,
     function_name: String,
     type_args: vector<String>,
-    args: vector<vector<u8>>,
+    args: vector<vector<u8>>
 ) acquires MultisigWallet {
-    let addr = signer::address_of(account);
-    let multisig_wallet = borrow_global_mut<MultisigWallet>(multisig_addr);
-    assert_member(&multisig_wallet.members, &addr);
-
-    let (height, timestamp) = get_block_info();
-    let config_version = multisig_wallet.config_version;
-
-    let proposal = Proposal {
+    create_proposal_internal(
+        account,
+        multisig_addr,
         module_address,
         module_name,
         function_name,
         type_args,
         args,
-        config_version,
-        proposal_height: height,
-        proposal_timestamp: timestamp,
-        votes: simple_map::create(),
-        status: 0, // in voting period
-    };
+        false,
+        vector[]
+    )
+}
+
- let proposal_id = table::length(&multisig_wallet.proposals) + 1; - table::add(&mut multisig_wallet.proposals, proposal_id, proposal); - event::emit<CreateProposalEvent>( - CreateProposalEvent { - multisig_addr, - proposal_id, - module_address, - module_name, - function_name, - type_args, - args, - config_version, - } + + + +## Function `create_proposal_with_json` + +Create new proposal + + +
public entry fun create_proposal_with_json(account: &signer, multisig_addr: address, module_address: address, module_name: string::String, function_name: string::String, type_args: vector<string::String>, args: vector<string::String>)
+
+ + + +##### Implementation + + +
public entry fun create_proposal_with_json(
+    account: &signer,
+    multisig_addr: address,
+    module_address: address,
+    module_name: String,
+    function_name: String,
+    type_args: vector<String>,
+    args: vector<String>
+) acquires MultisigWallet {
+    create_proposal_internal(
+        account,
+        multisig_addr,
+        module_address,
+        module_name,
+        function_name,
+        type_args,
+        vector[],
+        true,
+        args
     )
 }
 
-
- ## Function `vote_proposal` @@ -953,21 +978,26 @@ Vote proposal -
-Implementation +##### Implementation
public entry fun vote_proposal(
     account: &signer,
     multisig_addr: address,
     proposal_id: u64,
-    vote_yes: bool,
+    vote_yes: bool
 ) acquires MultisigWallet {
     let voter = signer::address_of(account);
     let multisig_wallet = borrow_global_mut<MultisigWallet>(multisig_addr);
     assert_member(&multisig_wallet.members, &voter);
 
-    assert!(table::contains(&multisig_wallet.proposals, proposal_id), error::invalid_argument(EPROPOSAL_NOT_FOUND));
+    assert!(
+        table::contains(
+            &multisig_wallet.proposals,
+            proposal_id
+        ),
+        error::invalid_argument(EPROPOSAL_NOT_FOUND)
+    );
     let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id);
 
     assert_config_version(multisig_wallet.config_version, proposal);
@@ -976,20 +1006,13 @@ Vote proposal
     vote(&mut proposal.votes, voter, vote_yes);
 
     event::emit<VoteProposalEvent>(
-        VoteProposalEvent {
-            multisig_addr,
-            proposal_id,
-            voter,
-            vote_yes,
-        }
+        VoteProposalEvent { multisig_addr, proposal_id, voter, vote_yes }
     )
 }
 
-
- ## Function `execute_proposal` @@ -1002,20 +1025,23 @@ Execute proposal -
-Implementation +##### Implementation
public entry fun execute_proposal(
-    account: &signer,
-    multisig_addr: address,
-    proposal_id: u64,
+    account: &signer, multisig_addr: address, proposal_id: u64
 ) acquires MultisigWallet {
     let executor = signer::address_of(account);
     let multisig_wallet = borrow_global_mut<MultisigWallet>(multisig_addr);
     assert_member(&multisig_wallet.members, &executor);
 
-    assert!(table::contains(&multisig_wallet.proposals, proposal_id), error::invalid_argument(EPROPOSAL_NOT_FOUND));
+    assert!(
+        table::contains(
+            &multisig_wallet.proposals,
+            proposal_id
+        ),
+        error::invalid_argument(EPROPOSAL_NOT_FOUND)
+    );
     let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id);
 
     assert_config_version(multisig_wallet.config_version, proposal);
@@ -1023,36 +1049,46 @@ Execute proposal
 
     // check passed
     assert!(
-        yes_vote_count(&proposal.votes, &multisig_wallet.members) >= multisig_wallet.threshold,
-        error::invalid_state(ENOT_PASS),
+        yes_vote_count(
+            &proposal.votes,
+            &multisig_wallet.members
+        ) >= multisig_wallet.threshold,
+        error::invalid_state(ENOT_PASS)
     );
 
-    let multisig_signer = &object::generate_signer_for_extending(&multisig_wallet.extend_ref);
-    move_execute(
-        multisig_signer,
-        proposal.module_address,
-        proposal.module_name,
-        proposal.function_name,
-        proposal.type_args,
-        proposal.args,
-    );
+    let multisig_signer =
+        &object::generate_signer_for_extending(&multisig_wallet.extend_ref);
+
+    if (!proposal.is_json) {
+        move_execute(
+            multisig_signer,
+            proposal.module_address,
+            proposal.module_name,
+            proposal.function_name,
+            proposal.type_args,
+            proposal.args
+        )
+    } else {
+        move_execute_with_json(
+            multisig_signer,
+            proposal.module_address,
+            proposal.module_name,
+            proposal.function_name,
+            proposal.type_args,
+            proposal.json_args
+        )
+    };
 
     proposal.status = 1; // executed
 
     event::emit<ExecuteProposalEvent>(
-        ExecuteProposalEvent {
-            multisig_addr,
-            proposal_id,
-            executor,
-        }
+        ExecuteProposalEvent { multisig_addr, proposal_id, executor }
     )
 }
 
-
- ## Function `update_config` @@ -1065,8 +1101,7 @@ Update config. Only execute by multisig wallet itself -
-Implementation +##### Implementation
public entry fun update_config(
@@ -1074,17 +1109,23 @@ Update config. Only execute by multisig wallet itself
     new_members: vector<address>,
     new_threshold: u64,
     new_max_voting_period_height: Option<u64>,
-    new_max_voting_period_timestamp: Option<u64>,
+    new_max_voting_period_timestamp: Option<u64>
 ) acquires MultisigWallet {
     let multisig_addr = signer::address_of(account);
     let multisig_wallet = borrow_global_mut<MultisigWallet>(multisig_addr);
 
-    assert!(vector::length(&new_members) >= new_threshold, error::invalid_argument(EINVALID_THRESHOLD));
+    assert!(
+        vector::length(&new_members) >= new_threshold,
+        error::invalid_argument(EINVALID_THRESHOLD)
+    );
     let new_members_map = simple_map::create<address, bool>();
-    vector::for_each(new_members, |member| simple_map::add(&mut new_members_map, member, true)); // just for check uniqueness
+    vector::for_each(
+        new_members,
+        |member| simple_map::add(&mut new_members_map, member, true)
+    ); // just for check uniqueness
     let new_max_voting_period = Period {
         height: new_max_voting_period_height,
-        timestamp: new_max_voting_period_timestamp,
+        timestamp: new_max_voting_period_timestamp
     };
 
     multisig_wallet.config_version = multisig_wallet.config_version + 1;
@@ -1097,240 +1138,8 @@ Update config. Only execute by multisig wallet itself
             multisig_addr,
             members: new_members,
             threshold: new_threshold,
-            max_voting_period: new_max_voting_period,
+            max_voting_period: new_max_voting_period
         }
     )
 }
 
- - - -
- - - -## Function `is_proposal_expired` - - - -
fun is_proposal_expired(max_period: &multisig::Period, proposal_height: u64, proposal_timestamp: u64): bool
-
- - - -
-Implementation - - -
fun is_proposal_expired(max_period: &Period, proposal_height: u64, proposal_timestamp: u64): bool {
-    let (height, timestamp) = get_block_info();
-    let expired_height = if (option::is_some(&max_period.height)) {
-        let max_voting_period_height = *option::borrow(&max_period.height);
-        (max_voting_period_height + proposal_height) >= height
-    } else {
-        false
-    };
-
-    let expired_timestamp = if (option::is_some(&max_period.timestamp)) {
-        let max_voting_period_timestamp = *option::borrow(&max_period.timestamp);
-        (max_voting_period_timestamp + proposal_timestamp) >= timestamp
-    } else {
-        false
-    };
-
-    expired_height || expired_timestamp
-}
-
- - - -
- - - -## Function `vote` - - - -
fun vote(votes: &mut simple_map::SimpleMap<address, bool>, voter: address, vote_yes: bool)
-
- - - -
-Implementation - - -
fun vote(votes: &mut SimpleMap<address, bool>, voter: address, vote_yes: bool) {
-    if (simple_map::contains_key(votes, &voter)) {
-        let vote = simple_map::borrow_mut(votes, &voter);
-        *vote = vote_yes;
-    } else {
-        simple_map::add(votes, voter, vote_yes);
-    };
-}
-
- - - -
- - - -## Function `yes_vote_count` - - - -
fun yes_vote_count(votes: &simple_map::SimpleMap<address, bool>, members: &vector<address>): u64
-
- - - -
-Implementation - - -
fun yes_vote_count(votes: &SimpleMap<address, bool>, members: &vector<address>): u64 {
-    let yes_count = 0;
-    vector::for_each_ref(members, |member| {
-        if (simple_map::contains_key(votes, member) && *simple_map::borrow(votes, member)) {
-            yes_count = yes_count + 1;
-        }
-    });
-
-    yes_count
-}
-
- - - -
- - - -## Function `proposal_to_proposal_response` - - - -
fun proposal_to_proposal_response(multisig_wallet: &multisig::MultisigWallet, multisig_addr: address, proposal_id: u64, proposal: &multisig::Proposal): multisig::ProposalResponse
-
- - - -
-Implementation - - -
fun proposal_to_proposal_response(
-    multisig_wallet: &MultisigWallet,
-    multisig_addr: address,
-    proposal_id: u64,
-    proposal: &Proposal,
-): ProposalResponse {
-    let status_index = proposal.status;
-    let is_expired = is_proposal_expired(&multisig_wallet.max_voting_period, proposal.proposal_height, proposal.proposal_timestamp);
-    let yes_vote_count = yes_vote_count(&proposal.votes, &multisig_wallet.members);
-    if (status_index == 0 && is_expired) {
-        status_index = 2
-    };
-
-    ProposalResponse {
-        multisig_addr,
-        proposal_id,
-        module_address: proposal.module_address,
-        module_name: proposal.module_name,
-        function_name: proposal.function_name,
-        type_args: proposal.type_args,
-        args: proposal.args,
-        proposal_height: proposal.proposal_height,
-        proposal_timestamp: proposal.proposal_timestamp,
-        config_version: proposal.config_version,
-        yes_vote_count,
-        status: string::utf8(*vector::borrow(&STATUS, (status_index as u64))),
-    }
-}
-
- - - -
- - - -## Function `assert_member` - - - -
fun assert_member(members: &vector<address>, member: &address)
-
- - - -
-Implementation - - -
inline fun assert_member(members: &vector<address>, member: &address) {
-    assert!(vector::contains(members, member), error::permission_denied(ENOT_MEMBER))
-}
-
- - - -
- - - -## Function `assert_config_version` - - - -
fun assert_config_version(multisig_wallet_config_version: u64, execute_proposal: &multisig::Proposal)
-
- - - -
-Implementation - - -
inline fun assert_config_version(multisig_wallet_config_version: u64, execute_proposal: &Proposal) {
-    assert!(multisig_wallet_config_version == execute_proposal.config_version, error::invalid_state(EOLD_CONFIG_VERSION))
-}
-
- - - -
- - - -## Function `assert_proposal` - - - -
fun assert_proposal(max_voting_period: &multisig::Period, proposal: &multisig::Proposal)
-
- - - -
-Implementation - - -
inline fun assert_proposal(max_voting_period: &Period, proposal: &Proposal) {
-    assert!(proposal.status == 0, error::invalid_state(EINVALID_PROPOSAL_STATUS));
-    assert!(
-        !is_proposal_expired(
-            max_voting_period,
-            proposal.proposal_height,
-            proposal.proposal_timestamp,
-        ),
-        error::invalid_state(EPROPOSAL_EXPIRED),
-    );
-}
-
- - - -
diff --git a/minitia_stdlib/doc/nft.md b/minitia_stdlib/doc/nft.md index d64051e..0216b6b 100644 --- a/minitia_stdlib/doc/nft.md +++ b/minitia_stdlib/doc/nft.md @@ -16,14 +16,12 @@ nft are: - [Struct `MutationEvent`](#0x1_nft_MutationEvent) - [Struct `NftInfoResponse`](#0x1_nft_NftInfoResponse) - [Constants](#@Constants_0) -- [Function `create_common`](#0x1_nft_create_common) - [Function `create`](#0x1_nft_create) - [Function `create_nft_address`](#0x1_nft_create_nft_address) - [Function `create_nft_seed`](#0x1_nft_create_nft_seed) - [Function `generate_mutator_ref`](#0x1_nft_generate_mutator_ref) - [Function `generate_burn_ref`](#0x1_nft_generate_burn_ref) - [Function `address_from_burn_ref`](#0x1_nft_address_from_burn_ref) -- [Function `borrow`](#0x1_nft_borrow) - [Function `is_nft`](#0x1_nft_is_nft) - [Function `creator`](#0x1_nft_creator) - [Function `collection_name`](#0x1_nft_collection_name) @@ -34,7 +32,6 @@ nft are: - [Function `royalty`](#0x1_nft_royalty) - [Function `nft_info`](#0x1_nft_nft_info) - [Function `nft_infos`](#0x1_nft_nft_infos) -- [Function `borrow_mut`](#0x1_nft_borrow_mut) - [Function `burn`](#0x1_nft_burn) - [Function `set_description`](#0x1_nft_set_description) - [Function `set_uri`](#0x1_nft_set_uri) @@ -65,8 +62,7 @@ Represents the common fields to all nfts. -
-Fields +##### Fields
@@ -99,8 +95,6 @@ Represents the common fields to all nfts.
-
- ## Struct `BurnRef` @@ -115,8 +109,7 @@ a small optimization to support either and take a fixed amount of 34-bytes. -
-Fields +##### Fields
@@ -129,8 +122,6 @@ a small optimization to support either and take a fixed amount of 34-bytes.
-
- ## Struct `MutatorRef` @@ -143,8 +134,7 @@ This enables mutating descritpion and URI by higher level services. -
-Fields +##### Fields
@@ -157,8 +147,6 @@ This enables mutating descritpion and URI by higher level services.
-
- ## Struct `MutationEvent` @@ -173,8 +161,7 @@ directly understand the behavior in a writeset. -
-Fields +##### Fields
@@ -205,8 +192,6 @@ directly understand the behavior in a writeset.
-
- ## Struct `NftInfoResponse` @@ -219,8 +204,7 @@ Struct for nft info query response -
-Fields +##### Fields
@@ -251,8 +235,6 @@ Struct for nft info query response
-
- ## Constants @@ -306,6 +288,16 @@ The field being changed is not mutable + + +The provided token id is invalid + + +
const EINVALID_TOKEN_ID: u64 = 9;
+
+ + + The nft does not exist @@ -364,58 +356,6 @@ The query length is over the maximum length - - -## Function `create_common` - - - -
fun create_common(constructor_ref: &object::ConstructorRef, creator_address: address, collection_name: string::String, description: string::String, token_id: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String)
-
- - - -
-Implementation - - -
inline fun create_common(
-    constructor_ref: &ConstructorRef,
-    creator_address: address,
-    collection_name: String,
-    description: String,
-    token_id: String,
-    royalty: Option<Royalty>,
-    uri: String,
-) {
-    assert!(string::length(&token_id) <= MAX_NFT_TOKEN_ID_LENGTH, error::out_of_range(ENFT_TOKEN_ID_TOO_LONG));
-    assert!(string::length(&description) <= MAX_DESCRIPTION_LENGTH, error::out_of_range(EDESCRIPTION_TOO_LONG));
-    assert!(string::length(&uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
-
-    let object_signer = object::generate_signer(constructor_ref);
-
-    let collection_addr = collection::create_collection_address(creator_address, &collection_name);
-    let collection = object::address_to_object<Collection>(collection_addr);
-    collection::increment_supply(collection, token_id, signer::address_of(&object_signer));
-
-    let nft = Nft {
-        collection,
-        description,
-        token_id,
-        uri,
-    };
-    move_to(&object_signer, nft);
-
-    if (option::is_some(&royalty)) {
-        royalty::init(constructor_ref, option::extract(&mut royalty))
-    };
-}
-
- - - -
- ## Function `create` @@ -429,8 +369,7 @@ additional specialization. -
-Implementation +##### Implementation
public fun create(
@@ -439,21 +378,27 @@ additional specialization.
     description: String,
     token_id: String,
     royalty: Option<Royalty>,
-    uri: String,
+    uri: String
 ): ConstructorRef {
     let creator_address = signer::address_of(creator);
     let seed = create_nft_seed(&collection_name, &token_id);
 
-    let constructor_ref = object::create_named_object(creator, seed, true);
-    create_common(&constructor_ref, creator_address, collection_name, description, token_id, royalty, uri);
+    let constructor_ref = object::create_deletable_named_object(creator, seed);
+    create_common(
+        &constructor_ref,
+        creator_address,
+        collection_name,
+        description,
+        token_id,
+        royalty,
+        uri
+    );
     constructor_ref
 }
 
-
- ## Function `create_nft_address` @@ -466,19 +411,21 @@ Generates the nft's address based upon the creator's address, the collection's n -
-Implementation +##### Implementation -
public fun create_nft_address(creator: address, collection: &String, token_id: &String): address {
-    object::create_object_address(creator, create_nft_seed(collection, token_id))
+
public fun create_nft_address(
+    creator: address, collection: &String, token_id: &String
+): address {
+    object::create_object_address(
+        &creator,
+        create_nft_seed(collection, token_id)
+    )
 }
 
-
- ## Function `create_nft_seed` @@ -491,12 +438,14 @@ Named objects are derived from a seed, the nft's seed is its token_id appended t -
-Implementation +##### Implementation
public fun create_nft_seed(collection: &String, token_id: &String): vector<u8> {
-    assert!(string::length(token_id) <= MAX_NFT_TOKEN_ID_LENGTH, error::out_of_range(ENFT_TOKEN_ID_TOO_LONG));
+    assert!(
+        string::length(token_id) <= MAX_NFT_TOKEN_ID_LENGTH,
+        error::out_of_range(ENFT_TOKEN_ID_TOO_LONG)
+    );
     let seed = *string::bytes(collection);
     vector::append(&mut seed, b"::");
     vector::append(&mut seed, *string::bytes(token_id));
@@ -506,8 +455,6 @@ Named objects are derived from a seed, the nft's seed is its token_id appended t
 
 
 
-
- ## Function `generate_mutator_ref` @@ -520,20 +467,17 @@ Creates a MutatorRef, which gates the ability to mutate any fields that support -
-Implementation +##### Implementation
public fun generate_mutator_ref(ref: &ConstructorRef): MutatorRef {
     let object = object::object_from_constructor_ref<Nft>(ref);
-    MutatorRef { self: object::object_address(object) }
+    MutatorRef { self: object::object_address(&object) }
 }
 
-
- ## Function `generate_burn_ref` @@ -546,8 +490,7 @@ Creates a BurnRef, which gates the ability to burn the given nft. -
-Implementation +##### Implementation
public fun generate_burn_ref(ref: &ConstructorRef): BurnRef {
@@ -558,8 +501,6 @@ Creates a BurnRef, which gates the ability to burn the given nft.
 
 
 
-
- ## Function `address_from_burn_ref` @@ -572,8 +513,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun address_from_burn_ref(ref: &BurnRef): address {
@@ -583,37 +523,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- - - -## Function `borrow` - - - -
fun borrow<T: key>(nft: object::Object<T>): &nft::Nft
-
- - - -
-Implementation - - -
inline fun borrow<T: key>(nft: Object<T>): &Nft acquires Nft {
-    let nft_address = object::object_address(nft);
-    assert!(
-        exists<Nft>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-    borrow_global<Nft>(nft_address)
-}
-
- - - -
- ## Function `is_nft` @@ -626,8 +535,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun is_nft(object_address: address): bool {
@@ -637,8 +545,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `creator` @@ -651,8 +557,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun creator<T: key>(nft: Object<T>): address acquires Nft {
@@ -662,8 +567,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `collection_name` @@ -676,8 +579,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun collection_name<T: key>(nft: Object<T>): String acquires Nft {
@@ -687,8 +589,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `collection_object` @@ -701,8 +601,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun collection_object<T: key>(nft: Object<T>): Object<Collection> acquires Nft {
@@ -712,8 +611,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `description` @@ -726,8 +623,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun description<T: key>(nft: Object<T>): String acquires Nft {
@@ -737,8 +633,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `token_id` @@ -751,8 +645,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun token_id<T: key>(nft: Object<T>): String acquires Nft {
@@ -762,8 +655,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `uri` @@ -776,8 +667,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun uri<T: key>(nft: Object<T>): String acquires Nft {
@@ -787,8 +677,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `royalty` @@ -801,8 +689,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun royalty<T: key>(nft: Object<T>): Option<Royalty> acquires Nft {
@@ -813,8 +700,10 @@ Extracts the nfts address from a BurnRef.
     } else {
         let creator = creator(nft);
         let collection_name = collection_name(nft);
-        let collection_address = collection::create_collection_address(creator, &collection_name);
-        let collection = object::address_to_object<collection::Collection>(collection_address);
+        let collection_address =
+            collection::create_collection_address(creator, &collection_name);
+        let collection =
+            object::address_to_object<collection::Collection>(collection_address);
         royalty::get(collection)
     }
 }
@@ -822,8 +711,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `nft_info` @@ -836,8 +723,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun nft_info(nft: Object<Nft>): NftInfoResponse acquires Nft {
@@ -846,15 +732,13 @@ Extracts the nfts address from a BurnRef.
         collection: nft.collection,
         description: nft.description,
         token_id: nft.token_id,
-        uri: nft.uri,
+        uri: nft.uri
     }
 }
 
-
- ## Function `nft_infos` @@ -867,13 +751,15 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun nft_infos(nfts: vector<Object<Nft>>): vector<NftInfoResponse> acquires Nft {
     let len = vector::length(&nfts);
-    assert!(len <= MAX_QUERY_LENGTH, error::invalid_argument(EQUERY_LENGTH_TOO_LONG));
+    assert!(
+        len <= MAX_QUERY_LENGTH,
+        error::invalid_argument(EQUERY_LENGTH_TOO_LONG)
+    );
     let index = 0;
     let res: vector<NftInfoResponse> = vector[];
     while (index < len) {
@@ -888,36 +774,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- - - -## Function `borrow_mut` - - - -
fun borrow_mut(mutator_ref: &nft::MutatorRef): &mut nft::Nft
-
- - - -
-Implementation - - -
inline fun borrow_mut(mutator_ref: &MutatorRef): &mut Nft acquires Nft {
-    assert!(
-        exists<Nft>(mutator_ref.self),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-    borrow_global_mut<Nft>(mutator_ref.self)
-}
-
- - - -
- ## Function `burn` @@ -929,8 +785,7 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun burn(burn_ref: BurnRef) acquires Nft {
@@ -942,12 +797,7 @@ Extracts the nfts address from a BurnRef.
         royalty::delete(addr)
     };
 
-    let Nft {
-        collection,
-        description: _,
-        token_id,
-        uri: _,
-    } = move_from<Nft>(addr);
+    let Nft { collection, description: _, token_id, uri: _ } = move_from<Nft>(addr);
 
     collection::decrement_supply(collection, token_id, addr);
 }
@@ -955,8 +805,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `set_description` @@ -968,12 +816,16 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation -
public fun set_description(mutator_ref: &MutatorRef, description: String) acquires Nft {
-    assert!(string::length(&description) <= MAX_DESCRIPTION_LENGTH, error::out_of_range(EDESCRIPTION_TOO_LONG));
+
public fun set_description(
+    mutator_ref: &MutatorRef, description: String
+) acquires Nft {
+    assert!(
+        string::length(&description) <= MAX_DESCRIPTION_LENGTH,
+        error::out_of_range(EDESCRIPTION_TOO_LONG)
+    );
     let nft = borrow_mut(mutator_ref);
     event::emit(
         MutationEvent {
@@ -981,7 +833,7 @@ Extracts the nfts address from a BurnRef.
             mutated_field_name: string::utf8(b"description"),
             old_value: nft.description,
             new_value: description
-        },
+        }
     );
     nft.description = description;
 }
@@ -989,8 +841,6 @@ Extracts the nfts address from a BurnRef.
 
 
 
-
- ## Function `set_uri` @@ -1002,25 +852,23 @@ Extracts the nfts address from a BurnRef. -
-Implementation +##### Implementation
public fun set_uri(mutator_ref: &MutatorRef, uri: String) acquires Nft {
-    assert!(string::length(&uri) <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
+    assert!(
+        string::length(&uri) <= MAX_URI_LENGTH,
+        error::out_of_range(EURI_TOO_LONG)
+    );
     let nft = borrow_mut(mutator_ref);
     event::emit(
         MutationEvent {
             nft: mutator_ref.self,
             mutated_field_name: string::utf8(b"uri"),
             old_value: nft.uri,
-            new_value: uri,
-        },
+            new_value: uri
+        }
     );
     nft.uri = uri;
 }
 
- - - -
diff --git a/minitia_stdlib/doc/object.md b/minitia_stdlib/doc/object.md index c5598a5..94710a9 100644 --- a/minitia_stdlib/doc/object.md +++ b/minitia_stdlib/doc/object.md @@ -35,16 +35,16 @@ make it so that a reference to a global object can be returned from a function. - [Constants](#@Constants_0) - [Function `address_to_object`](#0x1_object_address_to_object) - [Function `is_object`](#0x1_object_is_object) +- [Function `object_exists`](#0x1_object_object_exists) - [Function `create_object_address`](#0x1_object_create_object_address) - [Function `create_user_derived_object_address`](#0x1_object_create_user_derived_object_address) - [Function `create_guid_object_address`](#0x1_object_create_guid_object_address) -- [Function `exists_at`](#0x1_object_exists_at) - [Function `object_address`](#0x1_object_object_address) - [Function `convert`](#0x1_object_convert) - [Function `create_named_object`](#0x1_object_create_named_object) +- [Function `create_deletable_named_object`](#0x1_object_create_deletable_named_object) - [Function `create_user_derived_object`](#0x1_object_create_user_derived_object) - [Function `create_object`](#0x1_object_create_object) -- [Function `create_object_internal`](#0x1_object_create_object_internal) - [Function `generate_delete_ref`](#0x1_object_generate_delete_ref) - [Function `generate_extend_ref`](#0x1_object_generate_extend_ref) - [Function `generate_transfer_ref`](#0x1_object_generate_transfer_ref) @@ -66,7 +66,6 @@ make it so that a reference to a global object can be returned from a function. - [Function `transfer`](#0x1_object_transfer) - [Function `transfer_raw`](#0x1_object_transfer_raw) - [Function `transfer_to_object`](#0x1_object_transfer_to_object) -- [Function `verify_ungated_and_descendant`](#0x1_object_verify_ungated_and_descendant) - [Function `ungated_transfer_allowed`](#0x1_object_ungated_transfer_allowed) - [Function `owner`](#0x1_object_owner) - [Function `is_owner`](#0x1_object_is_owner) @@ -99,8 +98,7 @@ Tombstone is version store for deleted objects with version -
-Fields +##### Fields
@@ -113,8 +111,6 @@ Tombstone is version store for deleted objects with version
-
- ## Resource `ObjectCore` @@ -127,8 +123,7 @@ The core of the object model that defines ownership, transferability, and events -
-Fields +##### Fields
@@ -154,8 +149,6 @@ The core of the object model that defines ownership, transferability, and events
-
- ## Struct `Object` @@ -171,8 +164,7 @@ can remove it from storage at any point in time. -
-Fields +##### Fields
@@ -185,8 +177,6 @@ can remove it from storage at any point in time.
-
- ## Struct `ConstructorRef` @@ -199,8 +189,7 @@ This is a one time ability given to the creator to configure the object as neces -
-Fields +##### Fields
@@ -214,7 +203,7 @@ This is a one time ability given to the creator to configure the object as neces can_delete: bool
- True if the object can be deleted. Named objects are not deletable. + True if the object can be deleted.
version: u64 @@ -225,8 +214,6 @@ This is a one time ability given to the creator to configure the object as neces
-
- ## Struct `DeleteRef` @@ -239,8 +226,7 @@ Used to remove an object from storage. -
-Fields +##### Fields
@@ -259,8 +245,6 @@ Used to remove an object from storage.
-
- ## Struct `ExtendRef` @@ -273,8 +257,7 @@ Used to create events or move additional resources into object storage. -
-Fields +##### Fields
@@ -293,8 +276,6 @@ Used to create events or move additional resources into object storage.
-
- ## Struct `TransferRef` @@ -307,8 +288,7 @@ Used to create LinearTransferRef, hence ownership transfer. -
-Fields +##### Fields
@@ -327,8 +307,6 @@ Used to create LinearTransferRef, hence ownership transfer.
-
- ## Struct `LinearTransferRef` @@ -342,8 +320,7 @@ the current owner. -
-Fields +##### Fields
@@ -368,8 +345,6 @@ the current owner.
-
- ## Struct `DeriveRef` @@ -382,8 +357,7 @@ Used to create derived objects from a given objects. -
-Fields +##### Fields
@@ -402,8 +376,6 @@ Used to create derived objects from a given objects.
-
- ## Struct `CreateEvent` @@ -417,8 +389,7 @@ Emitted at the object creation. -
-Fields +##### Fields
@@ -443,8 +414,6 @@ Emitted at the object creation.
-
- ## Struct `TransferEvent` @@ -458,8 +427,7 @@ Emitted whenever the object's owner field is changed. -
-Fields +##### Fields
@@ -484,8 +452,6 @@ Emitted whenever the object's owner field is changed.
-
- ## Constants @@ -653,21 +619,24 @@ Produces an ObjectId from the given address. This is not verified. -
-Implementation +##### Implementation
public fun address_to_object<T: key>(object: address): Object<T> {
-    assert!(exists<ObjectCore>(object), error::not_found(EOBJECT_DOES_NOT_EXIST));
-    assert!(exists_at<T>(object), error::not_found(ERESOURCE_DOES_NOT_EXIST));
+    assert!(
+        exists<ObjectCore>(object),
+        error::not_found(EOBJECT_DOES_NOT_EXIST)
+    );
+    assert!(
+        exists_at<T>(object),
+        error::not_found(ERESOURCE_DOES_NOT_EXIST)
+    );
     Object<T> { inner: object }
 }
 
-
- ## Function `is_object` @@ -680,8 +649,7 @@ Returns true if there exists an object or the remnants of an object. -
-Implementation +##### Implementation
public fun is_object(object: address): bool {
@@ -691,7 +659,27 @@ Returns true if there exists an object or the remnants of an object.
 
 
 
-
+ + +## Function `object_exists` + +Returns true if there exists an object with resource T. + + +
public fun object_exists<T: key>(object: address): bool
+
+ + + +##### Implementation + + +
public fun object_exists<T: key>(object: address): bool {
+    exists<ObjectCore>(object) && exists_at<T>(object)
+}
+
+ + @@ -700,17 +688,16 @@ Returns true if there exists an object or the remnants of an object. Derives an object address from source material: sha3_256([creator address | seed | 0xFE]). -
public fun create_object_address(source: address, seed: vector<u8>): address
+
public fun create_object_address(source: &address, seed: vector<u8>): address
 
-
-Implementation +##### Implementation -
public fun create_object_address(source: address, seed: vector<u8>): address {
-    let bytes = bcs::to_bytes(&source);
+
public fun create_object_address(source: &address, seed: vector<u8>): address {
+    let bytes = bcs::to_bytes(source);
     vector::append(&mut bytes, seed);
     vector::push_back(&mut bytes, OBJECT_FROM_SEED_ADDRESS_SCHEME);
     from_bcs::to_address(hash::sha3_256(bytes))
@@ -719,8 +706,6 @@ Derives an object address from source material: sha3_256([creator address | seed
 
 
 
-
- ## Function `create_user_derived_object_address` @@ -733,11 +718,12 @@ Derives an object address from the source address and an object: sha3_256([sourc -
-Implementation +##### Implementation -
public fun create_user_derived_object_address(source: address, derive_from: address): address {
+
public fun create_user_derived_object_address(
+    source: address, derive_from: address
+): address {
     let bytes = bcs::to_bytes(&source);
     vector::append(&mut bytes, bcs::to_bytes(&derive_from));
     vector::push_back(&mut bytes, OBJECT_DERIVED_SCHEME);
@@ -747,8 +733,6 @@ Derives an object address from the source address and an object: sha3_256([sourc
 
 
 
-
- ## Function `create_guid_object_address` @@ -761,11 +745,12 @@ Derives an object from an Account GUID. -
-Implementation +##### Implementation -
public fun create_guid_object_address(source: address, creation_num: u64): address {
+
public fun create_guid_object_address(
+    source: address, creation_num: u64
+): address {
     let id = guid::create_id(source, creation_num);
     let bytes = bcs::to_bytes(&id);
     vector::push_back(&mut bytes, OBJECT_FROM_GUID_ADDRESS_SCHEME);
@@ -775,30 +760,6 @@ Derives an object from an Account GUID.
 
 
 
-
- - - -## Function `exists_at` - - - -
fun exists_at<T: key>(object: address): bool
-
- - - -
-Implementation - - -
native fun exists_at<T: key>(object: address): bool;
-
- - - -
- ## Function `object_address` @@ -806,24 +767,21 @@ Derives an object from an Account GUID. Returns the address of within an ObjectId. -
public fun object_address<T: key>(object: object::Object<T>): address
+
public fun object_address<T: key>(object: &object::Object<T>): address
 
-
-Implementation +##### Implementation -
public fun object_address<T: key>(object: Object<T>): address {
+
public fun object_address<T: key>(object: &Object<T>): address {
     object.inner
 }
 
-
- ## Function `convert` @@ -836,8 +794,7 @@ Convert Object to Object. -
-Implementation +##### Implementation
public fun convert<X: key, Y: key>(object: Object<X>): Object<Y> {
@@ -847,147 +804,121 @@ Convert Object to Object.
 
 
 
-
- ## Function `create_named_object` -Create a new named object and return the ConstructorRef. Named objects can be queried globally -by knowing the user generated seed used to create them. Named objects cannot be deleted. +Create a new named object and return the ConstructorRef. +Named objects can be queried globally by knowing the user generated seed used to create them. -
public fun create_named_object(creator: &signer, seed: vector<u8>, can_delete: bool): object::ConstructorRef
+
public fun create_named_object(creator: &signer, seed: vector<u8>): object::ConstructorRef
 
-
-Implementation +##### Implementation -
public fun create_named_object(creator: &signer, seed: vector<u8>, can_delete: bool): ConstructorRef acquires Tombstone {
+
public fun create_named_object(
+    creator: &signer, seed: vector<u8>
+): ConstructorRef acquires Tombstone {
     let creator_address = signer::address_of(creator);
-    let obj_addr = create_object_address(creator_address, seed);
-    create_object_internal(creator_address, obj_addr, can_delete)
+    let obj_addr = create_object_address(&creator_address, seed);
+    create_object_internal(creator_address, obj_addr, false)
 }
 
-
+ - - -## Function `create_user_derived_object` +## Function `create_deletable_named_object` -Create a new object whose address is derived based on the creator account address and another object. -Derivde objects, similar to named objects, cannot be deleted. +Create a new object that can be deleted and return the ConstructorRef. +Named objects can be queried globally by knowing the user generated seed used to create them. -
public(friend) fun create_user_derived_object(creator_address: address, derive_ref: &object::DeriveRef, can_delete: bool): object::ConstructorRef
+
public fun create_deletable_named_object(creator: &signer, seed: vector<u8>): object::ConstructorRef
 
-
-Implementation +##### Implementation -
public(friend) fun create_user_derived_object(creator_address: address, derive_ref: &DeriveRef, can_delete: bool): ConstructorRef acquires Tombstone {
-    let obj_addr = create_user_derived_object_address(creator_address, derive_ref.self);
-    create_object_internal(creator_address, obj_addr, can_delete)
+
public fun create_deletable_named_object(
+    creator: &signer, seed: vector<u8>
+): ConstructorRef acquires Tombstone {
+    let creator_address = signer::address_of(creator);
+    let obj_addr = create_object_address(&creator_address, seed);
+    create_object_internal(creator_address, obj_addr, true)
 }
 
-
- - + -## Function `create_object` +## Function `create_user_derived_object` -Create a new object by generating a random unique address based on transaction hash. -The unique address is computed sha3_256([transaction hash | auid counter | 0xFB]). +Create a new object whose address is derived based on the creator account address and another object. +Derivde objects, similar to named objects, cannot be deleted. -
public fun create_object(owner_address: address, can_delete: bool): object::ConstructorRef
+
public(friend) fun create_user_derived_object(creator_address: address, derive_ref: &object::DeriveRef, can_delete: bool): object::ConstructorRef
 
-
-Implementation +##### Implementation -
public fun create_object(owner_address: address, can_delete: bool): ConstructorRef acquires Tombstone {
-    let unique_address = transaction_context::generate_unique_address();
-    create_object_internal(owner_address, unique_address, can_delete)
+
public(friend) fun create_user_derived_object(
+    creator_address: address, derive_ref: &DeriveRef, can_delete: bool
+): ConstructorRef acquires Tombstone {
+    let obj_addr =
+        create_user_derived_object_address(creator_address, derive_ref.self);
+    create_object_internal(
+        creator_address,
+        obj_addr,
+        can_delete
+    )
 }
 
-
- - + -## Function `create_object_internal` +## Function `create_object` +Create a new object by generating a random unique address based on transaction hash. +The unique address is computed sha3_256([transaction hash | auid counter | 0xFB]). -
fun create_object_internal(creator_address: address, object: address, can_delete: bool): object::ConstructorRef
+
public fun create_object(owner_address: address, can_delete: bool): object::ConstructorRef
 
-
-Implementation +##### Implementation -
fun create_object_internal(
-    creator_address: address,
-    object: address,
-    can_delete: bool,
+
public fun create_object(
+    owner_address: address, can_delete: bool
 ): ConstructorRef acquires Tombstone {
-    // create resource account to prevent address overapping.
-    account::create_object_account(object);
-
-    assert!(!exists<ObjectCore>(object), error::already_exists(EOBJECT_EXISTS));
-    let object_signer = account::create_signer(object);
-    let version = if (exists<Tombstone>(object)) {
-        let Tombstone { version } = move_from<Tombstone>(object);
-        (version+1)
-    } else {
-        1
-    };
-
-    move_to(
-        &object_signer,
-        ObjectCore {
-            owner: creator_address,
-            allow_ungated_transfer: true,
-            version,
-        },
-    );
-
-    event::emit (
-        CreateEvent {
-            owner: creator_address,
-            object,
-            version,
-        }
-    );
-
-    ConstructorRef { self: object, version, can_delete }
+    let unique_address = transaction_context::generate_unique_address();
+    create_object_internal(
+        owner_address,
+        unique_address,
+        can_delete
+    )
 }
 
-
- ## Function `generate_delete_ref` @@ -1000,20 +931,20 @@ Generates the DeleteRef, which can be used to remove ObjectCore from global stor -
-Implementation +##### Implementation
public fun generate_delete_ref(ref: &ConstructorRef): DeleteRef {
-    assert!(ref.can_delete, error::permission_denied(ECANNOT_DELETE));
+    assert!(
+        ref.can_delete,
+        error::permission_denied(ECANNOT_DELETE)
+    );
     DeleteRef { self: ref.self, version: ref.version }
 }
 
-
- ## Function `generate_extend_ref` @@ -1026,8 +957,7 @@ Generates the ExtendRef, which can be used to add new events and resources to th -
-Implementation +##### Implementation
public fun generate_extend_ref(ref: &ConstructorRef): ExtendRef {
@@ -1037,8 +967,6 @@ Generates the ExtendRef, which can be used to add new events and resources to th
 
 
 
-
- ## Function `generate_transfer_ref` @@ -1051,8 +979,7 @@ Generates the TransferRef, which can be used to manage object transfers. -
-Implementation +##### Implementation
public fun generate_transfer_ref(ref: &ConstructorRef): TransferRef {
@@ -1062,8 +989,6 @@ Generates the TransferRef, which can be used to manage object transfers.
 
 
 
-
- ## Function `generate_derive_ref` @@ -1076,8 +1001,7 @@ Generates the DeriveRef, which can be used to create determnistic derived object -
-Implementation +##### Implementation
public fun generate_derive_ref(ref: &ConstructorRef): DeriveRef {
@@ -1087,8 +1011,6 @@ Generates the DeriveRef, which can be used to create determnistic derived object
 
 
 
-
- ## Function `generate_signer` @@ -1101,8 +1023,7 @@ Create a signer for the ConstructorRef -
-Implementation +##### Implementation
public fun generate_signer(ref: &ConstructorRef): signer {
@@ -1112,8 +1033,6 @@ Create a signer for the ConstructorRef
 
 
 
-
- ## Function `address_from_constructor_ref` @@ -1126,8 +1045,7 @@ Returns the address associated with the constructor -
-Implementation +##### Implementation
public fun address_from_constructor_ref(ref: &ConstructorRef): address {
@@ -1137,8 +1055,6 @@ Returns the address associated with the constructor
 
 
 
-
- ## Function `object_from_constructor_ref` @@ -1151,8 +1067,7 @@ Returns an Object from within a ConstructorRef -
-Implementation +##### Implementation
public fun object_from_constructor_ref<T: key>(ref: &ConstructorRef): Object<T> {
@@ -1162,8 +1077,6 @@ Returns an Object from within a ConstructorRef
 
 
 
-
- ## Function `can_generate_delete_ref` @@ -1176,8 +1089,7 @@ Returns whether or not the ConstructorRef can be used to create DeleteRef -
-Implementation +##### Implementation
public fun can_generate_delete_ref(ref: &ConstructorRef): bool {
@@ -1187,8 +1099,6 @@ Returns whether or not the ConstructorRef can be used to create DeleteRef
 
 
 
-
- ## Function `address_from_delete_ref` @@ -1201,8 +1111,7 @@ Returns the address associated with the constructor -
-Implementation +##### Implementation
public fun address_from_delete_ref(ref: &DeleteRef): address {
@@ -1212,8 +1121,6 @@ Returns the address associated with the constructor
 
 
 
-
- ## Function `object_from_delete_ref` @@ -1226,8 +1133,7 @@ Returns an Object from within a DeleteRef. -
-Implementation +##### Implementation
public fun object_from_delete_ref<T: key>(ref: &DeleteRef): Object<T> {
@@ -1237,8 +1143,6 @@ Returns an Object from within a DeleteRef.
 
 
 
-
- ## Function `delete` @@ -1251,31 +1155,28 @@ Removes from the specified Object from global storage. -
-Implementation +##### Implementation
public fun delete(ref: DeleteRef) acquires ObjectCore {
     let object_core = move_from<ObjectCore>(ref.self);
-    assert!(ref.version == object_core.version, error::permission_denied(EVERSION_MISMATCH));
+    assert!(
+        ref.version == object_core.version,
+        error::permission_denied(EVERSION_MISMATCH)
+    );
 
-    let ObjectCore {
-        owner: _,
-        allow_ungated_transfer: _,
-        version,
-    } = object_core;
+    let ObjectCore { owner: _, allow_ungated_transfer: _, version } = object_core;
 
     // set tombstone
-    move_to<Tombstone>(&account::create_signer(ref.self), Tombstone {
-        version,
-    });
+    move_to<Tombstone>(
+        &account::create_signer(ref.self),
+        Tombstone { version }
+    );
 }
 
-
- ## Function `generate_signer_for_extending` @@ -1288,13 +1189,15 @@ Create a signer for the ExtendRef -
-Implementation +##### Implementation
public fun generate_signer_for_extending(ref: &ExtendRef): signer acquires ObjectCore {
     let object_core = borrow_global<ObjectCore>(ref.self);
-    assert!(ref.version == object_core.version, error::permission_denied(EVERSION_MISMATCH));
+    assert!(
+        ref.version == object_core.version,
+        error::permission_denied(EVERSION_MISMATCH)
+    );
 
     account::create_signer(ref.self)
 }
@@ -1302,8 +1205,6 @@ Create a signer for the ExtendRef
 
 
 
-
- ## Function `address_from_extend_ref` @@ -1316,8 +1217,7 @@ Returns an address from within a ExtendRef. -
-Implementation +##### Implementation
public fun address_from_extend_ref(ref: &ExtendRef): address {
@@ -1327,8 +1227,6 @@ Returns an address from within a ExtendRef.
 
 
 
-
- ## Function `disable_ungated_transfer` @@ -1341,13 +1239,15 @@ Disable direct transfer, transfers can only be triggered via a TransferRef -
-Implementation +##### Implementation
public fun disable_ungated_transfer(ref: &TransferRef) acquires ObjectCore {
     let object_core = borrow_global_mut<ObjectCore>(ref.self);
-    assert!(ref.version == object_core.version, error::permission_denied(EVERSION_MISMATCH));
+    assert!(
+        ref.version == object_core.version,
+        error::permission_denied(EVERSION_MISMATCH)
+    );
 
     object_core.allow_ungated_transfer = false;
 }
@@ -1355,8 +1255,6 @@ Disable direct transfer, transfers can only be triggered via a TransferRef
 
 
 
-
- ## Function `enable_ungated_transfer` @@ -1369,13 +1267,15 @@ Enable direct transfer. -
-Implementation +##### Implementation
public fun enable_ungated_transfer(ref: &TransferRef) acquires ObjectCore {
     let object_core = borrow_global_mut<ObjectCore>(ref.self);
-    assert!(ref.version == object_core.version, error::permission_denied(EVERSION_MISMATCH));
+    assert!(
+        ref.version == object_core.version,
+        error::permission_denied(EVERSION_MISMATCH)
+    );
 
     object_core.allow_ungated_transfer = true;
 }
@@ -1383,8 +1283,6 @@ Enable direct transfer.
 
 
 
-
- ## Function `generate_linear_transfer_ref` @@ -1398,26 +1296,28 @@ time of generation is the owner at the time of transferring. -
-Implementation +##### Implementation -
public fun generate_linear_transfer_ref(ref: &TransferRef): LinearTransferRef acquires ObjectCore {
+
public fun generate_linear_transfer_ref(
+    ref: &TransferRef
+): LinearTransferRef acquires ObjectCore {
     let object_core = borrow_global<ObjectCore>(ref.self);
-    assert!(ref.version == object_core.version, error::permission_denied(EVERSION_MISMATCH));
+    assert!(
+        ref.version == object_core.version,
+        error::permission_denied(EVERSION_MISMATCH)
+    );
 
     LinearTransferRef {
         self: ref.self,
         owner: object_core.owner,
-        version: object_core.version,
+        version: object_core.version
     }
 }
 
-
- ## Function `transfer_with_ref` @@ -1430,22 +1330,21 @@ Transfer to the destination address using a LinearTransferRef. -
-Implementation +##### Implementation
public fun transfer_with_ref(ref: LinearTransferRef, to: address) acquires ObjectCore {
     let object_core = borrow_global_mut<ObjectCore>(ref.self);
-    assert!(ref.version == object_core.version, error::permission_denied(EVERSION_MISMATCH));
-    assert!(object_core.owner == ref.owner, error::permission_denied(ENOT_OBJECT_OWNER));
-
-    event::emit(
-        TransferEvent {
-            object: ref.self,
-            from: object_core.owner,
-            to,
-        },
+    assert!(
+        ref.version == object_core.version,
+        error::permission_denied(EVERSION_MISMATCH)
     );
+    assert!(
+        object_core.owner == ref.owner,
+        error::permission_denied(ENOT_OBJECT_OWNER)
+    );
+
+    event::emit(TransferEvent { object: ref.self, from: object_core.owner, to });
 
     object_core.owner = to;
 }
@@ -1453,8 +1352,6 @@ Transfer to the destination address using a LinearTransferRef.
 
 
 
-
- ## Function `transfer_call` @@ -1467,14 +1364,11 @@ Entry function that can be used to transfer, if allow_ungated_transfer is set tr -
-Implementation +##### Implementation
public entry fun transfer_call(
-    owner: &signer,
-    object: address,
-    to: address,
+    owner: &signer, object: address, to: address
 ) acquires ObjectCore {
     transfer_raw(owner, object, to)
 }
@@ -1482,8 +1376,6 @@ Entry function that can be used to transfer, if allow_ungated_transfer is set tr
 
 
 
-
- ## Function `transfer` @@ -1497,14 +1389,11 @@ for Object to the "to" address. -
-Implementation +##### Implementation
public entry fun transfer<T: key>(
-    owner: &signer,
-    object: Object<T>,
-    to: address,
+    owner: &signer, object: Object<T>, to: address
 ) acquires ObjectCore {
     transfer_raw(owner, object.inner, to)
 }
@@ -1512,8 +1401,6 @@ for Object to the "to" address.
 
 
 
-
- ## Function `transfer_raw` @@ -1529,38 +1416,23 @@ hierarchy. -
-Implementation +##### Implementation -
public fun transfer_raw(
-    owner: &signer,
-    object: address,
-    to: address,
-) acquires ObjectCore {
+
public fun transfer_raw(owner: &signer, object: address, to: address) acquires ObjectCore {
     let owner_address = signer::address_of(owner);
     verify_ungated_and_descendant(owner_address, object);
 
     let object_core = borrow_global_mut<ObjectCore>(object);
-    if (object_core.owner == to) {
-        return
-    };
+    if (object_core.owner == to) { return };
 
-    event::emit(
-        TransferEvent {
-            object: object,
-            from: object_core.owner,
-            to,
-        },
-    );
+    event::emit(TransferEvent { object: object, from: object_core.owner, to });
     object_core.owner = to;
 }
 
-
- ## Function `transfer_to_object` @@ -1573,14 +1445,11 @@ Transfer the given object to another object. See transfer for more -
-Implementation +##### Implementation
public entry fun transfer_to_object<O: key, T: key>(
-    owner: &signer,
-    object: Object<O>,
-    to: Object<T>,
+    owner: &signer, object: Object<O>, to: Object<T>
 ) acquires ObjectCore {
     transfer(owner, object, to.inner)
 }
@@ -1588,67 +1457,6 @@ Transfer the given object to another object. See transfer for more
 
 
 
-
- - - -## Function `verify_ungated_and_descendant` - -This checks that the destination address is eventually owned by the owner and that each -object between the two allows for ungated transfers. Note, this is limited to a depth of 8 -objects may have cyclic dependencies. - - -
fun verify_ungated_and_descendant(owner: address, destination: address)
-
- - - -
-Implementation - - -
fun verify_ungated_and_descendant(owner: address, destination: address) acquires ObjectCore {
-    let current_address = destination;
-    assert!(
-        exists<ObjectCore>(current_address),
-        error::not_found(EOBJECT_DOES_NOT_EXIST),
-    );
-
-    let object = borrow_global<ObjectCore>(current_address);
-    assert!(
-        object.allow_ungated_transfer,
-        error::permission_denied(ENO_UNGATED_TRANSFERS),
-    );
-
-    let current_address = object.owner;
-
-    let count = 0;
-    while (owner != current_address) {
-        let count = count + 1;
-        assert!(count < MAXIMUM_OBJECT_NESTING, error::out_of_range(EMAXIMUM_NESTING));
-
-        // At this point, the first object exists and so the more likely case is that the
-        // object's owner is not an object. So we return a more sensible error.
-        assert!(
-            exists<ObjectCore>(current_address),
-            error::permission_denied(ENOT_OBJECT_OWNER),
-        );
-        let object = borrow_global<ObjectCore>(current_address);
-        assert!(
-            object.allow_ungated_transfer,
-            error::permission_denied(ENO_UNGATED_TRANSFERS),
-        );
-
-        current_address = object.owner;
-    };
-}
-
- - - -
- ## Function `ungated_transfer_allowed` @@ -1662,14 +1470,13 @@ Return true if ungated transfer is allowed. -
-Implementation +##### Implementation
public fun ungated_transfer_allowed<T: key>(object: Object<T>): bool acquires ObjectCore {
     assert!(
         exists<ObjectCore>(object.inner),
-        error::not_found(EOBJECT_DOES_NOT_EXIST),
+        error::not_found(EOBJECT_DOES_NOT_EXIST)
     );
     borrow_global<ObjectCore>(object.inner).allow_ungated_transfer
 }
@@ -1677,8 +1484,6 @@ Return true if ungated transfer is allowed.
 
 
 
-
- ## Function `owner` @@ -1692,14 +1497,13 @@ Return the current owner. -
-Implementation +##### Implementation
public fun owner<T: key>(object: Object<T>): address acquires ObjectCore {
     assert!(
         exists<ObjectCore>(object.inner),
-        error::not_found(EOBJECT_DOES_NOT_EXIST),
+        error::not_found(EOBJECT_DOES_NOT_EXIST)
     );
     borrow_global<ObjectCore>(object.inner).owner
 }
@@ -1707,8 +1511,6 @@ Return the current owner.
 
 
 
-
- ## Function `is_owner` @@ -1722,8 +1524,7 @@ Return true if the provided address is the current owner. -
-Implementation +##### Implementation
public fun is_owner<T: key>(object: Object<T>, owner: address): bool acquires ObjectCore {
@@ -1733,8 +1534,6 @@ Return true if the provided address is the current owner.
 
 
 
-
- ## Function `owns` @@ -1748,19 +1547,18 @@ Return true if the provided address has indirect or direct ownership of the prov -
-Implementation +##### Implementation
public fun owns<T: key>(object: Object<T>, owner: address): bool acquires ObjectCore {
-    let current_address = object_address(object);
+    let current_address = object_address(&object);
     if (current_address == owner) {
         return true
     };
 
     assert!(
         exists<ObjectCore>(current_address),
-        error::not_found(EOBJECT_DOES_NOT_EXIST),
+        error::not_found(EOBJECT_DOES_NOT_EXIST)
     );
 
     let object = borrow_global<ObjectCore>(current_address);
@@ -1768,8 +1566,11 @@ Return true if the provided address has indirect or direct ownership of the prov
 
     let count = 0;
     while (owner != current_address) {
-        let count = count + 1;
-        assert!(count < MAXIMUM_OBJECT_NESTING, error::out_of_range(EMAXIMUM_NESTING));
+        count = count + 1;
+        assert!(
+            count < MAXIMUM_OBJECT_NESTING,
+            error::out_of_range(EMAXIMUM_NESTING)
+        );
         if (!exists<ObjectCore>(current_address)) {
             return false
         };
@@ -1780,7 +1581,3 @@ Return true if the provided address has indirect or direct ownership of the prov
     true
 }
 
- - - -
diff --git a/minitia_stdlib/doc/object_code_deployment.md b/minitia_stdlib/doc/object_code_deployment.md new file mode 100644 index 0000000..3bb2ea2 --- /dev/null +++ b/minitia_stdlib/doc/object_code_deployment.md @@ -0,0 +1,316 @@ + + + +# Module `0x1::object_code_deployment` + +This module allows users to deploy, upgrade and freeze modules deployed to objects on-chain. +This enables users to deploy modules to an object with a unique address each time they are published. +This modules provides an alternative method to publish code on-chain, where code is deployed to objects rather than accounts. +This is encouraged as it abstracts the necessary resources needed for deploying modules, +along with the required authorization to upgrade and freeze modules. + +The functionalities of this module are as follows. + +Publishing modules flow: +1. Create a new object with the address derived from the publisher address and the object seed. +2. Publish the module passed in the function via metadata_serialized and code to the newly created object. +3. Emits 'Publish' event with the address of the newly created object. +4. Create a ManagingRefs which stores the extend ref of the newly created object. +Note: This is needed to upgrade the code as the signer must be generated to upgrade the existing code in an object. + +Upgrading modules flow: +1. Assert the code_object passed in the function is owned by the publisher. +2. Assert the code_object passed in the function exists in global storage. +2. Retrieve the ExtendRef from the code_object and generate the signer from this. +3. Upgrade the module with the metadata_serialized and code passed in the function. +4. Emits 'Upgrade' event with the address of the object with the upgraded code. +Note: If the modules were deployed as immutable when calling publish, the upgrade will fail. + +Freezing modules flow: +1. Assert the code_object passed in the function exists in global storage. +2. Assert the code_object passed in the function is owned by the publisher. +3. Mark all the modules in the code_object as immutable. +4. Emits 'Freeze' event with the address of the object with the frozen code. +Note: There is no unfreeze function as this gives no benefit if the user can freeze/unfreeze modules at will. +Once modules are marked as immutable, they cannot be made mutable again. + + +- [Resource `ManagingRefs`](#0x1_object_code_deployment_ManagingRefs) +- [Struct `Publish`](#0x1_object_code_deployment_Publish) +- [Struct `Upgrade`](#0x1_object_code_deployment_Upgrade) +- [Struct `Freeze`](#0x1_object_code_deployment_Freeze) +- [Constants](#@Constants_0) +- [Function `publish`](#0x1_object_code_deployment_publish) +- [Function `upgrade`](#0x1_object_code_deployment_upgrade) +- [Function `freeze_code_object`](#0x1_object_code_deployment_freeze_code_object) + + +
use 0x1::account;
+use 0x1::bcs;
+use 0x1::code;
+use 0x1::error;
+use 0x1::event;
+use 0x1::object;
+use 0x1::signer;
+use 0x1::string;
+use 0x1::vector;
+
+ + + + + +## Resource `ManagingRefs` + +Internal struct, attached to the object, that holds Refs we need to manage the code deployment (i.e. upgrades). + + +
struct ManagingRefs has key
+
+ + + +##### Fields + + +
+
+extend_ref: object::ExtendRef +
+
+ We need to keep the extend ref to be able to generate the signer to upgrade existing code. +
+
+ + + + +## Struct `Publish` + +Event emitted when code is published to an object. + + +
#[event]
+struct Publish has drop, store
+
+ + + +##### Fields + + +
+
+object_address: address +
+
+ +
+
+ + + + +## Struct `Upgrade` + +Event emitted when code in an existing object is upgraded. + + +
#[event]
+struct Upgrade has drop, store
+
+ + + +##### Fields + + +
+
+object_address: address +
+
+ +
+
+ + + + +## Struct `Freeze` + +Event emitted when code in an existing object is made immutable. + + +
#[event]
+struct Freeze has drop, store
+
+ + + +##### Fields + + +
+
+object_address: address +
+
+ +
+
+ + + + +## Constants + + + + +code_object does not exist. + + +
const ECODE_OBJECT_DOES_NOT_EXIST: u64 = 3;
+
+ + + + + +Not the owner of the code_object + + +
const ENOT_CODE_OBJECT_OWNER: u64 = 2;
+
+ + + + + +Object code deployment feature not supported. + + +
const EOBJECT_CODE_DEPLOYMENT_NOT_SUPPORTED: u64 = 1;
+
+ + + + + + + +
const OBJECT_CODE_DEPLOYMENT_DOMAIN_SEPARATOR: vector<u8> = [109, 105, 110, 105, 116, 105, 97, 95, 115, 116, 100, 58, 58, 111, 98, 106, 101, 99, 116, 95, 99, 111, 100, 101, 95, 100, 101, 112, 108, 111, 121, 109, 101, 110, 116];
+
+ + + + + +## Function `publish` + +Creates a new object with a unique address derived from the publisher address and the object seed. +Publishes the code passed in the function to the newly created object. +The caller must provide package metadata describing the package via metadata_serialized and +the code to be published via code. This contains a vector of modules to be deployed on-chain. + + +
public entry fun publish(publisher: &signer, module_ids: vector<string::String>, code: vector<vector<u8>>)
+
+ + + +##### Implementation + + +
public entry fun publish(
+    publisher: &signer, module_ids: vector<String>, code: vector<vector<u8>>
+) {
+    let publisher_address = signer::address_of(publisher);
+    let object_seed = object_seed(publisher_address);
+    let constructor_ref = &object::create_named_object(publisher, object_seed);
+    let code_signer = &object::generate_signer(constructor_ref);
+    code::publish(code_signer, module_ids, code, 1);
+
+    event::emit(Publish { object_address: signer::address_of(code_signer) });
+
+    move_to(
+        code_signer,
+        ManagingRefs { extend_ref: object::generate_extend_ref(constructor_ref) }
+    );
+}
+
+ + + + + +## Function `upgrade` + +Upgrades the existing modules at the code_object address with the new modules passed in code, +along with the metadata metadata_serialized. +Note: If the modules were deployed as immutable when calling publish, the upgrade will fail. +Requires the publisher to be the owner of the code_object. + + +
public entry fun upgrade(publisher: &signer, module_ids: vector<string::String>, code: vector<vector<u8>>, code_object: object::Object<code::MetadataStore>)
+
+ + + +##### Implementation + + +
public entry fun upgrade(
+    publisher: &signer,
+    module_ids: vector<String>,
+    code: vector<vector<u8>>,
+    code_object: Object<MetadataStore>
+) acquires ManagingRefs {
+    let publisher_address = signer::address_of(publisher);
+    assert!(
+        object::is_owner(code_object, publisher_address),
+        error::permission_denied(ENOT_CODE_OBJECT_OWNER)
+    );
+
+    let code_object_address = object::object_address(&code_object);
+    assert!(
+        exists<ManagingRefs>(code_object_address),
+        error::not_found(ECODE_OBJECT_DOES_NOT_EXIST)
+    );
+
+    let extend_ref = &borrow_global<ManagingRefs>(code_object_address).extend_ref;
+    let code_signer = &object::generate_signer_for_extending(extend_ref);
+    code::publish(code_signer, module_ids, code, 1);
+
+    event::emit(Upgrade { object_address: signer::address_of(code_signer) });
+}
+
+ + + + + +## Function `freeze_code_object` + +Make an existing upgradable package immutable. Once this is called, the package cannot be made upgradable again. +Each code_object should only have one package, as one package is deployed per object in this module. +Requires the publisher to be the owner of the code_object. + + +
public entry fun freeze_code_object(publisher: &signer, code_object: object::Object<code::MetadataStore>)
+
+ + + +##### Implementation + + +
public entry fun freeze_code_object(
+    publisher: &signer, code_object: Object<MetadataStore>
+) {
+    code::freeze_code_object(publisher, code_object);
+
+    event::emit(Freeze { object_address: object::object_address(&code_object) });
+}
+
diff --git a/minitia_stdlib/doc/oracle.md b/minitia_stdlib/doc/oracle.md index 1631bd1..00f23d3 100644 --- a/minitia_stdlib/doc/oracle.md +++ b/minitia_stdlib/doc/oracle.md @@ -6,7 +6,6 @@ - [Function `get_price`](#0x1_oracle_get_price) -- [Function `get_price_internal`](#0x1_oracle_get_price_internal)
use 0x1::string;
@@ -26,37 +25,10 @@
 
 
 
-
-Implementation +##### Implementation
public fun get_price(pair_id: String): (u256, u64, u64) {
     get_price_internal(*string::bytes(&pair_id))
 }
 
- - - -
- - - -## Function `get_price_internal` - - - -
fun get_price_internal(pair_id: vector<u8>): (u256, u64, u64)
-
- - - -
-Implementation - - -
native fun get_price_internal(pair_id: vector<u8>): (u256, u64, u64);
-
- - - -
diff --git a/minitia_stdlib/doc/primary_fungible_store.md b/minitia_stdlib/doc/primary_fungible_store.md index 0b80276..e6d87c9 100644 --- a/minitia_stdlib/doc/primary_fungible_store.md +++ b/minitia_stdlib/doc/primary_fungible_store.md @@ -21,7 +21,6 @@ fungible asset to it. This emits an deposit event. - [Resource `DeriveRefPod`](#0x1_primary_fungible_store_DeriveRefPod) - [Resource `ModuleStore`](#0x1_primary_fungible_store_ModuleStore) - [Struct `PrimaryStoreCreatedEvent`](#0x1_primary_fungible_store_PrimaryStoreCreatedEvent) -- [Function `init_module`](#0x1_primary_fungible_store_init_module) - [Function `create_primary_store_enabled_fungible_asset`](#0x1_primary_fungible_store_create_primary_store_enabled_fungible_asset) - [Function `ensure_primary_store_exists`](#0x1_primary_fungible_store_ensure_primary_store_exists) - [Function `create_primary_store`](#0x1_primary_fungible_store_create_primary_store) @@ -32,9 +31,12 @@ fungible asset to it. This emits an deposit event. - [Function `is_frozen`](#0x1_primary_fungible_store_is_frozen) - [Function `balance`](#0x1_primary_fungible_store_balance) - [Function `balances`](#0x1_primary_fungible_store_balances) +- [Function `sudo_deposit`](#0x1_primary_fungible_store_sudo_deposit) +- [Function `sudo_transfer`](#0x1_primary_fungible_store_sudo_transfer) - [Function `withdraw`](#0x1_primary_fungible_store_withdraw) - [Function `deposit`](#0x1_primary_fungible_store_deposit) - [Function `transfer`](#0x1_primary_fungible_store_transfer) +- [Function `transfer_assert_minimum_deposit`](#0x1_primary_fungible_store_transfer_assert_minimum_deposit) - [Function `mint`](#0x1_primary_fungible_store_mint) - [Function `burn`](#0x1_primary_fungible_store_burn) - [Function `set_frozen_flag`](#0x1_primary_fungible_store_set_frozen_flag) @@ -44,6 +46,7 @@ fungible asset to it. This emits an deposit event.
use 0x1::account;
+use 0x1::dispatchable_fungible_asset;
 use 0x1::event;
 use 0x1::fungible_asset;
 use 0x1::object;
@@ -69,8 +72,7 @@ assets.
 
 
 
-
-Fields +##### Fields
@@ -83,8 +85,6 @@ assets.
-
- ## Resource `ModuleStore` @@ -96,8 +96,7 @@ assets. -
-Fields +##### Fields
@@ -116,8 +115,6 @@ assets.
-
- ## Struct `PrimaryStoreCreatedEvent` @@ -130,8 +127,7 @@ assets. -
-Fields +##### Fields
@@ -156,35 +152,6 @@ assets.
-
- - - -## Function `init_module` - - - -
fun init_module(chain: &signer)
-
- - - -
-Implementation - - -
fun init_module (chain: &signer) {
-    move_to(chain, ModuleStore {
-        issuers: table::new(),
-        user_stores: table::new(),
-    })
-}
-
- - - -
- ## Function `create_primary_store_enabled_fungible_asset` @@ -199,8 +166,7 @@ so that users can easily deposit/withdraw/transfer fungible assets. -
-Implementation +##### Implementation
public fun create_primary_store_enabled_fungible_asset(
@@ -210,7 +176,7 @@ so that users can easily deposit/withdraw/transfer fungible assets.
     symbol: String,
     decimals: u8,
     icon_uri: String,
-    project_uri: String,
+    project_uri: String
 ) acquires ModuleStore {
     fungible_asset::add_fungibility(
         constructor_ref,
@@ -219,28 +185,32 @@ so that users can easily deposit/withdraw/transfer fungible assets.
         symbol,
         decimals,
         icon_uri,
-        project_uri,
+        project_uri
     );
 
     let metadata = object::object_from_constructor_ref<Metadata>(constructor_ref);
     let metadata_signer = &object::generate_signer(constructor_ref);
-    move_to(metadata_signer, DeriveRefPod {
-        metadata_derive_ref: object::generate_derive_ref(constructor_ref),
-    });
-
-    let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
-    table::add(
-        &mut module_store.issuers,
-        object::object_address(metadata),
-        object::owner(metadata),
+    move_to(
+        metadata_signer,
+        DeriveRefPod {
+            metadata_derive_ref: object::generate_derive_ref(constructor_ref)
+        }
     );
+
+    // record issuers for cosmos side query
+    if (exists<ModuleStore>(@minitia_std)) {
+        let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
+        table::add(
+            &mut module_store.issuers,
+            object::object_address(&metadata),
+            object::owner(metadata)
+        );
+    }
 }
 
-
- ## Function `ensure_primary_store_exists` @@ -253,13 +223,11 @@ Ensure that the primary store object for the given address exists. If it doesn't -
-Implementation +##### Implementation
public fun ensure_primary_store_exists<T: key>(
-    owner: address,
-    metadata: Object<T>,
+    owner: address, metadata: Object<T>
 ): Object<FungibleStore> acquires DeriveRefPod, ModuleStore {
     if (!primary_store_exists(owner, metadata)) {
         create_primary_store(owner, metadata)
@@ -271,8 +239,6 @@ Ensure that the primary store object for the given address exists. If it doesn't
 
 
 
-
- ## Function `create_primary_store` @@ -285,55 +251,61 @@ Create a primary store object to hold fungible asset for the given address. -
-Implementation +##### Implementation
public fun create_primary_store<T: key>(
-    owner_addr: address,
-    metadata: Object<T>,
+    owner_addr: address, metadata: Object<T>
 ): Object<FungibleStore> acquires DeriveRefPod, ModuleStore {
-    let metadata_addr = object::object_address(metadata);
+    let metadata_addr = object::object_address(&metadata);
     object::address_to_object<Metadata>(metadata_addr);
 
     let derive_ref = &borrow_global<DeriveRefPod>(metadata_addr).metadata_derive_ref;
-    let constructor_ref = &object::create_user_derived_object(owner_addr, derive_ref, false);
+    let constructor_ref =
+        &object::create_user_derived_object(owner_addr, derive_ref, false);
 
     // Disable ungated transfer as deterministic stores shouldn't be transferrable.
     let transfer_ref = &object::generate_transfer_ref(constructor_ref);
     object::disable_ungated_transfer(transfer_ref);
 
     let store = fungible_asset::create_store(constructor_ref, metadata);
+    let store_addr = object::address_from_constructor_ref(constructor_ref);
 
-    // add owner store to table for balances query
-    let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
-    if (!table::contains(&module_store.user_stores, owner_addr)) {
-        table::add(&mut module_store.user_stores, owner_addr, table::new());
+    // record owner store to table for cosmos side query
+    if (exists<ModuleStore>(@minitia_std)) {
+        let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
+        if (!table::contains(
+            &module_store.user_stores,
+            owner_addr
+        )) {
+            table::add(
+                &mut module_store.user_stores,
+                owner_addr,
+                table::new()
+            );
+        };
+
+        let user_stores = table::borrow_mut(&mut module_store.user_stores, owner_addr);
+        table::add(
+            user_stores,
+            metadata_addr,
+            store_addr
+        );
     };
 
-    let user_stores = table::borrow_mut(&mut module_store.user_stores, owner_addr);
-    let store_addr = object::address_from_constructor_ref(constructor_ref);
-    table::add(user_stores, metadata_addr, store_addr);
-
     // emit store created event
-    event::emit(PrimaryStoreCreatedEvent {
-        owner_addr,
-        store_addr,
-        metadata_addr,
-    });
-
+    event::emit(PrimaryStoreCreatedEvent { owner_addr, store_addr, metadata_addr });
     store
 }
 
-
- ## Function `issuer` +Get the address of the issuer for the given metadata object.
#[view]
@@ -342,20 +314,20 @@ Create a primary store object to hold fungible asset for the given address.
 
 
 
-
-Implementation +##### Implementation
public fun issuer<T: key>(metadata: Object<T>): address acquires ModuleStore {
     let module_store = borrow_global<ModuleStore>(@minitia_std);
-    *table::borrow(&module_store.issuers, object::object_address(metadata))
+    *table::borrow(
+        &module_store.issuers,
+        object::object_address(&metadata)
+    )
 }
 
-
- ## Function `primary_store_address` @@ -369,20 +341,19 @@ Get the address of the primary store for the given account. -
-Implementation +##### Implementation -
public fun primary_store_address<T: key>(owner: address, metadata: Object<T>): address {
-    let metadata_addr = object::object_address(metadata);
+
public fun primary_store_address<T: key>(
+    owner: address, metadata: Object<T>
+): address {
+    let metadata_addr = object::object_address(&metadata);
     object::create_user_derived_object_address(owner, metadata_addr)
 }
 
-
- ## Function `primary_store` @@ -396,11 +367,11 @@ Get the primary store object for the given account. -
-Implementation +##### Implementation -
public fun primary_store<T: key>(owner: address, metadata: Object<T>): Object<FungibleStore> {
+
public fun primary_store<T: key>(owner: address, metadata: Object<T>):
+    Object<FungibleStore> {
     let store = primary_store_address(owner, metadata);
     object::address_to_object<FungibleStore>(store)
 }
@@ -408,8 +379,6 @@ Get the primary store object for the given account.
 
 
 
-
- ## Function `primary_store_exists` @@ -423,19 +392,18 @@ Return whether the given account's primary store exists. -
-Implementation +##### Implementation -
public fun primary_store_exists<T: key>(account: address, metadata: Object<T>): bool {
+
public fun primary_store_exists<T: key>(
+    account: address, metadata: Object<T>
+): bool {
     fungible_asset::store_exists(primary_store_address(account, metadata))
 }
 
-
- ## Function `is_frozen` @@ -449,23 +417,18 @@ Return whether the given account's primary store is frozen. -
-Implementation +##### Implementation
public fun is_frozen<T: key>(account: address, metadata: Object<T>): bool {
     if (primary_store_exists(account, metadata)) {
         fungible_asset::is_frozen(primary_store(account, metadata))
-    } else {
-        false
-    }
+    } else { false }
 }
 
-
- ## Function `balance` @@ -479,27 +442,23 @@ Get the balance of account's p -
-Implementation +##### Implementation
public fun balance<T: key>(account: address, metadata: Object<T>): u64 {
     if (primary_store_exists(account, metadata)) {
         fungible_asset::balance(primary_store(account, metadata))
-    } else {
-        0
-    }
+    } else { 0 }
 }
 
-
- ## Function `balances` +Get the balances of account's primary store for all fungible assets.
#[view]
@@ -508,34 +467,35 @@ Get the balance of account's p
 
 
 
-
-Implementation +##### Implementation
public fun balances(
-    account: address,
-    start_after: Option<address>,
-    limit: u8,
-): (vector<Object<Metadata>>, vector<u64>)  acquires ModuleStore {
+    account: address, start_after: Option<address>, limit: u8
+): (vector<Object<Metadata>>, vector<u64>) acquires ModuleStore {
     let module_store = borrow_global<ModuleStore>(@minitia_std);
     let account_stores = table::borrow(&module_store.user_stores, account);
     let iter = table::iter(
         account_stores,
         option::none(),
         start_after,
-        2,
+        2
     );
 
     let metadata_vec: vector<Object<Metadata>> = vector[];
     let balance_vec: vector<u64> = vector[];
 
-    while (table::prepare<address, address>(&mut iter) && vector::length(&balance_vec) < (limit as u64)) {
-        let (metadata_addr, store_addr) = table::next<address, address>(&mut iter);
+    while (table::prepare<address, address>(iter)
+        && vector::length(&balance_vec) < (limit as u64)) {
+        let (metadata_addr, store_addr) = table::next<address, address>(iter);
         let metadata = object::address_to_object<Metadata>(metadata_addr);
         let store = object::address_to_object<FungibleStore>(*store_addr);
 
         vector::push_back(&mut metadata_vec, metadata);
-        vector::push_back(&mut balance_vec, fungible_asset::balance(store));
+        vector::push_back(
+            &mut balance_vec,
+            fungible_asset::balance(store)
+        );
     };
 
     (metadata_vec, balance_vec)
@@ -544,7 +504,75 @@ Get the balance of account's p
 
 
 
-
+ + +## Function `sudo_deposit` + +Deposit fungible asset fa to the given account's primary store. + +This function is only callable by the chain. + + +
public(friend) fun sudo_deposit(owner: address, fa: fungible_asset::FungibleAsset)
+
+ + + +##### Implementation + + +
public(friend) fun sudo_deposit(
+    owner: address, fa: FungibleAsset
+) acquires DeriveRefPod, ModuleStore {
+    let metadata = fungible_asset::asset_metadata(&fa);
+    let store = ensure_primary_store_exists(owner, metadata);
+    fungible_asset::sudo_deposit(store, fa);
+
+    // create cosmos side account
+    if (!account::exists_at(owner)) {
+        let _acc_num = account::create_account(owner);
+    };
+}
+
+ + + + + +## Function `sudo_transfer` + +Transfer amount of fungible asset from sender's primary store to receiver's primary store. + +This function is only callable by the chain. + + +
public(friend) fun sudo_transfer<T: key>(sender: &signer, metadata: object::Object<T>, recipient: address, amount: u64)
+
+ + + +##### Implementation + + +
public(friend) fun sudo_transfer<T: key>(
+    sender: &signer,
+    metadata: Object<T>,
+    recipient: address,
+    amount: u64
+) acquires DeriveRefPod, ModuleStore {
+    let sender_store =
+        ensure_primary_store_exists(signer::address_of(sender), metadata);
+    let recipient_store = ensure_primary_store_exists(recipient, metadata);
+    fungible_asset::sudo_transfer(
+        sender,
+        sender_store,
+        recipient_store,
+        amount
+    );
+}
+
+ + @@ -558,20 +586,23 @@ Withdraw amount of fungible asset from the given account's primary -
-Implementation +##### Implementation -
public fun withdraw<T: key>(owner: &signer, metadata: Object<T>, amount: u64): FungibleAsset {
+
public fun withdraw<T: key>(
+    owner: &signer, metadata: Object<T>, amount: u64
+): FungibleAsset {
+    if (amount == 0) {
+        return fungible_asset::zero(metadata)
+    };
+
     let store = primary_store(signer::address_of(owner), metadata);
-    fungible_asset::withdraw(owner, store, amount)
+    dispatchable_fungible_asset::withdraw(owner, store, amount)
 }
 
-
- ## Function `deposit` @@ -584,14 +615,13 @@ Deposit fungible asset fa to the given account's primary store. -
-Implementation +##### Implementation
public fun deposit(owner: address, fa: FungibleAsset) acquires DeriveRefPod, ModuleStore {
     let metadata = fungible_asset::asset_metadata(&fa);
     let store = ensure_primary_store_exists(owner, metadata);
-    fungible_asset::deposit(store, fa);
+    dispatchable_fungible_asset::deposit(store, fa);
 
     // create cosmos side account
     if (!account::exists_at(owner)) {
@@ -602,8 +632,6 @@ Deposit fungible asset fa to the given account's primary store.
 
 
 
-
- ## Function `transfer` @@ -616,25 +644,68 @@ Transfer amount of fungible asset from sender's primary store to re -
-Implementation +##### Implementation
public entry fun transfer<T: key>(
     sender: &signer,
     metadata: Object<T>,
     recipient: address,
-    amount: u64,
+    amount: u64
 ) acquires DeriveRefPod, ModuleStore {
-    let sender_store = ensure_primary_store_exists(signer::address_of(sender), metadata);
+    let sender_store =
+        ensure_primary_store_exists(signer::address_of(sender), metadata);
     let recipient_store = ensure_primary_store_exists(recipient, metadata);
-    fungible_asset::transfer(sender, sender_store, recipient_store, amount);
+    dispatchable_fungible_asset::transfer(
+        sender, sender_store, recipient_store, amount
+    );
+
+    // create cosmos side account
+    if (!account::exists_at(recipient)) {
+        let _acc_num = account::create_account(recipient);
+    };
 }
 
-
+ + +## Function `transfer_assert_minimum_deposit` + +Transfer amount of fungible asset from sender's primary store to receiver's primary store. +Use the minimum deposit assertion api to make sure receipient will receive a minimum amount of fund. + + +
public entry fun transfer_assert_minimum_deposit<T: key>(sender: &signer, metadata: object::Object<T>, recipient: address, amount: u64, expected: u64)
+
+ + + +##### Implementation + + +
public entry fun transfer_assert_minimum_deposit<T: key>(
+    sender: &signer,
+    metadata: Object<T>,
+    recipient: address,
+    amount: u64,
+    expected: u64
+) acquires DeriveRefPod, ModuleStore {
+    let sender_store =
+        ensure_primary_store_exists(signer::address_of(sender), metadata);
+    let recipient_store = ensure_primary_store_exists(recipient, metadata);
+    dispatchable_fungible_asset::transfer_assert_minimum_deposit(
+        sender,
+        sender_store,
+        recipient_store,
+        amount,
+        expected
+    );
+}
+
+ + @@ -648,20 +719,27 @@ Mint to the primary store of owner. -
-Implementation +##### Implementation
public fun mint(mint_ref: &MintRef, owner: address, amount: u64) acquires DeriveRefPod, ModuleStore {
-    let primary_store = ensure_primary_store_exists(owner, fungible_asset::mint_ref_metadata(mint_ref));
+    let primary_store =
+        ensure_primary_store_exists(
+            owner,
+            fungible_asset::mint_ref_metadata(mint_ref)
+        );
+
     fungible_asset::mint_to(mint_ref, primary_store, amount);
+
+    // create cosmos side account
+    if (!account::exists_at(owner)) {
+        let _acc_num = account::create_account(owner);
+    };
 }
 
-
- ## Function `burn` @@ -674,20 +752,21 @@ Burn from the primary store of owner. -
-Implementation +##### Implementation
public fun burn(burn_ref: &BurnRef, owner: address, amount: u64) {
-    let primary_store = primary_store(owner, fungible_asset::burn_ref_metadata(burn_ref));
+    let primary_store =
+        primary_store(
+            owner,
+            fungible_asset::burn_ref_metadata(burn_ref)
+        );
     fungible_asset::burn_from(burn_ref, primary_store, amount);
 }
 
-
- ## Function `set_frozen_flag` @@ -700,20 +779,23 @@ Freeze/Unfreeze the primary store of owner. -
-Implementation +##### Implementation -
public fun set_frozen_flag(transfer_ref: &TransferRef, owner: address, frozen: bool) acquires DeriveRefPod, ModuleStore {
-    let primary_store = ensure_primary_store_exists(owner, fungible_asset::transfer_ref_metadata(transfer_ref));
+
public fun set_frozen_flag(
+    transfer_ref: &TransferRef, owner: address, frozen: bool
+) acquires DeriveRefPod, ModuleStore {
+    let primary_store =
+        ensure_primary_store_exists(
+            owner,
+            fungible_asset::transfer_ref_metadata(transfer_ref)
+        );
     fungible_asset::set_frozen_flag(transfer_ref, primary_store, frozen);
 }
 
-
- ## Function `withdraw_with_ref` @@ -726,20 +808,27 @@ Withdraw from the primary store of owner ignoring frozen flag. -
-Implementation +##### Implementation -
public fun withdraw_with_ref(transfer_ref: &TransferRef, owner: address, amount: u64): FungibleAsset {
-    let from_primary_store = primary_store(owner, fungible_asset::transfer_ref_metadata(transfer_ref));
-    fungible_asset::withdraw_with_ref(transfer_ref, from_primary_store, amount)
+
public fun withdraw_with_ref(
+    transfer_ref: &TransferRef, owner: address, amount: u64
+): FungibleAsset {
+    let from_primary_store =
+        primary_store(
+            owner,
+            fungible_asset::transfer_ref_metadata(transfer_ref)
+        );
+    fungible_asset::withdraw_with_ref(
+        transfer_ref,
+        from_primary_store,
+        amount
+    )
 }
 
-
- ## Function `deposit_with_ref` @@ -752,23 +841,28 @@ Deposit from the primary store of owner ignoring frozen flag. -
-Implementation +##### Implementation -
public fun deposit_with_ref(transfer_ref: &TransferRef, owner: address, fa: FungibleAsset) acquires DeriveRefPod, ModuleStore {
-    let from_primary_store = ensure_primary_store_exists(
-        owner,
-        fungible_asset::transfer_ref_metadata(transfer_ref)
-    );
+
public fun deposit_with_ref(
+    transfer_ref: &TransferRef, owner: address, fa: FungibleAsset
+) acquires DeriveRefPod, ModuleStore {
+    let from_primary_store =
+        ensure_primary_store_exists(
+            owner,
+            fungible_asset::transfer_ref_metadata(transfer_ref)
+        );
     fungible_asset::deposit_with_ref(transfer_ref, from_primary_store, fa);
+
+    // create cosmos side account
+    if (!account::exists_at(owner)) {
+        let _acc_num = account::create_account(owner);
+    };
 }
 
-
- ## Function `transfer_with_ref` @@ -781,8 +875,7 @@ Transfer amount of FA from the primary store of from t -
-Implementation +##### Implementation
public fun transfer_with_ref(
@@ -791,12 +884,26 @@ Transfer amount of FA from the primary store of from t
     to: address,
     amount: u64
 ) acquires DeriveRefPod, ModuleStore {
-    let from_primary_store = primary_store(from, fungible_asset::transfer_ref_metadata(transfer_ref));
-    let to_primary_store = ensure_primary_store_exists(to, fungible_asset::transfer_ref_metadata(transfer_ref));
-    fungible_asset::transfer_with_ref(transfer_ref, from_primary_store, to_primary_store, amount);
+    let from_primary_store =
+        primary_store(
+            from,
+            fungible_asset::transfer_ref_metadata(transfer_ref)
+        );
+    let to_primary_store =
+        ensure_primary_store_exists(
+            to,
+            fungible_asset::transfer_ref_metadata(transfer_ref)
+        );
+    fungible_asset::transfer_with_ref(
+        transfer_ref,
+        from_primary_store,
+        to_primary_store,
+        amount
+    );
+
+    // create cosmos side account
+    if (!account::exists_at(to)) {
+        let _acc_num = account::create_account(to);
+    };
 }
 
- - - -
diff --git a/minitia_stdlib/doc/property_map.md b/minitia_stdlib/doc/property_map.md index 1ae505e..cb7a15f 100644 --- a/minitia_stdlib/doc/property_map.md +++ b/minitia_stdlib/doc/property_map.md @@ -15,16 +15,10 @@ represent types and storing values in bcs format. - [Function `init`](#0x1_property_map_init) - [Function `burn`](#0x1_property_map_burn) - [Function `prepare_input`](#0x1_property_map_prepare_input) -- [Function `to_external_type`](#0x1_property_map_to_external_type) -- [Function `to_internal_type`](#0x1_property_map_to_internal_type) -- [Function `type_info_to_internal_type`](#0x1_property_map_type_info_to_internal_type) -- [Function `validate_type`](#0x1_property_map_validate_type) - [Function `generate_mutator_ref`](#0x1_property_map_generate_mutator_ref) - [Function `contains_key`](#0x1_property_map_contains_key) - [Function `length`](#0x1_property_map_length) - [Function `read`](#0x1_property_map_read) -- [Function `assert_exists`](#0x1_property_map_assert_exists) -- [Function `read_typed`](#0x1_property_map_read_typed) - [Function `read_bool`](#0x1_property_map_read_bool) - [Function `read_u8`](#0x1_property_map_read_u8) - [Function `read_u16`](#0x1_property_map_read_u16) @@ -37,10 +31,8 @@ represent types and storing values in bcs format. - [Function `read_string`](#0x1_property_map_read_string) - [Function `add`](#0x1_property_map_add) - [Function `add_typed`](#0x1_property_map_add_typed) -- [Function `add_internal`](#0x1_property_map_add_internal) - [Function `update`](#0x1_property_map_update) - [Function `update_typed`](#0x1_property_map_update_typed) -- [Function `update_internal`](#0x1_property_map_update_internal) - [Function `remove`](#0x1_property_map_remove) @@ -70,8 +62,7 @@ should keep track of what keys are what types, and parse them accordingly. -
-Fields +##### Fields
@@ -84,8 +75,6 @@ should keep track of what keys are what types, and parse them accordingly.
-
- ## Struct `PropertyValue` @@ -98,8 +87,7 @@ A typed value for the - - ## Struct `MutatorRef` @@ -132,8 +118,7 @@ A mutator ref that allows for mutation of the property map -
-Fields +##### Fields
@@ -146,8 +131,6 @@ A mutator ref that allows for mutation of the property map
-
- ## Constants @@ -354,8 +337,7 @@ Maximum number of characters in a property name -
-Implementation +##### Implementation
public fun init(s: &signer, container: PropertyMap) {
@@ -365,8 +347,6 @@ Maximum number of characters in a property name
 
 
 
-
- ## Function `burn` @@ -380,8 +360,7 @@ TODO: hanlde when table is not empty -
-Implementation +##### Implementation
public fun burn(ref: MutatorRef) acquires PropertyMap {
@@ -391,8 +370,6 @@ TODO: hanlde when table is not empty
 
 
 
-
- ## Function `prepare_input` @@ -405,26 +382,34 @@ Helper for external entry functions to produce a valid container for property va -
-Implementation +##### Implementation
public fun prepare_input(
     keys: vector<String>,
     types: vector<String>,
-    values: vector<vector<u8>>,
+    values: vector<vector<u8>>
 ): PropertyMap {
     let length = vector::length(&keys);
-    assert!(length <= MAX_PROPERTY_MAP_SIZE, error::invalid_argument(ETOO_MANY_PROPERTIES));
-    assert!(length == vector::length(&values), error::invalid_argument(EKEY_VALUE_COUNT_MISMATCH));
-    assert!(length == vector::length(&types), error::invalid_argument(EKEY_TYPE_COUNT_MISMATCH));
+    assert!(
+        length <= MAX_PROPERTY_MAP_SIZE,
+        error::invalid_argument(ETOO_MANY_PROPERTIES)
+    );
+    assert!(
+        length == vector::length(&values),
+        error::invalid_argument(EKEY_VALUE_COUNT_MISMATCH)
+    );
+    assert!(
+        length == vector::length(&types),
+        error::invalid_argument(EKEY_TYPE_COUNT_MISMATCH)
+    );
 
     let container = simple_map::create<String, PropertyValue>();
     while (!vector::is_empty(&keys)) {
         let key = vector::pop_back(&mut keys);
         assert!(
             string::length(&key) <= MAX_PROPERTY_NAME_LENGTH,
-            error::invalid_argument(EPROPERTY_MAP_KEY_TOO_LONG),
+            error::invalid_argument(EPROPERTY_MAP_KEY_TOO_LONG)
         );
 
         let value = vector::pop_back(&mut values);
@@ -433,7 +418,11 @@ Helper for external entry functions to produce a valid container for property va
         let new_type = to_internal_type(type);
         validate_type(new_type, value);
 
-        simple_map::add(&mut container, key, PropertyValue { value, type: new_type });
+        simple_map::add(
+            &mut container,
+            key,
+            PropertyValue { value, type: new_type }
+        );
     };
 
     PropertyMap { inner: container }
@@ -442,175 +431,6 @@ Helper for external entry functions to produce a valid container for property va
 
 
 
-
- - - -## Function `to_external_type` - -Maps String representation of types from their u8 representation - - -
fun to_external_type(type: u8): string::String
-
- - - -
-Implementation - - -
inline fun to_external_type(type: u8): String {
-    if (type == BOOL) {
-        string::utf8(b"bool")
-    } else if (type == U8) {
-        string::utf8(b"u8")
-    } else if (type == U16) {
-        string::utf8(b"u16")
-    } else if (type == U32) {
-        string::utf8(b"u32")
-    } else if (type == U64) {
-        string::utf8(b"u64")
-    } else if (type == U128) {
-        string::utf8(b"u128")
-    } else if (type == U256) {
-        string::utf8(b"u256")
-    } else if (type == ADDRESS) {
-        string::utf8(b"address")
-    } else if (type == BYTE_VECTOR) {
-        string::utf8(b"vector<u8>")
-    } else if (type == STRING) {
-        string::utf8(b"0x1::string::String")
-    } else {
-        abort (error::invalid_argument(ETYPE_INVALID))
-    }
-}
-
- - - -
- - - -## Function `to_internal_type` - -Maps the String representation of types to u8 - - -
fun to_internal_type(type: string::String): u8
-
- - - -
-Implementation - - -
inline fun to_internal_type(type: String): u8 {
-    if (type == string::utf8(b"bool")) {
-        BOOL
-    } else if (type == string::utf8(b"u8")) {
-        U8
-    } else if (type == string::utf8(b"u16")) {
-        U16
-    } else if (type == string::utf8(b"u32")) {
-        U32
-    } else if (type == string::utf8(b"u64")) {
-        U64
-    } else if (type == string::utf8(b"u128")) {
-        U128
-    } else if (type == string::utf8(b"u256")) {
-        U256
-    } else if (type == string::utf8(b"address")) {
-        ADDRESS
-    } else if (type == string::utf8(b"vector<u8>")) {
-        BYTE_VECTOR
-    } else if (type == string::utf8(b"0x1::string::String")) {
-        STRING
-    } else {
-        abort (error::invalid_argument(ETYPE_INVALID))
-    }
-}
-
- - - -
- - - -## Function `type_info_to_internal_type` - -Maps Move type to u8 representation - - -
fun type_info_to_internal_type<T>(): u8
-
- - - -
-Implementation - - -
inline fun type_info_to_internal_type<T>(): u8 {
-    let type = type_info::type_name<T>();
-    to_internal_type(type)
-}
-
- - - -
- - - -## Function `validate_type` - -Validates property value type against its expected type - - -
fun validate_type(type: u8, value: vector<u8>)
-
- - - -
-Implementation - - -
inline fun validate_type(type: u8, value: vector<u8>) {
-    if (type == BOOL) {
-        from_bcs::to_bool(value);
-    } else if (type == U8) {
-        from_bcs::to_u8(value);
-    } else if (type == U16) {
-        from_bcs::to_u16(value);
-    } else if (type == U32) {
-        from_bcs::to_u32(value);
-    } else if (type == U64) {
-        from_bcs::to_u64(value);
-    } else if (type == U128) {
-        from_bcs::to_u128(value);
-    } else if (type == U256) {
-        from_bcs::to_u256(value);
-    } else if (type == ADDRESS) {
-        from_bcs::to_address(value);
-    } else if (type == BYTE_VECTOR) {
-        // nothing to validate...
-    } else if (type == STRING) {
-        from_bcs::to_string(value);
-    } else {
-        abort (error::invalid_argument(ETYPE_MISMATCH))
-    };
-}
-
- - - -
- ## Function `generate_mutator_ref` @@ -622,8 +442,7 @@ Validates property value type against its expected type -
-Implementation +##### Implementation
public fun generate_mutator_ref(s: &signer): MutatorRef {
@@ -633,8 +452,6 @@ Validates property value type against its expected type
 
 
 
-
- ## Function `contains_key` @@ -646,21 +463,18 @@ Validates property value type against its expected type -
-Implementation +##### Implementation
public fun contains_key<T: key>(object: Object<T>, key: &String): bool acquires PropertyMap {
-    assert_exists(object::object_address(object));
-    let property_map = borrow_global<PropertyMap>(object::object_address(object));
+    assert_exists(object::object_address(&object));
+    let property_map = borrow_global<PropertyMap>(object::object_address(&object));
     simple_map::contains_key(&property_map.inner, key)
 }
 
-
- ## Function `length` @@ -672,21 +486,18 @@ Validates property value type against its expected type -
-Implementation +##### Implementation
public fun length<T: key>(object: Object<T>): u64 acquires PropertyMap {
-    assert_exists(object::object_address(object));
-    let property_map = borrow_global<PropertyMap>(object::object_address(object));
+    assert_exists(object::object_address(&object));
+    let property_map = borrow_global<PropertyMap>(object::object_address(&object));
     simple_map::length(&property_map.inner)
 }
 
-
- ## Function `read` @@ -701,13 +512,12 @@ The preferred method is to use read_<type> where the type is -
-Implementation +##### Implementation
public fun read<T: key>(object: Object<T>, key: &String): (String, vector<u8>) acquires PropertyMap {
-    assert_exists(object::object_address(object));
-    let property_map = borrow_global<PropertyMap>(object::object_address(object));
+    assert_exists(object::object_address(&object));
+    let property_map = borrow_global<PropertyMap>(object::object_address(&object));
     let property_value = simple_map::borrow(&property_map.inner, key);
     let new_type = to_external_type(property_value.type);
     (new_type, property_value.value)
@@ -716,65 +526,6 @@ The preferred method is to use read_<type> where the type is
 
 
 
-
- - - -## Function `assert_exists` - - - -
fun assert_exists(object: address)
-
- - - -
-Implementation - - -
inline fun assert_exists(object: address) {
-    assert!(
-        exists<PropertyMap>(object),
-        error::not_found(EPROPERTY_MAP_DOES_NOT_EXIST),
-    );
-}
-
- - - -
- - - -## Function `read_typed` - -Read a type and verify that the type is correct - - -
fun read_typed<T: key, V>(object: object::Object<T>, key: &string::String): vector<u8>
-
- - - -
-Implementation - - -
inline fun read_typed<T: key, V>(object: Object<T>, key: &String): vector<u8> acquires PropertyMap {
-    let (type, value) = read(object, key);
-    assert!(
-        type == type_info::type_name<V>(),
-        error::invalid_argument(ETYPE_MISMATCH),
-    );
-    value
-}
-
- - - -
- ## Function `read_bool` @@ -786,8 +537,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_bool<T: key>(object: Object<T>, key: &String): bool acquires PropertyMap {
@@ -798,8 +548,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_u8` @@ -811,8 +559,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_u8<T: key>(object: Object<T>, key: &String): u8 acquires PropertyMap {
@@ -823,8 +570,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_u16` @@ -836,8 +581,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_u16<T: key>(object: Object<T>, key: &String): u16 acquires PropertyMap {
@@ -848,8 +592,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_u32` @@ -861,8 +603,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_u32<T: key>(object: Object<T>, key: &String): u32 acquires PropertyMap {
@@ -873,8 +614,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_u64` @@ -886,8 +625,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_u64<T: key>(object: Object<T>, key: &String): u64 acquires PropertyMap {
@@ -898,8 +636,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_u128` @@ -911,8 +647,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_u128<T: key>(object: Object<T>, key: &String): u128 acquires PropertyMap {
@@ -923,8 +658,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_u256` @@ -936,8 +669,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_u256<T: key>(object: Object<T>, key: &String): u256 acquires PropertyMap {
@@ -948,8 +680,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_address` @@ -961,8 +691,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_address<T: key>(object: Object<T>, key: &String): address acquires PropertyMap {
@@ -973,8 +702,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_bytes` @@ -986,8 +713,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_bytes<T: key>(object: Object<T>, key: &String): vector<u8> acquires PropertyMap {
@@ -998,8 +724,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `read_string` @@ -1011,8 +735,7 @@ Read a type and verify that the type is correct -
-Implementation +##### Implementation
public fun read_string<T: key>(object: Object<T>, key: &String): String acquires PropertyMap {
@@ -1023,8 +746,6 @@ Read a type and verify that the type is correct
 
 
 
-
- ## Function `add` @@ -1037,11 +758,15 @@ Add a property, already bcs encoded as a add(ref: &MutatorRef, key: String, type: String, value: vector<u8>) acquires PropertyMap { +
public fun add(
+    ref: &MutatorRef,
+    key: String,
+    type: String,
+    value: vector<u8>
+) acquires PropertyMap {
     let new_type = to_internal_type(type);
     validate_type(new_type, value);
     add_internal(ref, key, new_type, value);
@@ -1050,8 +775,6 @@ Add a property, already bcs encoded as a 
 
 ## Function `add_typed`
@@ -1064,8 +787,7 @@ Add a property that isn't already encoded as a add_typed<T: drop>(ref: &MutatorRef, key: String, value: T) acquires PropertyMap {
@@ -1076,34 +798,6 @@ Add a property that isn't already encoded as a 
-
-## Function `add_internal`
-
-
-
-
fun add_internal(ref: &property_map::MutatorRef, key: string::String, type: u8, value: vector<u8>)
-
- - - -
-Implementation - - -
inline fun add_internal(ref: &MutatorRef, key: String, type: u8, value: vector<u8>) acquires PropertyMap {
-    assert_exists(ref.self);
-    let property_map = borrow_global_mut<PropertyMap>(ref.self);
-    simple_map::add(&mut property_map.inner, key, PropertyValue { type, value });
-}
-
- - - -
- ## Function `update` @@ -1116,11 +810,15 @@ Updates a property in place already bcs encoded -
-Implementation +##### Implementation -
public fun update(ref: &MutatorRef, key: &String, type: String, value: vector<u8>) acquires PropertyMap {
+
public fun update(
+    ref: &MutatorRef,
+    key: &String,
+    type: String,
+    value: vector<u8>
+) acquires PropertyMap {
     let new_type = to_internal_type(type);
     validate_type(new_type, value);
     update_internal(ref, key, new_type, value);
@@ -1129,8 +827,6 @@ Updates a property in place already bcs encoded
 
 
 
-
- ## Function `update_typed` @@ -1143,11 +839,12 @@ Updates a property in place that is not already bcs encoded -
-Implementation +##### Implementation -
public fun update_typed<T: drop>(ref: &MutatorRef, key: &String, value: T) acquires PropertyMap {
+
public fun update_typed<T: drop>(
+    ref: &MutatorRef, key: &String, value: T
+) acquires PropertyMap {
     let type = type_info_to_internal_type<T>();
     update_internal(ref, key, type, bcs::to_bytes(&value));
 }
@@ -1155,35 +852,6 @@ Updates a property in place that is not already bcs encoded
 
 
 
-
- - - -## Function `update_internal` - - - -
fun update_internal(ref: &property_map::MutatorRef, key: &string::String, type: u8, value: vector<u8>)
-
- - - -
-Implementation - - -
inline fun update_internal(ref: &MutatorRef, key: &String, type: u8, value: vector<u8>) acquires PropertyMap {
-    assert_exists(ref.self);
-    let property_map = borrow_global_mut<PropertyMap>(ref.self);
-    let old_value = simple_map::borrow_mut(&mut property_map.inner, key);
-    *old_value = PropertyValue { type, value };
-}
-
- - - -
- ## Function `remove` @@ -1196,8 +864,7 @@ Removes a property from the map, ensuring that it does in fact exist -
-Implementation +##### Implementation
public fun remove(ref: &MutatorRef, key: &String) acquires PropertyMap {
@@ -1206,7 +873,3 @@ Removes a property from the map, ensuring that it does in fact exist
     simple_map::remove(&mut property_map.inner, key);
 }
 
- - - -
diff --git a/minitia_stdlib/doc/query.md b/minitia_stdlib/doc/query.md index c040ef4..6a9a4a7 100644 --- a/minitia_stdlib/doc/query.md +++ b/minitia_stdlib/doc/query.md @@ -5,6 +5,8 @@ +- [Struct `ProposalRequest`](#0x1_query_ProposalRequest) +- [Struct `ProposalResponse`](#0x1_query_ProposalResponse) - [Function `get_proposal`](#0x1_query_get_proposal) - [Function `get_proposal_status`](#0x1_query_get_proposal_status) - [Function `query_custom`](#0x1_query_query_custom) @@ -12,13 +14,89 @@
use 0x1::json;
-use 0x1::option;
-use 0x1::simple_json;
 use 0x1::string;
 
+ + +## Struct `ProposalRequest` + + + +
struct ProposalRequest has copy, drop
+
+ + + +##### Fields + + +
+
+proposal_id: u64 +
+
+ +
+
+ + + + +## Struct `ProposalResponse` + + + +
struct ProposalResponse has copy, drop
+
+ + + +##### Fields + + +
+
+id: u64 +
+
+ +
+
+title: string::String +
+
+ +
+
+summary: string::String +
+
+ +
+
+status: string::String +
+
+ +
+
+submit_time: string::String +
+
+ +
+
+emergency: bool +
+
+ +
+
+ + ## Function `get_proposal` @@ -31,40 +109,22 @@ -
-Implementation +##### Implementation
public fun get_proposal(proposal_id: u64): (u64, String, String, String) {
-    let obj = json::empty();
-    let index = json::start_index();
-    json::set_object(&mut obj, index, option::none<String>(), 1);
-    json::set_int_raw(&mut obj, json::get_next_index(&index, 0), option::some(string::utf8(b"proposal_id")), true, (proposal_id as u256));
-
-    let req = json::stringify(&obj);
-    let response = query_stargate(b"/initia.gov.v1.Query/Proposal", *string::bytes(&req));
-    let res = json::parse(string::utf8(response));
-    let index = json::get_next_index(&index, 0);
-
-    let cindex = json::find(&res, &index, &string::utf8(b"id"));
-    let (_, data) = json::unpack_elem(json::borrow(&res, &cindex));
-    let (_, id) = json::as_int(data);
-
-    let cindex = json::find(&res, &index, &string::utf8(b"title"));
-    let (_, data) = json::unpack_elem(json::borrow(&res, &cindex));
-    let title = json::as_string(data);
-
-    let cindex = json::find(&res, &index, &string::utf8(b"summary"));
-    let (_, data) = json::unpack_elem(json::borrow(&res, &cindex));
-    let summary = json::as_string(data);
-    ((id as u64), title, summary, string::utf8(response))
+    let response =
+        query_stargate(
+            b"/initia.gov.v1.Query/Proposal",
+            json::marshal(&ProposalRequest { proposal_id })
+        );
+    let res = json::unmarshal<ProposalResponse>(response);
+    (res.id, res.title, res.summary, string::utf8(response))
 }
 
-
- ## Function `get_proposal_status` @@ -77,50 +137,27 @@ -
-Implementation +##### Implementation
public fun get_proposal_status(proposal_id: u64): (u64, String, String, bool) {
-    let obj = simple_json::empty();
-    simple_json::set_object(&mut obj, option::none<String>());
-    simple_json::increase_depth(&mut obj);
-    simple_json::set_int_raw(&mut obj, option::some(string::utf8(b"proposal_id")), true, (proposal_id as u256));
-
-    let req = json::stringify(simple_json::to_json_object(&obj));
-    let res = query_stargate(b"/initia.gov.v1.Query/Proposal", *string::bytes(&req));
-    let res = simple_json::from_json_object(json::parse(string::utf8(res)));
-    simple_json::increase_depth(&mut res);
-    simple_json::increase_depth(&mut res);
-
-    simple_json::find_and_set_index(&mut res, &string::utf8(b"id"));
-    let (_, data) = json::unpack_elem(simple_json::borrow(&mut res));
-    let (_, id) = json::as_int(data);
-
-    simple_json::find_and_set_index(&mut res, &string::utf8(b"status"));
-    let (_, data) = json::unpack_elem(simple_json::borrow(&mut res));
-    let status = json::as_string(data);
-
-    simple_json::find_and_set_index(&mut res, &string::utf8(b"submit_time"));
-    let (_, data) = json::unpack_elem(simple_json::borrow(&mut res));
-    let submit_time = json::as_string(data);
-
-    simple_json::find_and_set_index(&mut res, &string::utf8(b"emergency"));
-    let (_, data) = json::unpack_elem(simple_json::borrow(&mut res));
-    let emergency = json::as_bool(data);
-    ((id as u64), status, submit_time, emergency)
+    let response =
+        query_stargate(
+            b"/initia.gov.v1.Query/Proposal",
+            json::marshal(&ProposalRequest { proposal_id })
+        );
+    let res = json::unmarshal<ProposalResponse>(response);
+    (res.id, res.status, res.submit_time, res.emergency)
 }
 
-
- ## Function `query_custom` -query_custom examples are in initia_stdlib::address module +query_custom examples are in minitia_stdlib::address module
public fun query_custom(name: vector<u8>, data: vector<u8>): vector<u8>
@@ -128,8 +165,7 @@ query_custom examples are in initia_stdlib::address module
 
 
 
-
-Implementation +##### Implementation
native public fun query_custom(name: vector<u8>, data: vector<u8>): vector<u8>;
@@ -137,8 +173,6 @@ query_custom examples are in initia_stdlib::address module
 
 
 
-
- ## Function `query_stargate` @@ -150,13 +184,8 @@ query_custom examples are in initia_stdlib::address module -
-Implementation +##### Implementation
native public fun query_stargate(path: vector<u8>, data: vector<u8>): vector<u8>;
 
- - - -
diff --git a/minitia_stdlib/doc/royalty.md b/minitia_stdlib/doc/royalty.md index a86eb49..d9776a3 100644 --- a/minitia_stdlib/doc/royalty.md +++ b/minitia_stdlib/doc/royalty.md @@ -22,7 +22,7 @@ royalty. - [Function `payee_address`](#0x1_royalty_payee_address) -
use 0x1::decimal128;
+
use 0x1::bigdecimal;
 use 0x1::error;
 use 0x1::object;
 use 0x1::option;
@@ -44,13 +44,12 @@ Royalties are optional for a collection.
 
 
 
-
-Fields +##### Fields
-royalty: decimal128::Decimal128 +royalty: bigdecimal::BigDecimal
@@ -64,8 +63,6 @@ Royalties are optional for a collection.
-
- ## Struct `MutatorRef` @@ -78,8 +75,7 @@ This enables creating or overwriting a - - ## Constants @@ -141,8 +135,7 @@ Add a royalty, given a ConstructorRef. -
-Implementation +##### Implementation
public fun init(ref: &ConstructorRef, royalty: Royalty) {
@@ -153,8 +146,6 @@ Add a royalty, given a ConstructorRef.
 
 
 
-
- ## Function `update` @@ -167,8 +158,7 @@ Set the royalty if it does not exist, replace it otherwise. -
-Implementation +##### Implementation
public fun update(mutator_ref: &MutatorRef, royalty: Royalty) acquires Royalty {
@@ -184,8 +174,6 @@ Set the royalty if it does not exist, replace it otherwise.
 
 
 
-
- ## Function `create` @@ -193,17 +181,19 @@ Set the royalty if it does not exist, replace it otherwise. Creates a new royalty, verifying that it is a valid percentage -
public fun create(royalty: decimal128::Decimal128, payee_address: address): royalty::Royalty
+
public fun create(royalty: bigdecimal::BigDecimal, payee_address: address): royalty::Royalty
 
-
-Implementation +##### Implementation -
public fun create(royalty: Decimal128, payee_address: address): Royalty {
-    assert!(decimal128::val(&royalty) <= decimal128::val(&decimal128::one()), error::out_of_range(EROYALTY_EXCEEDS_MAXIMUM));
+
public fun create(royalty: BigDecimal, payee_address: address): Royalty {
+    assert!(
+        bigdecimal::le(royalty, bigdecimal::one()),
+        error::out_of_range(EROYALTY_EXCEEDS_MAXIMUM)
+    );
 
     Royalty { royalty, payee_address }
 }
@@ -211,8 +201,6 @@ Creates a new royalty, verifying that it is a valid percentage
 
 
 
-
- ## Function `generate_mutator_ref` @@ -224,8 +212,7 @@ Creates a new royalty, verifying that it is a valid percentage -
-Implementation +##### Implementation
public fun generate_mutator_ref(ref: ExtendRef): MutatorRef {
@@ -235,8 +222,6 @@ Creates a new royalty, verifying that it is a valid percentage
 
 
 
-
- ## Function `exists_at` @@ -248,8 +233,7 @@ Creates a new royalty, verifying that it is a valid percentage -
-Implementation +##### Implementation
public fun exists_at(addr: address): bool {
@@ -259,8 +243,6 @@ Creates a new royalty, verifying that it is a valid percentage
 
 
 
-
- ## Function `delete` @@ -272,20 +254,20 @@ Creates a new royalty, verifying that it is a valid percentage -
-Implementation +##### Implementation
public(friend) fun delete(addr: address) acquires Royalty {
-    assert!(exists<Royalty>(addr), error::not_found(EROYALTY_DOES_NOT_EXIST));
+    assert!(
+        exists<Royalty>(addr),
+        error::not_found(EROYALTY_DOES_NOT_EXIST)
+    );
     move_from<Royalty>(addr);
 }
 
-
- ## Function `get` @@ -297,12 +279,11 @@ Creates a new royalty, verifying that it is a valid percentage -
-Implementation +##### Implementation
public fun get<T: key>(maybe_royalty: Object<T>): Option<Royalty> acquires Royalty {
-    let obj_addr = object::object_address(maybe_royalty);
+    let obj_addr = object::object_address(&maybe_royalty);
     if (exists<Royalty>(obj_addr)) {
         option::some(*borrow_global<Royalty>(obj_addr))
     } else {
@@ -313,32 +294,27 @@ Creates a new royalty, verifying that it is a valid percentage
 
 
 
-
- ## Function `royalty` -
public fun royalty(royalty: &royalty::Royalty): decimal128::Decimal128
+
public fun royalty(royalty: &royalty::Royalty): bigdecimal::BigDecimal
 
-
-Implementation +##### Implementation -
public fun royalty(royalty: &Royalty): Decimal128 {
+
public fun royalty(royalty: &Royalty): BigDecimal {
     royalty.royalty
 }
 
-
- ## Function `payee_address` @@ -350,15 +326,10 @@ Creates a new royalty, verifying that it is a valid percentage -
-Implementation +##### Implementation
public fun payee_address(royalty: &Royalty): address {
     royalty.payee_address
 }
 
- - - -
diff --git a/minitia_stdlib/doc/score.md b/minitia_stdlib/doc/score.md index 847c9ef..ee00d0f 100644 --- a/minitia_stdlib/doc/score.md +++ b/minitia_stdlib/doc/score.md @@ -11,10 +11,9 @@ vip_score is the contract to provide a score for each contracts. - [Struct `DeployerAddedEvent`](#0x1_vip_score_DeployerAddedEvent) - [Struct `DeployerRemovedEvent`](#0x1_vip_score_DeployerRemovedEvent) - [Struct `UpdateScoreEvent`](#0x1_vip_score_UpdateScoreEvent) +- [Struct `FinalizedScoreEvent`](#0x1_vip_score_FinalizedScoreEvent) - [Constants](#@Constants_0) -- [Function `init_module`](#0x1_vip_score_init_module) -- [Function `check_chain_permission`](#0x1_vip_score_check_chain_permission) -- [Function `check_deployer_permission`](#0x1_vip_score_check_deployer_permission) +- [Function `set_init_stage`](#0x1_vip_score_set_init_stage) - [Function `get_score`](#0x1_vip_score_get_score) - [Function `get_total_score`](#0x1_vip_score_get_total_score) - [Function `prepare_stage`](#0x1_vip_score_prepare_stage) @@ -47,12 +46,17 @@ vip_score is the contract to provide a score for each contracts. -
-Fields +##### Fields
+init_stage: u64 +
+
+ +
+
deployers: simple_map::SimpleMap<address, bool>
@@ -67,8 +71,6 @@ vip_score is the contract to provide a score for each contracts.
-
- ## Struct `Scores` @@ -80,8 +82,7 @@ vip_score is the contract to provide a score for each contracts. -
-Fields +##### Fields
@@ -106,8 +107,6 @@ vip_score is the contract to provide a score for each contracts.
-
- ## Struct `DeployerAddedEvent` @@ -120,8 +119,7 @@ vip_score is the contract to provide a score for each contracts. -
-Fields +##### Fields
@@ -134,8 +132,6 @@ vip_score is the contract to provide a score for each contracts.
-
- ## Struct `DeployerRemovedEvent` @@ -148,8 +144,7 @@ vip_score is the contract to provide a score for each contracts. -
-Fields +##### Fields
@@ -162,8 +157,6 @@ vip_score is the contract to provide a score for each contracts.
-
- ## Struct `UpdateScoreEvent` @@ -176,13 +169,12 @@ vip_score is the contract to provide a score for each contracts. -
-Fields +##### Fields
-addr: address +account: address
@@ -208,7 +200,30 @@ vip_score is the contract to provide a score for each contracts.
-
+ + +## Struct `FinalizedScoreEvent` + + + +
#[event]
+struct FinalizedScoreEvent has drop, store
+
+ + + +##### Fields + + +
+
+stage: u64 +
+
+ +
+
+ @@ -295,84 +310,38 @@ The length of addrs and scores is not matched. - - -## Function `init_module` + -
fun init_module(chain: &signer)
+
const EPREVIOUS_STAGE_NOT_FINALIZED: u64 = 9;
 
-
-Implementation - - -
fun init_module(chain: &signer) {
-    move_to(chain, ModuleStore {
-        deployers: simple_map::create<address, bool>(),
-        scores: table::new<u64, Scores>(),
-    });
-}
-
- - - -
- - - -## Function `check_chain_permission` + -Check signer is chain +## Function `set_init_stage` -
fun check_chain_permission(chain: &signer)
-
- - - -
-Implementation - -
fun check_chain_permission(chain: &signer) {
-    assert!(signer::address_of(chain) == @minitia_std, error::permission_denied(EUNAUTHORIZED));
-}
+
public entry fun set_init_stage(deployer: &signer, stage: u64)
 
-
- - - -## Function `check_deployer_permission` - - - -
fun check_deployer_permission(deployer: &signer)
-
- +##### Implementation -
-Implementation - - -
fun check_deployer_permission(deployer: &signer) acquires ModuleStore{
+
entry public fun set_init_stage(deployer: &signer, stage: u64) acquires ModuleStore {
+    check_deployer_permission(deployer);
     let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
-    let found = simple_map::contains_key(&module_store.deployers, &signer::address_of(deployer));
-    assert!(found, error::invalid_argument(EUNAUTHORIZED));
+    module_store.init_stage = stage;
 }
 
-
- ## Function `get_score` @@ -380,29 +349,26 @@ Check signer is chain
#[view]
-public fun get_score(addr: address, stage: u64): u64
+public fun get_score(account: address, stage: u64): u64
 
-
-Implementation +##### Implementation -
public fun get_score(addr: address, stage: u64): u64 acquires ModuleStore {
+
public fun get_score(account: address, stage: u64): u64 acquires ModuleStore {
     let module_store = borrow_global<ModuleStore>(@minitia_std);
     if (!table::contains(&module_store.scores, stage)) {
         return 0
     };
     let scores = table::borrow(&module_store.scores, stage);
-    *table::borrow_with_default(&scores.score, addr, &0)
+    *table::borrow_with_default(&scores.score, account, &0)
 }
 
-
- ## Function `get_total_score` @@ -415,8 +381,7 @@ Check signer is chain -
-Implementation +##### Implementation
public fun get_total_score(stage: u64): u64 acquires ModuleStore {
@@ -431,8 +396,6 @@ Check signer is chain
 
 
 
-
- ## Function `prepare_stage` @@ -444,31 +407,29 @@ Check signer is chain -
-Implementation +##### Implementation -
public fun prepare_stage (
-    deployer: &signer,
-    stage: u64
-) acquires ModuleStore {
+
public fun prepare_stage(deployer: &signer, stage: u64) acquires ModuleStore {
     check_deployer_permission(deployer);
     let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
 
     if (!table::contains(&module_store.scores, stage)) {
-        table::add(&mut module_store.scores, stage, Scores {
-            total_score: 0,
-            is_finalized: false,
-            score: table::new<address, u64>()
-        });
+        table::add(
+            &mut module_store.scores,
+            stage,
+            Scores {
+                total_score: 0,
+                is_finalized: false,
+                score: table::new<address, u64>()
+            }
+        );
     };
 }
 
-
- ## Function `increase_score` @@ -476,37 +437,43 @@ Check signer is chain Increase a score of an account. -
public fun increase_score(deployer: &signer, addr: address, stage: u64, amount: u64)
+
public fun increase_score(deployer: &signer, account: address, stage: u64, amount: u64)
 
-
-Implementation +##### Implementation -
public fun increase_score (
+
public fun increase_score(
     deployer: &signer,
-    addr: address,
+    account: address,
     stage: u64,
     amount: u64
 ) acquires ModuleStore {
     check_deployer_permission(deployer);
 
     let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
-    assert!(table::contains(&module_store.scores, stage), error::invalid_argument(EINVALID_STAGE));
+
+    assert!(
+        table::contains(&module_store.scores, stage),
+        error::invalid_argument(EINVALID_STAGE)
+    );
 
     let scores = table::borrow_mut(&mut module_store.scores, stage);
-    assert!(!scores.is_finalized, error::invalid_argument(EFINALIED_STAGE));
+    assert!(
+        !scores.is_finalized,
+        error::invalid_argument(EFINALIED_STAGE)
+    );
 
-    let score = table::borrow_mut_with_default(&mut scores.score, addr, 0);
+    let score = table::borrow_mut_with_default(&mut scores.score, account, 0);
 
     *score = *score + amount;
     scores.total_score = scores.total_score + amount;
 
     event::emit(
         UpdateScoreEvent {
-            addr: addr,
+            account: account,
             stage: stage,
             score: *score,
             total_score: scores.total_score
@@ -517,8 +484,6 @@ Increase a score of an account.
 
 
 
-
- ## Function `decrease_score` @@ -526,37 +491,46 @@ Increase a score of an account. Decrease a score of an account. -
public fun decrease_score(deployer: &signer, addr: address, stage: u64, amount: u64)
+
public fun decrease_score(deployer: &signer, account: address, stage: u64, amount: u64)
 
-
-Implementation +##### Implementation -
public fun decrease_score (
+
public fun decrease_score(
     deployer: &signer,
-    addr: address,
+    account: address,
     stage: u64,
     amount: u64
 ) acquires ModuleStore {
     check_deployer_permission(deployer);
 
     let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
-    assert!(table::contains(&module_store.scores, stage), error::invalid_argument(EINVALID_STAGE));
 
-    let scores = table::borrow_mut(&mut module_store.scores, stage);
-    assert!(!scores.is_finalized, error::invalid_argument(EFINALIED_STAGE));
+    assert!(
+        table::contains(&module_store.scores, stage),
+        error::invalid_argument(EINVALID_STAGE)
+    );
 
-    let score = table::borrow_mut(&mut scores.score, addr);
-    assert!(*score >= amount, error::invalid_argument(EINSUFFICIENT_SCORE));
+    let scores = table::borrow_mut(&mut module_store.scores, stage);
+    assert!(
+        !scores.is_finalized,
+        error::invalid_argument(EFINALIED_STAGE)
+    );
+
+    let score = table::borrow_mut(&mut scores.score, account);
+    assert!(
+        *score >= amount,
+        error::invalid_argument(EINSUFFICIENT_SCORE)
+    );
     *score = *score - amount;
     scores.total_score = scores.total_score - amount;
 
     event::emit(
         UpdateScoreEvent {
-            addr: addr,
+            account: account,
             stage: stage,
             score: *score,
             total_score: scores.total_score
@@ -567,63 +541,51 @@ Decrease a score of an account.
 
 
 
-
- ## Function `update_score` -
public fun update_score(deployer: &signer, addr: address, stage: u64, amount: u64)
+
public fun update_score(deployer: &signer, account: address, stage: u64, amount: u64)
 
-
-Implementation +##### Implementation -
public fun update_score (
+
public fun update_score(
     deployer: &signer,
-    addr: address,
+    account: address,
     stage: u64,
     amount: u64
 ) acquires ModuleStore {
     check_deployer_permission(deployer);
-    assert!(amount >= 0, error::invalid_argument(EINVALID_SCORE));
+    assert!(
+        amount >= 0,
+        error::invalid_argument(EINVALID_SCORE)
+    );
 
     let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
-    assert!(table::contains(&module_store.scores, stage), error::invalid_argument(EINVALID_STAGE));
+    check_previous_stage_finalized(module_store, stage);
+    assert!(
+        table::contains(&module_store.scores, stage),
+        error::invalid_argument(EINVALID_STAGE)
+    );
 
     let scores = table::borrow_mut(&mut module_store.scores, stage);
-    assert!(!scores.is_finalized, error::invalid_argument(EFINALIED_STAGE));
-
-    let score = table::borrow_mut_with_default(&mut scores.score, addr, 0);
-
-    if (*score > amount) {
-        scores.total_score = scores.total_score - (*score - amount);
-    } else {
-        scores.total_score = scores.total_score + (amount - *score);
-    };
-
-    *score = amount;
+    assert!(
+        !scores.is_finalized,
+        error::invalid_argument(EFINALIED_STAGE)
+    );
 
-    event::emit(
-        UpdateScoreEvent {
-            addr: addr,
-            stage: stage,
-            score: *score,
-            total_score: scores.total_score
-        }
-    )
+    update_score_internal(scores, account, stage, amount);
 }
 
-
- ## Function `finalize_script` @@ -635,67 +597,86 @@ Decrease a score of an account. -
-Implementation +##### Implementation -
public entry fun finalize_script(
-    deployer: &signer,
-    stage: u64
-) acquires ModuleStore {
+
public entry fun finalize_script(deployer: &signer, stage: u64) acquires ModuleStore {
     check_deployer_permission(deployer);
     let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
-    assert!(table::contains(&module_store.scores, stage), error::invalid_argument(EINVALID_STAGE));
+    assert!(
+        table::contains(&module_store.scores, stage),
+        error::invalid_argument(EINVALID_STAGE)
+    );
 
     let scores = table::borrow_mut(&mut module_store.scores, stage);
-    assert!(!scores.is_finalized, error::invalid_argument(EFINALIED_STAGE));
+    assert!(
+        !scores.is_finalized,
+        error::invalid_argument(EFINALIED_STAGE)
+    );
     scores.is_finalized = true;
+
+    event::emit(FinalizedScoreEvent { stage })
+
 }
 
-
- ## Function `update_score_script` -
public entry fun update_score_script(deployer: &signer, stage: u64, addrs: vector<address>, scores: vector<u64>)
+
public entry fun update_score_script(deployer: &signer, stage: u64, addrs: vector<address>, update_scores: vector<u64>)
 
-
-Implementation +##### Implementation
public entry fun update_score_script(
     deployer: &signer,
     stage: u64,
     addrs: vector<address>,
-    scores: vector<u64>
+    update_scores: vector<u64>
 ) acquires ModuleStore {
-    assert!(vector::length(&addrs) == vector::length(&scores), error::invalid_argument(ENOT_MATCH_LENGTH));
+    assert!(
+        vector::length(&addrs) == vector::length(&update_scores),
+        error::invalid_argument(ENOT_MATCH_LENGTH)
+    );
+    // permission check is performed in prepare_stage
     prepare_stage(deployer, stage);
 
-    vector::enumerate_ref(&addrs, |i, addr| {
-        update_score(
-            deployer,
-            *addr,
-            stage,
-            *vector::borrow(&scores, i),
-        );
-    });
+    let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
+    check_previous_stage_finalized(module_store, stage);
+    assert!(
+        table::contains(&module_store.scores, stage),
+        error::invalid_argument(EINVALID_STAGE)
+    );
+
+    let scores = table::borrow_mut(&mut module_store.scores, stage);
+    assert!(
+        !scores.is_finalized,
+        error::invalid_argument(EFINALIED_STAGE)
+    );
+    vector::enumerate_ref(
+        &addrs,
+        |i, addr| {
+            update_score_internal(
+                scores,
+                *addr,
+                stage,
+                *vector::borrow(&update_scores, i)
+            );
+        }
+    );
 }
 
-
- ## Function `add_deployer_script` @@ -707,31 +688,30 @@ Decrease a score of an account. -
-Implementation +##### Implementation
public entry fun add_deployer_script(
-    chain: &signer,
-    deployer: address,
+    chain: &signer, deployer: address
 ) acquires ModuleStore {
     check_chain_permission(chain);
     let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
-    assert!(!simple_map::contains_key(&module_store.deployers, &deployer), error::invalid_argument(EDEPLOYER_ALREADY_ADDED));
-    simple_map::add(&mut module_store.deployers, deployer, true);
-
-    event::emit(
-        DeployerAddedEvent {
-            deployer: deployer
-        }
-    )
+    assert!(
+        !simple_map::contains_key(&module_store.deployers, &deployer),
+        error::invalid_argument(EDEPLOYER_ALREADY_ADDED)
+    );
+    simple_map::add(
+        &mut module_store.deployers,
+        deployer,
+        true
+    );
+
+    event::emit(DeployerAddedEvent { deployer: deployer })
 }
 
-
- ## Function `remove_deployer_script` @@ -743,27 +723,20 @@ Decrease a score of an account. -
-Implementation +##### Implementation
public entry fun remove_deployer_script(
-    chain: &signer,
-    deployer: address,
+    chain: &signer, deployer: address
 ) acquires ModuleStore {
     check_chain_permission(chain);
     let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
-    assert!(simple_map::contains_key(&module_store.deployers, &deployer), error::invalid_argument(EDEPLOYER_NOT_FOUND));
+    assert!(
+        simple_map::contains_key(&module_store.deployers, &deployer),
+        error::invalid_argument(EDEPLOYER_NOT_FOUND)
+    );
     simple_map::remove(&mut module_store.deployers, &deployer);
 
-    event::emit(
-        DeployerRemovedEvent {
-            deployer: deployer
-        }
-    )
+    event::emit(DeployerRemovedEvent { deployer: deployer })
 }
 
- - - -
diff --git a/minitia_stdlib/doc/secp256k1.md b/minitia_stdlib/doc/secp256k1.md index e64227d..d66c72a 100644 --- a/minitia_stdlib/doc/secp256k1.md +++ b/minitia_stdlib/doc/secp256k1.md @@ -6,17 +6,19 @@ This module implements ECDSA signatures based on the prime-order secp256k1 ellptic curve (i.e., cofactor is 1). -- [Struct `PublicKey`](#0x1_secp256k1_PublicKey) -- [Struct `Signature`](#0x1_secp256k1_Signature) +- [Struct `ECDSARawPublicKey`](#0x1_secp256k1_ECDSARawPublicKey) +- [Struct `ECDSACompressedPublicKey`](#0x1_secp256k1_ECDSACompressedPublicKey) +- [Struct `ECDSASignature`](#0x1_secp256k1_ECDSASignature) - [Constants](#@Constants_0) -- [Function `public_key_from_bytes`](#0x1_secp256k1_public_key_from_bytes) -- [Function `signature_from_bytes`](#0x1_secp256k1_signature_from_bytes) -- [Function `public_key_to_bytes`](#0x1_secp256k1_public_key_to_bytes) -- [Function `signature_to_bytes`](#0x1_secp256k1_signature_to_bytes) -- [Function `verify`](#0x1_secp256k1_verify) -- [Function `recover_public_key`](#0x1_secp256k1_recover_public_key) -- [Function `verify_internal`](#0x1_secp256k1_verify_internal) -- [Function `recover_public_key_internal`](#0x1_secp256k1_recover_public_key_internal) +- [Function `ecdsa_signature_from_bytes`](#0x1_secp256k1_ecdsa_signature_from_bytes) +- [Function `ecdsa_raw_public_key_from_64_bytes`](#0x1_secp256k1_ecdsa_raw_public_key_from_64_bytes) +- [Function `ecdsa_raw_public_key_from_bytes`](#0x1_secp256k1_ecdsa_raw_public_key_from_bytes) +- [Function `ecdsa_compressed_public_key_from_bytes`](#0x1_secp256k1_ecdsa_compressed_public_key_from_bytes) +- [Function `ecdsa_raw_public_key_to_bytes`](#0x1_secp256k1_ecdsa_raw_public_key_to_bytes) +- [Function `ecdsa_compressed_public_key_to_bytes`](#0x1_secp256k1_ecdsa_compressed_public_key_to_bytes) +- [Function `ecdsa_signature_to_bytes`](#0x1_secp256k1_ecdsa_signature_to_bytes) +- [Function `ecdsa_recover`](#0x1_secp256k1_ecdsa_recover) +- [Function `ecdsa_recover_compressed`](#0x1_secp256k1_ecdsa_recover_compressed)
use 0x1::error;
@@ -25,21 +27,19 @@ This module implements ECDSA signatures based on the prime-order secp256k1 ellpt
 
 
 
-
+
 
-## Struct `PublicKey`
+## Struct `ECDSARawPublicKey`
 
-A secp256k1-based ECDSA public key.
-It can be raw or compressed public key.
+A 64-byte ECDSA public key.
 
 
-
struct PublicKey has copy, drop, store
+
struct ECDSARawPublicKey has copy, drop, store
 
-
-Fields +##### Fields
@@ -52,22 +52,19 @@ It can be raw or compressed public key.
-
+ - +## Struct `ECDSACompressedPublicKey` -## Struct `Signature` +A 33-byte ECDSA public key. -A secp256k1-based ECDSA signature. - -
struct Signature has copy, drop, store
+
struct ECDSACompressedPublicKey has copy, drop, store
 
-
-Fields +##### Fields
@@ -80,308 +77,339 @@ A secp256k1-based ECDSA signature.
-
+ - +## Struct `ECDSASignature` -## Constants +A 64-byte ECDSA signature. - +
struct ECDSASignature has copy, drop, store
+
-Wrong number of bytes were given as pubkey. -
const E_WRONG_PUBKEY_SIZE: u64 = 1;
-
+##### Fields +
+
+bytes: vector<u8> +
+
- +
+
-Wrong number of bytes were given as signature. + + +## Constants + + + + +The size of a secp256k1-based ECDSA compressed public key, in bytes. -
const E_WRONG_SIGNATURE_SIZE: u64 = 2;
+
+
const COMPRESSED_PUBLIC_KEY_SIZE: u64 = 33;
 
- + -The size of a secp256k1-based ECDSA compressed-public key, in bytes. +An error occurred while deserializing, for example due to wrong input size. -
const PUBLIC_KEY_SIZE: u64 = 33;
+
const E_DESERIALIZE: u64 = 1;
 
- + -The size of a secp256k1-based ECDSA signature, in bytes. +The size of a hashed message for secp256k1-based ECDSA signing -
const SIGNATURE_SIZE: u64 = 64;
+
const MESSAGE_SIZE: u64 = 32;
 
- + -Wrong number of bytes were given as message. +The size of a secp256k1-based ECDSA public key, in bytes. -
const E_WRONG_MESSAGE_SIZE: u64 = 2;
+
const RAW_PUBLIC_KEY_NUM_BYTES: u64 = 64;
 
- + -The size of a hashed message for secp256k1-based ECDSA signing +The size of a secp256k1-based ECDSA signature, in bytes. -
const MESSAGE_SIZE: u64 = 32;
+
const SIGNATURE_NUM_BYTES: u64 = 64;
 
- + -## Function `public_key_from_bytes` +## Function `ecdsa_signature_from_bytes` -Constructs an PublicKey struct, given 33-byte representation. +Constructs an ECDSASignature struct from the given 64 bytes. -
public fun public_key_from_bytes(bytes: vector<u8>): secp256k1::PublicKey
+
public fun ecdsa_signature_from_bytes(bytes: vector<u8>): secp256k1::ECDSASignature
 
-
-Implementation +##### Implementation -
public fun public_key_from_bytes(bytes: vector<u8>): PublicKey {
+
public fun ecdsa_signature_from_bytes(bytes: vector<u8>): ECDSASignature {
     assert!(
-        std::vector::length(&bytes) == PUBLIC_KEY_SIZE,
-        std::error::invalid_argument(PUBLIC_KEY_SIZE),
+        std::vector::length(&bytes) == SIGNATURE_NUM_BYTES,
+        std::error::invalid_argument(E_DESERIALIZE)
     );
-    PublicKey { bytes }
+    ECDSASignature { bytes }
 }
 
-
- - + -## Function `signature_from_bytes` +## Function `ecdsa_raw_public_key_from_64_bytes` -Constructs an Signature struct from the given 64 bytes. +Constructs an ECDSARawPublicKey struct, given a 64-byte raw representation. -
public fun signature_from_bytes(bytes: vector<u8>): secp256k1::Signature
+
public fun ecdsa_raw_public_key_from_64_bytes(bytes: vector<u8>): secp256k1::ECDSARawPublicKey
 
-
-Implementation +##### Implementation -
public fun signature_from_bytes(bytes: vector<u8>): Signature {
-    assert!(std::vector::length(&bytes) == SIGNATURE_SIZE, std::error::invalid_argument(E_WRONG_SIGNATURE_SIZE));
-    Signature { bytes }
+
public fun ecdsa_raw_public_key_from_64_bytes(bytes: vector<u8>): ECDSARawPublicKey {
+    ecdsa_raw_public_key_from_bytes(bytes)
 }
 
-
- - + -## Function `public_key_to_bytes` +## Function `ecdsa_raw_public_key_from_bytes` -Serializes an PublicKey struct to bytes. +Constructs an ECDSARawPublicKey struct, given a 64-byte raw representation. -
public fun public_key_to_bytes(pk: &secp256k1::PublicKey): vector<u8>
+
public fun ecdsa_raw_public_key_from_bytes(bytes: vector<u8>): secp256k1::ECDSARawPublicKey
 
-
-Implementation +##### Implementation -
public fun public_key_to_bytes(pk: &PublicKey): vector<u8> {
-    pk.bytes
+
public fun ecdsa_raw_public_key_from_bytes(bytes: vector<u8>): ECDSARawPublicKey {
+    assert!(
+        std::vector::length(&bytes) == RAW_PUBLIC_KEY_NUM_BYTES,
+        std::error::invalid_argument(E_DESERIALIZE)
+    );
+    ECDSARawPublicKey { bytes }
 }
 
-
+ - +## Function `ecdsa_compressed_public_key_from_bytes` -## Function `signature_to_bytes` +Constructs an ECDSACompressedPublicKey struct, given a 33-byte raw representation. -Serializes an Signature struct to bytes. - -
public fun signature_to_bytes(sig: &secp256k1::Signature): vector<u8>
+
public fun ecdsa_compressed_public_key_from_bytes(bytes: vector<u8>): secp256k1::ECDSACompressedPublicKey
 
-
-Implementation +##### Implementation -
public fun signature_to_bytes(sig: &Signature): vector<u8> {
-    sig.bytes
+
public fun ecdsa_compressed_public_key_from_bytes(bytes: vector<u8>):
+    ECDSACompressedPublicKey {
+    assert!(
+        std::vector::length(&bytes) == COMPRESSED_PUBLIC_KEY_SIZE,
+        std::error::invalid_argument(E_DESERIALIZE)
+    );
+    ECDSACompressedPublicKey { bytes }
 }
 
-
- - + -## Function `verify` +## Function `ecdsa_raw_public_key_to_bytes` -Returns true only the signature can verify the public key on the message +Serializes an ECDSARawPublicKey struct to 64-bytes. -
public fun verify(message: vector<u8>, public_key: &secp256k1::PublicKey, signature: &secp256k1::Signature): bool
+
public fun ecdsa_raw_public_key_to_bytes(pk: &secp256k1::ECDSARawPublicKey): vector<u8>
 
-
-Implementation +##### Implementation -
public fun verify(
-    message: vector<u8>,
-    public_key: &PublicKey,
-    signature: &Signature,
-): bool {
-    assert!(
-        std::vector::length(&message) == MESSAGE_SIZE,
-        std::error::invalid_argument(E_WRONG_MESSAGE_SIZE),
-    );
-
-    return verify_internal(message, public_key.bytes, signature.bytes)
+
public fun ecdsa_raw_public_key_to_bytes(pk: &ECDSARawPublicKey): vector<u8> {
+    pk.bytes
 }
 
-
+ - +## Function `ecdsa_compressed_public_key_to_bytes` -## Function `recover_public_key` +Serializes an ECDSARawPublicKey struct to 64-bytes. + + +
public fun ecdsa_compressed_public_key_to_bytes(pk: &secp256k1::ECDSACompressedPublicKey): vector<u8>
+
-Recovers the signer's (33-byte) compressed public key from a secp256k1 ECDSA signature given the recovery_id -and the signed message (32 byte digest). -Note that an invalid signature, or a signature from a different message, will result in the recovery of an -incorrect public key. This recovery algorithm can only be used to check validity of a signature if the signer's -public key (or its hash) is known beforehand. +##### Implementation -
public fun recover_public_key(message: vector<u8>, recovery_id: u8, signature: &secp256k1::Signature): option::Option<secp256k1::PublicKey>
+
+
public fun ecdsa_compressed_public_key_to_bytes(
+    pk: &ECDSACompressedPublicKey
+): vector<u8> {
+    pk.bytes
+}
 
-
-Implementation + +## Function `ecdsa_signature_to_bytes` -
public fun recover_public_key(
-    message: vector<u8>,
-    recovery_id: u8,
-    signature: &Signature,
-): Option<PublicKey> {
-    assert!(
-        std::vector::length(&message) == MESSAGE_SIZE,
-        std::error::invalid_argument(E_WRONG_MESSAGE_SIZE),
-    );
+Serializes an ECDSASignature struct to 64-bytes.
 
-    let (pk, success) = recover_public_key_internal(recovery_id, message, signature.bytes);
-    if (success) {
-        std::option::some(public_key_from_bytes(pk))
-    } else {
-        std::option::none<PublicKey>()
-    }
-}
+
+
public fun ecdsa_signature_to_bytes(sig: &secp256k1::ECDSASignature): vector<u8>
 
-
+##### Implementation - -## Function `verify_internal` +
public fun ecdsa_signature_to_bytes(sig: &ECDSASignature): vector<u8> {
+    sig.bytes
+}
+
-Returns true if signature verifies on public_key and message -and returns false otherwise. -
fun verify_internal(message: vector<u8>, public_key: vector<u8>, signature: vector<u8>): bool
-
+ +## Function `ecdsa_recover` +Recovers the signer's raw (64-byte) public key from a secp256k1 ECDSA signature given the recovery_id and the signed +message (32 byte digest). -
-Implementation +Note that an invalid signature, or a signature from a different message, will result in the recovery of an +incorrect public key. This recovery algorithm can only be used to check validity of a signature if the signer's +public key (or its hash) is known beforehand. -
native fun verify_internal(
-    message: vector<u8>,
-    public_key: vector<u8>,
-    signature: vector<u8>,
-): bool;
+
public fun ecdsa_recover(message: vector<u8>, recovery_id: u8, signature: &secp256k1::ECDSASignature): option::Option<secp256k1::ECDSARawPublicKey>
 
-
+##### Implementation - -## Function `recover_public_key_internal` +
public fun ecdsa_recover(
+    message: vector<u8>, recovery_id: u8, signature: &ECDSASignature
+): Option<ECDSARawPublicKey> {
+    assert!(
+        std::vector::length(&message) == MESSAGE_SIZE,
+        std::error::invalid_argument(E_DESERIALIZE)
+    );
 
-Returns (public_key, true) if signature verifies on message under the recovered public_key
-and returns ([], false) otherwise.
+    let (pk, success) =
+        recover_public_key_internal(
+            recovery_id,
+            message,
+            signature.bytes,
+            false
+        );
+    if (success) {
+        std::option::some(ecdsa_raw_public_key_from_bytes(pk))
+    } else {
+        std::option::none<ECDSARawPublicKey>()
+    }
+}
+
-
fun recover_public_key_internal(recovery_id: u8, message: vector<u8>, signature: vector<u8>): (vector<u8>, bool)
-
+ + +## Function `ecdsa_recover_compressed` +Recovers the signer's raw (64-byte) public key from a secp256k1 ECDSA signature given the recovery_id and the signed +message (32 byte digest). -
-Implementation +Note that an invalid signature, or a signature from a different message, will result in the recovery of an +incorrect public key. This recovery algorithm can only be used to check validity of a signature if the signer's +public key (or its hash) is known beforehand. -
native fun recover_public_key_internal(
-    recovery_id: u8,
-    message: vector<u8>,
-    signature: vector<u8>,
-): (vector<u8>, bool);
+
public fun ecdsa_recover_compressed(message: vector<u8>, recovery_id: u8, signature: &secp256k1::ECDSASignature): option::Option<secp256k1::ECDSACompressedPublicKey>
 
-
+##### Implementation + + +
public fun ecdsa_recover_compressed(
+    message: vector<u8>, recovery_id: u8, signature: &ECDSASignature
+): Option<ECDSACompressedPublicKey> {
+    assert!(
+        std::vector::length(&message) == MESSAGE_SIZE,
+        std::error::invalid_argument(E_DESERIALIZE)
+    );
+
+    let (pk, success) =
+        recover_public_key_internal(
+            recovery_id,
+            message,
+            signature.bytes,
+            true
+        );
+    if (success) {
+        std::option::some(ecdsa_compressed_public_key_from_bytes(pk))
+    } else {
+        std::option::none<ECDSACompressedPublicKey>()
+    }
+}
+
diff --git a/minitia_stdlib/doc/simple_json.md b/minitia_stdlib/doc/simple_json.md deleted file mode 100644 index 23dd20e..0000000 --- a/minitia_stdlib/doc/simple_json.md +++ /dev/null @@ -1,635 +0,0 @@ - - - -# Module `0x1::simple_json` - -simple_json is a serde style json wrapper to build objects easier - - -- [Struct `SimpleJsonObject`](#0x1_simple_json_SimpleJsonObject) -- [Constants](#@Constants_0) -- [Function `empty`](#0x1_simple_json_empty) -- [Function `from_json_object`](#0x1_simple_json_from_json_object) -- [Function `to_json_object`](#0x1_simple_json_to_json_object) -- [Function `index`](#0x1_simple_json_index) -- [Function `increase_depth`](#0x1_simple_json_increase_depth) -- [Function `decrease_depth`](#0x1_simple_json_decrease_depth) -- [Function `set_index_internal`](#0x1_simple_json_set_index_internal) -- [Function `set_child_length`](#0x1_simple_json_set_child_length) -- [Function `borrow`](#0x1_simple_json_borrow) -- [Function `borrow_mut`](#0x1_simple_json_borrow_mut) -- [Function `set_index`](#0x1_simple_json_set_index) -- [Function `set_to_last_index`](#0x1_simple_json_set_to_last_index) -- [Function `find_and_set_index`](#0x1_simple_json_find_and_set_index) -- [Function `try_find_and_set_index`](#0x1_simple_json_try_find_and_set_index) -- [Function `set_bool`](#0x1_simple_json_set_bool) -- [Function `set_int_raw`](#0x1_simple_json_set_int_raw) -- [Function `set_int_string`](#0x1_simple_json_set_int_string) -- [Function `set_dec_string`](#0x1_simple_json_set_dec_string) -- [Function `set_string`](#0x1_simple_json_set_string) -- [Function `set_array`](#0x1_simple_json_set_array) -- [Function `set_object`](#0x1_simple_json_set_object) - - -
use 0x1::decimal256;
-use 0x1::json;
-use 0x1::option;
-use 0x1::string;
-
- - - - - -## Struct `SimpleJsonObject` - - - -
struct SimpleJsonObject has copy, drop
-
- - - -
-Fields - - -
-
-obj: json::JsonObject -
-
- -
-
-index: json::JsonIndex -
-
- -
-
- - -
- - - -## Constants - - - - - - -
const EKEY_NOT_FOUND: u64 = 0;
-
- - - - - -## Function `empty` - - - -
public fun empty(): simple_json::SimpleJsonObject
-
- - - -
-Implementation - - -
public fun empty(): SimpleJsonObject{
-    SimpleJsonObject {
-        obj: json::empty(),
-        index: json::start_index(),
-    }
-}
-
- - - -
- - - -## Function `from_json_object` - - - -
public fun from_json_object(object: json::JsonObject): simple_json::SimpleJsonObject
-
- - - -
-Implementation - - -
public fun from_json_object(object: JsonObject): SimpleJsonObject{
-    SimpleJsonObject {
-        obj: object,
-        index: json::start_index(),
-    }
-}
-
- - - -
- - - -## Function `to_json_object` - - - -
public fun to_json_object(object: &simple_json::SimpleJsonObject): &json::JsonObject
-
- - - -
-Implementation - - -
public fun to_json_object(object: &SimpleJsonObject): &JsonObject{
-    &object.obj
-}
-
- - - -
- - - -## Function `index` - - - -
public fun index(object: &simple_json::SimpleJsonObject): &json::JsonIndex
-
- - - -
-Implementation - - -
public fun index(object: &SimpleJsonObject): &JsonIndex{
-    &object.index
-}
-
- - - -
- - - -## Function `increase_depth` - - - -
public fun increase_depth(object: &mut simple_json::SimpleJsonObject)
-
- - - -
-Implementation - - -
public fun increase_depth(object: &mut SimpleJsonObject) {
-    object.index = json::get_next_index(&object.index, 0)
-}
-
- - - -
- - - -## Function `decrease_depth` - - - -
public fun decrease_depth(object: &mut simple_json::SimpleJsonObject)
-
- - - -
-Implementation - - -
public fun decrease_depth(object: &mut SimpleJsonObject) {
-    let (prev_index, _) = json::get_prev_index(&object.index);
-    object.index = prev_index;
-}
-
- - - -
- - - -## Function `set_index_internal` - - - -
fun set_index_internal(object: &mut simple_json::SimpleJsonObject): u64
-
- - - -
-Implementation - - -
fun set_index_internal(object: &mut SimpleJsonObject): u64{
-    if(json::get_depth(&object.index) == 1) return 0;
-
-    let (prev_index, last) = json::get_prev_index(&object.index);
-
-    if(last == 0 && json::get_child_length(json::borrow(&object.obj, &prev_index)) == 0) return 0;
-    object.index = json::get_next_index(&prev_index, last + 1);
-    last+1
-}
-
- - - -
- - - -## Function `set_child_length` - - - -
fun set_child_length(object: &mut simple_json::SimpleJsonObject)
-
- - - -
-Implementation - - -
fun set_child_length(object: &mut SimpleJsonObject) {
-    let (prev_index, last) = json::get_prev_index(&object.index);
-    json::set_child_length(json::borrow_mut(&mut object.obj, &prev_index) ,last+1);
-}
-
- - - -
- - - -## Function `borrow` - - - -
public fun borrow(object: &simple_json::SimpleJsonObject): &json::JsonElem
-
- - - -
-Implementation - - -
public fun borrow(object: &SimpleJsonObject): &JsonElem {
-    json::borrow(&object.obj, &object.index)
-}
-
- - - -
- - - -## Function `borrow_mut` - - - -
public fun borrow_mut(object: &mut simple_json::SimpleJsonObject): &mut json::JsonElem
-
- - - -
-Implementation - - -
public fun borrow_mut(object: &mut SimpleJsonObject): &mut JsonElem {
-    json::borrow_mut(&mut object.obj, &object.index)
-}
-
- - - -
- - - -## Function `set_index` - - - -
public fun set_index(object: &mut simple_json::SimpleJsonObject, position: u64)
-
- - - -
-Implementation - - -
public fun set_index(object: &mut SimpleJsonObject, position: u64){
-    let (prev_index, _) = json::get_prev_index(&object.index);
-    object.index = json::get_next_index(&prev_index, position);
-}
-
- - - -
- - - -## Function `set_to_last_index` - - - -
public fun set_to_last_index(object: &mut simple_json::SimpleJsonObject)
-
- - - -
-Implementation - - -
public fun set_to_last_index(object: &mut SimpleJsonObject){
-    let (prev_index, _) = json::get_prev_index(&object.index);
-    let child_length = json::get_child_length(json::borrow(&object.obj, &prev_index));
-    if(child_length == 0) return;
-    object.index = json::get_next_index(&prev_index, child_length - 1);
-}
-
- - - -
- - - -## Function `find_and_set_index` - - - -
public fun find_and_set_index(object: &mut simple_json::SimpleJsonObject, key: &string::String)
-
- - - -
-Implementation - - -
public fun find_and_set_index(object: &mut SimpleJsonObject, key: &String) {
-    let (prev_index, _) = json::get_prev_index(&object.index);
-    let find_index = json::find(&object.obj, &prev_index, key);
-
-    assert!(!json::is_null_index(&find_index), EKEY_NOT_FOUND);
-    object.index = find_index;
-}
-
- - - -
- - - -## Function `try_find_and_set_index` - - - -
public fun try_find_and_set_index(object: &mut simple_json::SimpleJsonObject, key: &string::String): bool
-
- - - -
-Implementation - - -
public fun try_find_and_set_index(object: &mut SimpleJsonObject, key: &String):bool {
-    let (prev_index, _) = json::get_prev_index(&object.index);
-    let find_index = json::find(&object.obj, &prev_index, key);
-
-    if ( json::is_null_index(&find_index)) {
-        false
-    } else {
-        object.index = find_index;
-        true
-    }
-}
-
- - - -
- - - -## Function `set_bool` - - - -
public fun set_bool(object: &mut simple_json::SimpleJsonObject, key: option::Option<string::String>, value: bool)
-
- - - -
-Implementation - - -
public fun set_bool(object: &mut SimpleJsonObject, key: Option<String>, value: bool) {
-    set_index_internal(object);
-    json::set_bool(&mut object.obj, object.index, key, value);
-    if(json::get_depth(&object.index) != 1) set_child_length(object);
-}
-
- - - -
- - - -## Function `set_int_raw` - - - -
public fun set_int_raw(object: &mut simple_json::SimpleJsonObject, key: option::Option<string::String>, is_positive: bool, value: u256)
-
- - - -
-Implementation - - -
public fun set_int_raw(object:&mut SimpleJsonObject, key: Option<String>, is_positive: bool, value: u256) {
-    set_index_internal(object);
-    json::set_int_raw(&mut object.obj, object.index, key, is_positive, value);
-    if(json::get_depth(&object.index) != 1) set_child_length(object);
-}
-
- - - -
- - - -## Function `set_int_string` - - - -
public fun set_int_string(object: &mut simple_json::SimpleJsonObject, key: option::Option<string::String>, is_positive: bool, value: u256)
-
- - - -
-Implementation - - -
public fun set_int_string(object:&mut SimpleJsonObject, key: Option<String>, is_positive: bool, value: u256) {
-    set_index_internal(object);
-    json::set_int_string(&mut object.obj, object.index, key, is_positive, value);
-    if(json::get_depth(&object.index) != 1) set_child_length(object);
-}
-
- - - -
- - - -## Function `set_dec_string` - - - -
public fun set_dec_string(object: &mut simple_json::SimpleJsonObject, key: option::Option<string::String>, is_positive: bool, value: decimal256::Decimal256)
-
- - - -
-Implementation - - -
public fun set_dec_string(object:&mut SimpleJsonObject, key: Option<String>, is_positive: bool, value: Decimal256) {
-    set_index_internal(object);
-    json::set_dec_string(&mut object.obj, object.index, key, is_positive, value);
-    if(json::get_depth(&object.index) != 1) set_child_length(object);
-}
-
- - - -
- - - -## Function `set_string` - - - -
public fun set_string(object: &mut simple_json::SimpleJsonObject, key: option::Option<string::String>, value: string::String)
-
- - - -
-Implementation - - -
public fun set_string(object: &mut SimpleJsonObject, key: Option<String>, value: String) {
-    set_index_internal(object);
-    json::set_string(&mut object.obj, object.index, key, value);
-    if(json::get_depth(&object.index) != 1) set_child_length(object);
-}
-
- - - -
- - - -## Function `set_array` - - - -
public fun set_array(object: &mut simple_json::SimpleJsonObject, key: option::Option<string::String>)
-
- - - -
-Implementation - - -
public fun set_array(object: &mut SimpleJsonObject, key: Option<String>) {
-    set_index_internal(object);
-    json::set_array(&mut object.obj, object.index, key, 0);
-    if(json::get_depth(&object.index) != 1) set_child_length(object);
-}
-
- - - -
- - - -## Function `set_object` - - - -
public fun set_object(object: &mut simple_json::SimpleJsonObject, key: option::Option<string::String>)
-
- - - -
-Implementation - - -
public fun set_object(object: &mut SimpleJsonObject, key: Option<String>) {
-    set_index_internal(object);
-    json::set_object(&mut object.obj, object.index, key, 0);
-    if(json::get_depth(&object.index) != 1) set_child_length(object);
-}
-
- - - -
diff --git a/minitia_stdlib/doc/simple_map.md b/minitia_stdlib/doc/simple_map.md index d2f6b71..d3a714b 100644 --- a/minitia_stdlib/doc/simple_map.md +++ b/minitia_stdlib/doc/simple_map.md @@ -3,11 +3,11 @@ # Module `0x1::simple_map` -This module provides a solution for sorted maps, that is it has the properties that +This module provides a solution for unsorted maps, that is it has the properties that 1) Keys point to Values 2) Each Key must be unique -3) A Key can be found within O(Log N) time -4) The data is stored as a sorted by Key +3) A Key can be found within O(N) time +4) The keys are unsorted. 5) Adds and removals take O(N) time @@ -15,19 +15,26 @@ This module provides a solution for sorted maps, that is it has the properties t - [Struct `Element`](#0x1_simple_map_Element) - [Constants](#@Constants_0) - [Function `length`](#0x1_simple_map_length) +- [Function `new`](#0x1_simple_map_new) +- [Function `new_from`](#0x1_simple_map_new_from) - [Function `create`](#0x1_simple_map_create) - [Function `borrow`](#0x1_simple_map_borrow) - [Function `borrow_mut`](#0x1_simple_map_borrow_mut) - [Function `contains_key`](#0x1_simple_map_contains_key) - [Function `destroy_empty`](#0x1_simple_map_destroy_empty) - [Function `add`](#0x1_simple_map_add) +- [Function `add_all`](#0x1_simple_map_add_all) +- [Function `upsert`](#0x1_simple_map_upsert) +- [Function `keys`](#0x1_simple_map_keys) +- [Function `values`](#0x1_simple_map_values) +- [Function `to_vec_pair`](#0x1_simple_map_to_vec_pair) +- [Function `destroy`](#0x1_simple_map_destroy) - [Function `remove`](#0x1_simple_map_remove) -- [Function `find`](#0x1_simple_map_find) -
use 0x1::comparator;
-use 0x1::error;
+
use 0x1::error;
 use 0x1::option;
+use 0x1::vector;
 
@@ -43,8 +50,7 @@ This module provides a solution for sorted maps, that is it has the properties t -
-Fields +##### Fields
@@ -57,8 +63,6 @@ This module provides a solution for sorted maps, that is it has the properties t
-
- ## Struct `Element` @@ -70,8 +74,7 @@ This module provides a solution for sorted maps, that is it has the properties t -
-Fields +##### Fields
@@ -90,8 +93,6 @@ This module provides a solution for sorted maps, that is it has the properties t
-
- ## Constants @@ -99,18 +100,20 @@ This module provides a solution for sorted maps, that is it has the properties t +Map key already exists -
const EKEY_ALREADY_EXISTS: u64 = 0;
+
const EKEY_ALREADY_EXISTS: u64 = 1;
 
+Map key is not found -
const EKEY_NOT_FOUND: u64 = 1;
+
const EKEY_NOT_FOUND: u64 = 2;
 
@@ -121,287 +124,437 @@ This module provides a solution for sorted maps, that is it has the properties t -
public fun length<Key: store, Value: store>(map: &simple_map::SimpleMap<Key, Value>): u64
+
public fun length<Key: store, Value: store>(self: &simple_map::SimpleMap<Key, Value>): u64
 
-
-Implementation +##### Implementation -
public fun length<Key: store, Value: store>(map: &SimpleMap<Key, Value>): u64 {
-    vector::length(&map.data)
+
public fun length<Key: store, Value: store>(self: &SimpleMap<Key, Value>): u64 {
+    vector::length(&self.data)
 }
 
-
+ + +## Function `new` + +Create an empty SimpleMap. + + +
public fun new<Key: store, Value: store>(): simple_map::SimpleMap<Key, Value>
+
+ + + +##### Implementation + + +
public fun new<Key: store, Value: store>(): SimpleMap<Key, Value> {
+    SimpleMap { data: vector::empty() }
+}
+
+ + + + + +## Function `new_from` + +Create a SimpleMap from a vector of keys and values. The keys must be unique. + + +
public fun new_from<Key: store, Value: store>(keys: vector<Key>, values: vector<Value>): simple_map::SimpleMap<Key, Value>
+
+ + + +##### Implementation + + +
public fun new_from<Key: store, Value: store>(
+    keys: vector<Key>, values: vector<Value>
+): SimpleMap<Key, Value> {
+    let map = new();
+    add_all(&mut map, keys, values);
+    map
+}
+
+ + ## Function `create` +Create an empty SimpleMap. +This function is deprecated, use new instead. -
public fun create<Key: store, Value: store>(): simple_map::SimpleMap<Key, Value>
+
#[deprecated]
+public fun create<Key: store, Value: store>(): simple_map::SimpleMap<Key, Value>
 
-
-Implementation +##### Implementation
public fun create<Key: store, Value: store>(): SimpleMap<Key, Value> {
-    SimpleMap {
-        data: vector::empty(),
-    }
+    new()
 }
 
-
- ## Function `borrow` -
public fun borrow<Key: store, Value: store>(map: &simple_map::SimpleMap<Key, Value>, key: &Key): &Value
+
public fun borrow<Key: store, Value: store>(self: &simple_map::SimpleMap<Key, Value>, key: &Key): &Value
 
-
-Implementation +##### Implementation
public fun borrow<Key: store, Value: store>(
-    map: &SimpleMap<Key, Value>,
-    key: &Key,
+    self: &SimpleMap<Key, Value>, key: &Key
 ): &Value {
-    let (maybe_idx, _) = find(map, key);
+    let maybe_idx = find(self, key);
     assert!(option::is_some(&maybe_idx), error::invalid_argument(EKEY_NOT_FOUND));
     let idx = option::extract(&mut maybe_idx);
-    &vector::borrow(&map.data, idx).value
+    &vector::borrow(&self.data, idx).value
 }
 
-
- ## Function `borrow_mut` -
public fun borrow_mut<Key: store, Value: store>(map: &mut simple_map::SimpleMap<Key, Value>, key: &Key): &mut Value
+
public fun borrow_mut<Key: store, Value: store>(self: &mut simple_map::SimpleMap<Key, Value>, key: &Key): &mut Value
 
-
-Implementation +##### Implementation
public fun borrow_mut<Key: store, Value: store>(
-    map: &mut SimpleMap<Key, Value>,
-    key: &Key,
+    self: &mut SimpleMap<Key, Value>, key: &Key
 ): &mut Value {
-    let (maybe_idx, _) = find(map, key);
+    let maybe_idx = find(self, key);
     assert!(option::is_some(&maybe_idx), error::invalid_argument(EKEY_NOT_FOUND));
     let idx = option::extract(&mut maybe_idx);
-    &mut vector::borrow_mut(&mut map.data, idx).value
+    &mut vector::borrow_mut(&mut self.data, idx).value
 }
 
-
- ## Function `contains_key` -
public fun contains_key<Key: store, Value: store>(map: &simple_map::SimpleMap<Key, Value>, key: &Key): bool
+
public fun contains_key<Key: store, Value: store>(self: &simple_map::SimpleMap<Key, Value>, key: &Key): bool
 
-
-Implementation +##### Implementation
public fun contains_key<Key: store, Value: store>(
-    map: &SimpleMap<Key, Value>,
-    key: &Key,
+    self: &SimpleMap<Key, Value>, key: &Key
 ): bool {
-    let (maybe_idx, _) = find(map, key);
+    let maybe_idx = find(self, key);
     option::is_some(&maybe_idx)
 }
 
-
- ## Function `destroy_empty` -
public fun destroy_empty<Key: store, Value: store>(map: simple_map::SimpleMap<Key, Value>)
+
public fun destroy_empty<Key: store, Value: store>(self: simple_map::SimpleMap<Key, Value>)
 
-
-Implementation +##### Implementation -
public fun destroy_empty<Key: store, Value: store>(map: SimpleMap<Key, Value>) {
-    let SimpleMap { data } = map;
+
public fun destroy_empty<Key: store, Value: store>(
+    self: SimpleMap<Key, Value>
+) {
+    let SimpleMap { data } = self;
     vector::destroy_empty(data);
 }
 
-
- ## Function `add` +Add a key/value pair to the map. The key must not already exist. -
public fun add<Key: store, Value: store>(map: &mut simple_map::SimpleMap<Key, Value>, key: Key, value: Value)
+
public fun add<Key: store, Value: store>(self: &mut simple_map::SimpleMap<Key, Value>, key: Key, value: Value)
 
-
-Implementation +##### Implementation
public fun add<Key: store, Value: store>(
-    map: &mut SimpleMap<Key, Value>,
+    self: &mut SimpleMap<Key, Value>,
     key: Key,
-    value: Value,
+    value: Value
 ) {
-    let (maybe_idx, maybe_placement) = find(map, &key);
+    let maybe_idx = find(self, &key);
     assert!(option::is_none(&maybe_idx), error::invalid_argument(EKEY_ALREADY_EXISTS));
 
-    // Append to the end and then swap elements until the list is ordered again
-    vector::push_back(&mut map.data, Element { key, value });
+    vector::push_back(&mut self.data, Element { key, value });
+}
+
+ + + + + +## Function `add_all` + +Add multiple key/value pairs to the map. The keys must not already exist. + + +
public fun add_all<Key: store, Value: store>(self: &mut simple_map::SimpleMap<Key, Value>, keys: vector<Key>, values: vector<Value>)
+
+ + + +##### Implementation + + +
public fun add_all<Key: store, Value: store>(
+    self: &mut SimpleMap<Key, Value>,
+    keys: vector<Key>,
+    values: vector<Value>
+) {
+    vector::zip(
+        keys,
+        values,
+        |key, value| {
+            add(self, key, value);
+        }
+    );
+}
+
+ + + + + +## Function `upsert` + +Insert key/value pair or update an existing key to a new value + - let placement = option::extract(&mut maybe_placement); - let end = vector::length(&map.data) - 1; - while (placement < end) { - vector::swap(&mut map.data, placement, end); - placement = placement + 1; +
public fun upsert<Key: store, Value: store>(self: &mut simple_map::SimpleMap<Key, Value>, key: Key, value: Value): (option::Option<Key>, option::Option<Value>)
+
+ + + +##### Implementation + + +
public fun upsert<Key: store, Value: store>(
+    self: &mut SimpleMap<Key, Value>,
+    key: Key,
+    value: Value
+): (std::option::Option<Key>, std::option::Option<Value>) {
+    let data = &mut self.data;
+    let len = vector::length(data);
+    let i = 0;
+    while (i < len) {
+        let element = vector::borrow(data, i);
+        if (&element.key == &key) {
+            vector::push_back(data, Element { key, value });
+            vector::swap(data, i, len);
+            let Element { key, value } = vector::pop_back(data);
+            return (std::option::some(key), std::option::some(value))
+        };
+        i = i + 1;
     };
+    vector::push_back(&mut self.data, Element { key, value });
+    (std::option::none(), std::option::none())
 }
 
-
+ + +## Function `keys` + +Return all keys in the map. This requires keys to be copyable. + + +
public fun keys<Key: copy, Value>(self: &simple_map::SimpleMap<Key, Value>): vector<Key>
+
- -## Function `remove` +##### Implementation -
public fun remove<Key: store, Value: store>(map: &mut simple_map::SimpleMap<Key, Value>, key: &Key): (Key, Value)
+
public fun keys<Key: copy, Value>(self: &SimpleMap<Key, Value>): vector<Key> {
+    vector::map_ref(
+        &self.data,
+        |e| {
+            let e: &Element<Key, Value> = e;
+            e.key
+        }
+    )
+}
 
-
-Implementation + +## Function `values` -
public fun remove<Key: store, Value: store>(
-    map: &mut SimpleMap<Key, Value>,
-    key: &Key,
-): (Key, Value) {
-    let (maybe_idx, _) = find(map, key);
-    assert!(option::is_some(&maybe_idx), error::invalid_argument(EKEY_NOT_FOUND));
+Return all values in the map. This requires values to be copyable.
 
-    let placement = option::extract(&mut maybe_idx);
-    let end = vector::length(&map.data) - 1;
 
-    while (placement < end) {
-        vector::swap(&mut map.data, placement, placement + 1);
-        placement = placement + 1;
-    };
+
public fun values<Key, Value: copy>(self: &simple_map::SimpleMap<Key, Value>): vector<Value>
+
- let Element { key, value } = vector::pop_back(&mut map.data); - (key, value) + + +##### Implementation + + +
public fun values<Key, Value: copy>(self: &SimpleMap<Key, Value>): vector<Value> {
+    vector::map_ref(
+        &self.data,
+        |e| {
+            let e: &Element<Key, Value> = e;
+            e.value
+        }
+    )
 }
 
-
+ + +## Function `to_vec_pair` + +Transform the map into two vectors with the keys and values respectively +Primarily used to destroy a map + + +
public fun to_vec_pair<Key: store, Value: store>(self: simple_map::SimpleMap<Key, Value>): (vector<Key>, vector<Value>)
+
- -## Function `find` +##### Implementation -
fun find<Key: store, Value: store>(map: &simple_map::SimpleMap<Key, Value>, key: &Key): (option::Option<u64>, option::Option<u64>)
+
public fun to_vec_pair<Key: store, Value: store>(
+    self: SimpleMap<Key, Value>
+): (vector<Key>, vector<Value>) {
+    let keys: vector<Key> = vector::empty();
+    let values: vector<Value> = vector::empty();
+    let SimpleMap { data } = self;
+    vector::for_each(
+        data,
+        |e| {
+            let Element { key, value } = e;
+            vector::push_back(&mut keys, key);
+            vector::push_back(&mut values, value);
+        }
+    );
+    (keys, values)
+}
 
-
-Implementation + +## Function `destroy` -
fun find<Key: store, Value: store>(
-    map: &SimpleMap<Key, Value>,
-    key: &Key,
-): (option::Option<u64>, option::Option<u64>) {
-    let length = vector::length(&map.data);
+For maps that cannot be dropped this is a utility to destroy them
+using lambdas to destroy the individual keys and values.
 
-    if (length == 0) {
-        return (option::none(), option::some(0))
-    };
 
-    let left = 0;
-    let right = length;
+
public fun destroy<Key: store, Value: store>(self: simple_map::SimpleMap<Key, Value>, dk: |Key|, dv: |Value|)
+
+ - while (left != right) { - let mid = (left + right) / 2; - let potential_key = &vector::borrow(&map.data, mid).key; - if (comparator::is_smaller_than(&comparator::compare(potential_key, key))) { - left = mid + 1; - } else { - right = mid; - }; - }; - if (left != length && key == &vector::borrow(&map.data, left).key) { - (option::some(left), option::none()) - } else { - (option::none(), option::some(left)) - } +##### Implementation + + +
public inline fun destroy<Key: store, Value: store>(
+    self: SimpleMap<Key, Value>,
+    dk: |Key|,
+    dv: |Value|
+) {
+    let (keys, values) = to_vec_pair(self);
+    vector::destroy(keys, |_k| dk(_k));
+    vector::destroy(values, |_v| dv(_v));
 }
 
-
+ + +## Function `remove` + +Remove a key/value pair from the map. The key must exist. + + +
public fun remove<Key: store, Value: store>(self: &mut simple_map::SimpleMap<Key, Value>, key: &Key): (Key, Value)
+
+ + + +##### Implementation + + +
public fun remove<Key: store, Value: store>(
+    self: &mut SimpleMap<Key, Value>, key: &Key
+): (Key, Value) {
+    let maybe_idx = find(self, key);
+    assert!(option::is_some(&maybe_idx), error::invalid_argument(EKEY_NOT_FOUND));
+    let placement = option::extract(&mut maybe_idx);
+    let Element { key, value } = vector::swap_remove(&mut self.data, placement);
+    (key, value)
+}
+
diff --git a/minitia_stdlib/doc/simple_nft.md b/minitia_stdlib/doc/simple_nft.md index 622539c..418409e 100644 --- a/minitia_stdlib/doc/simple_nft.md +++ b/minitia_stdlib/doc/simple_nft.md @@ -13,9 +13,7 @@ Sample of nft extension including metadata property type by using 0x1::initia_nf - [Function `create_collection_object`](#0x1_simple_nft_create_collection_object) - [Function `mint`](#0x1_simple_nft_mint) - [Function `mint_nft_object`](#0x1_simple_nft_mint_nft_object) -- [Function `borrow`](#0x1_simple_nft_borrow) - [Function `are_properties_mutable`](#0x1_simple_nft_are_properties_mutable) -- [Function `authorized_borrow`](#0x1_simple_nft_authorized_borrow) - [Function `burn`](#0x1_simple_nft_burn) - [Function `set_description`](#0x1_simple_nft_set_description) - [Function `set_uri`](#0x1_simple_nft_set_uri) @@ -24,23 +22,20 @@ Sample of nft extension including metadata property type by using 0x1::initia_nf - [Function `remove_property`](#0x1_simple_nft_remove_property) - [Function `update_property`](#0x1_simple_nft_update_property) - [Function `update_typed_property`](#0x1_simple_nft_update_typed_property) -- [Function `collection_object`](#0x1_simple_nft_collection_object) -- [Function `borrow_collection`](#0x1_simple_nft_borrow_collection) - [Function `is_mutable_collection_description`](#0x1_simple_nft_is_mutable_collection_description) - [Function `is_mutable_collection_royalty`](#0x1_simple_nft_is_mutable_collection_royalty) - [Function `is_mutable_collection_uri`](#0x1_simple_nft_is_mutable_collection_uri) - [Function `is_mutable_collection_nft_description`](#0x1_simple_nft_is_mutable_collection_nft_description) - [Function `is_mutable_collection_nft_uri`](#0x1_simple_nft_is_mutable_collection_nft_uri) - [Function `is_mutable_collection_nft_properties`](#0x1_simple_nft_is_mutable_collection_nft_properties) -- [Function `authorized_borrow_collection`](#0x1_simple_nft_authorized_borrow_collection) - [Function `set_collection_description`](#0x1_simple_nft_set_collection_description) - [Function `set_collection_royalties`](#0x1_simple_nft_set_collection_royalties) - [Function `set_collection_royalties_call`](#0x1_simple_nft_set_collection_royalties_call) - [Function `set_collection_uri`](#0x1_simple_nft_set_collection_uri) -
use 0x1::collection;
-use 0x1::decimal128;
+
use 0x1::bigdecimal;
+use 0x1::collection;
 use 0x1::error;
 use 0x1::initia_nft;
 use 0x1::nft;
@@ -66,8 +61,7 @@ Storage state for managing the no-code Collection.
 
 
 
-
-Fields +##### Fields
@@ -80,8 +74,6 @@ Storage state for managing the no-code Collection.
-
- ## Resource `SimpleNft` @@ -94,8 +86,7 @@ Storage state for managing the no-code Nft. -
-Fields +##### Fields
@@ -108,8 +99,6 @@ Storage state for managing the no-code Nft.
-
- ## Constants @@ -172,13 +161,12 @@ The property map being mutated is not mutable Create a new collection -
public entry fun create_collection(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: decimal128::Decimal128)
+
public entry fun create_collection(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation
public entry fun create_collection(
@@ -193,7 +181,7 @@ Create a new collection
     mutable_nft_description: bool,
     mutable_nft_properties: bool,
     mutable_nft_uri: bool,
-    royalty: Decimal128,
+    royalty: BigDecimal
 ) {
     create_collection_object(
         creator,
@@ -207,28 +195,25 @@ Create a new collection
         mutable_nft_description,
         mutable_nft_properties,
         mutable_nft_uri,
-        royalty,
+        royalty
     );
 }
 
-
- ## Function `create_collection_object` -
public fun create_collection_object(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: decimal128::Decimal128): object::Object<simple_nft::SimpleNftCollection>
+
public fun create_collection_object(creator: &signer, description: string::String, max_supply: option::Option<u64>, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: bigdecimal::BigDecimal): object::Object<simple_nft::SimpleNftCollection>
 
-
-Implementation +##### Implementation
public fun create_collection_object(
@@ -243,27 +228,26 @@ Create a new collection
     mutable_nft_description: bool,
     mutable_nft_properties: bool,
     mutable_nft_uri: bool,
-    royalty: Decimal128,
+    royalty: BigDecimal
 ): Object<SimpleNftCollection> {
-    let (_, extend_ref) = initia_nft::create_collection_object(
-        creator,
-        description,
-        max_supply,
-        name,
-        uri,
-        mutable_description,
-        mutable_royalty,
-        mutable_uri,
-        mutable_nft_description,
-        mutable_nft_uri,
-        royalty,
-    );
+    let (_, extend_ref) =
+        initia_nft::create_collection_object(
+            creator,
+            description,
+            max_supply,
+            name,
+            uri,
+            mutable_description,
+            mutable_royalty,
+            mutable_uri,
+            mutable_nft_description,
+            mutable_nft_uri,
+            royalty
+        );
 
     let object_signer = object::generate_signer_for_extending(&extend_ref);
 
-    let simple_nft_collection = SimpleNftCollection {
-        mutable_nft_properties,
-    };
+    let simple_nft_collection = SimpleNftCollection { mutable_nft_properties };
     move_to(&object_signer, simple_nft_collection);
     object::address_to_object<SimpleNftCollection>(signer::address_of(&object_signer))
 }
@@ -271,8 +255,6 @@ Create a new collection
 
 
 
-
- ## Function `mint` @@ -285,8 +267,7 @@ With an existing collection, directly mint a viable nft into the creators accoun -
-Implementation +##### Implementation
public entry fun mint(
@@ -298,22 +279,31 @@ With an existing collection, directly mint a viable nft into the creators accoun
     property_keys: vector<String>,
     property_types: vector<String>,
     property_values: vector<vector<u8>>,
-    to: Option<address>,
+    to: Option<address>
 ) {
-    let nft_object = mint_nft_object(
-        creator, collection, description,
-        token_id, uri, property_keys, property_types, property_values,
-    );
+    let nft_object =
+        mint_nft_object(
+            creator,
+            collection,
+            description,
+            token_id,
+            uri,
+            property_keys,
+            property_types,
+            property_values
+        );
     if (option::is_some(&to)) {
-        object::transfer(creator, nft_object, option::extract(&mut to));
+        object::transfer(
+            creator,
+            nft_object,
+            option::extract(&mut to)
+        );
     }
 }
 
-
- ## Function `mint_nft_object` @@ -326,8 +316,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun mint_nft_object(
@@ -338,23 +327,29 @@ Mint a nft into an existing collection, and retrieve the object / address of the
     uri: String,
     property_keys: vector<String>,
     property_types: vector<String>,
-    property_values: vector<vector<u8>>,
+    property_values: vector<vector<u8>>
 ): Object<SimpleNft> {
-    let (object, extend_ref) = initia_nft::mint_nft_object(
-        creator,
-        collection,
-        description,
-        token_id,
-        uri,
-        true,
-    );
+    let (object, extend_ref) =
+        initia_nft::mint_nft_object(
+            creator,
+            collection,
+            description,
+            token_id,
+            uri,
+            true
+        );
     let s = object::generate_signer_for_extending(&extend_ref);
 
-    let properties = property_map::prepare_input(property_keys, property_types, property_values);
+    let properties =
+        property_map::prepare_input(
+            property_keys,
+            property_types,
+            property_values
+        );
     property_map::init(&s, properties);
 
     let simple_nft = SimpleNft {
-        property_mutator_ref: property_map::generate_mutator_ref(&s),
+        property_mutator_ref: property_map::generate_mutator_ref(&s)
     };
     move_to(&s, simple_nft);
 
@@ -364,37 +359,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- - - -## Function `borrow` - - - -
fun borrow<T: key>(nft: object::Object<T>): &simple_nft::SimpleNft
-
- - - -
-Implementation - - -
inline fun borrow<T: key>(nft: Object<T>): &SimpleNft {
-    let nft_address = object::object_address(nft);
-    assert!(
-        exists<SimpleNft>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-    borrow_global<SimpleNft>(nft_address)
-}
-
- - - -
- ## Function `are_properties_mutable` @@ -407,8 +371,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun are_properties_mutable<T: key>(nft: Object<T>): bool acquires SimpleNftCollection {
@@ -419,42 +382,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- - - -## Function `authorized_borrow` - - - -
fun authorized_borrow<T: key>(nft: object::Object<T>, creator: &signer): &simple_nft::SimpleNft
-
- - - -
-Implementation - - -
inline fun authorized_borrow<T: key>(nft: Object<T>, creator: &signer): &SimpleNft {
-    let nft_address = object::object_address(nft);
-    assert!(
-        exists<SimpleNft>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-
-    assert!(
-        nft::creator(nft) == signer::address_of(creator),
-        error::permission_denied(ENOT_CREATOR),
-    );
-    borrow_global<SimpleNft>(nft_address)
-}
-
- - - -
- ## Function `burn` @@ -466,22 +393,21 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun burn<T: key>(owner: &signer, nft: Object<T>) acquires SimpleNft {
-    let nft_address = object::object_address(nft);
+    let nft_address = object::object_address(&nft);
     assert!(
         exists<SimpleNft>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
+        error::not_found(ENFT_DOES_NOT_EXIST)
     );
     assert!(
         object::owns(nft, signer::address_of(owner)),
-        error::permission_denied(ENOT_OWNER),
+        error::permission_denied(ENOT_OWNER)
     );
 
-    let simple_nft = move_from<SimpleNft>(object::object_address(nft));
+    let simple_nft = move_from<SimpleNft>(object::object_address(&nft));
     let SimpleNft { property_mutator_ref } = simple_nft;
     property_map::burn(property_mutator_ref);
     initia_nft::burn(owner, nft);
@@ -490,8 +416,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `set_description` @@ -503,14 +427,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_description<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    description: String,
+    creator: &signer, nft: Object<T>, description: String
 ) {
     initia_nft::set_description(creator, nft, description);
 }
@@ -518,8 +439,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `set_uri` @@ -531,14 +450,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_uri<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    uri: String,
+    creator: &signer, nft: Object<T>, uri: String
 ) {
     initia_nft::set_uri(creator, nft, uri);
 }
@@ -546,8 +462,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `add_property` @@ -559,8 +473,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun add_property<T: key>(
@@ -568,22 +481,25 @@ Mint a nft into an existing collection, and retrieve the object / address of the
     nft: Object<T>,
     key: String,
     type: String,
-    value: vector<u8>,
+    value: vector<u8>
 ) acquires SimpleNftCollection, SimpleNft {
     let simple_nft = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
-    property_map::add(&simple_nft.property_mutator_ref, key, type, value);
+    property_map::add(
+        &simple_nft.property_mutator_ref,
+        key,
+        type,
+        value
+    );
 }
 
-
- ## Function `add_typed_property` @@ -595,20 +511,19 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun add_typed_property<T: key, V: drop>(
     creator: &signer,
     nft: Object<T>,
     key: String,
-    value: V,
+    value: V
 ) acquires SimpleNftCollection, SimpleNft {
     let simple_nft = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
     property_map::add_typed(&simple_nft.property_mutator_ref, key, value);
@@ -617,8 +532,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `remove_property` @@ -630,19 +543,16 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun remove_property<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    key: String,
+    creator: &signer, nft: Object<T>, key: String
 ) acquires SimpleNftCollection, SimpleNft {
     let simple_nft = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
     property_map::remove(&simple_nft.property_mutator_ref, &key);
@@ -651,8 +561,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `update_property` @@ -664,8 +572,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun update_property<T: key>(
@@ -673,22 +580,25 @@ Mint a nft into an existing collection, and retrieve the object / address of the
     nft: Object<T>,
     key: String,
     type: String,
-    value: vector<u8>,
+    value: vector<u8>
 ) acquires SimpleNftCollection, SimpleNft {
     let simple_nft = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
-    property_map::update(&simple_nft.property_mutator_ref, &key, type, value);
+    property_map::update(
+        &simple_nft.property_mutator_ref,
+        &key,
+        type,
+        value
+    );
 }
 
-
- ## Function `update_typed_property` @@ -700,84 +610,31 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun update_typed_property<T: key, V: drop>(
     creator: &signer,
     nft: Object<T>,
     key: String,
-    value: V,
+    value: V
 ) acquires SimpleNftCollection, SimpleNft {
     let simple_nft = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
-    property_map::update_typed(&simple_nft.property_mutator_ref, &key, value);
-}
-
- - - -
- - - -## Function `collection_object` - - - -
fun collection_object(creator: &signer, name: &string::String): object::Object<simple_nft::SimpleNftCollection>
-
- - - -
-Implementation - - -
inline fun collection_object(creator: &signer, name: &String): Object<SimpleNftCollection> {
-    let collection_addr = collection::create_collection_address(signer::address_of(creator), name);
-    object::address_to_object<SimpleNftCollection>(collection_addr)
-}
-
- - - -
- - - -## Function `borrow_collection` - - - -
fun borrow_collection<T: key>(nft: object::Object<T>): &simple_nft::SimpleNftCollection
-
- - - -
-Implementation - - -
inline fun borrow_collection<T: key>(nft: Object<T>): &SimpleNftCollection {
-    let collection_address = object::object_address(nft);
-    assert!(
-        exists<SimpleNftCollection>(collection_address),
-        error::not_found(ECOLLECTION_DOES_NOT_EXIST),
+    property_map::update_typed(
+        &simple_nft.property_mutator_ref,
+        &key,
+        value
     );
-    borrow_global<SimpleNftCollection>(collection_address)
 }
 
-
- ## Function `is_mutable_collection_description` @@ -789,12 +646,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_description<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool {
     initia_nft::is_mutable_collection_description(collection)
 }
@@ -802,8 +658,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_royalty` @@ -815,12 +669,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_royalty<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool {
     initia_nft::is_mutable_collection_royalty(collection)
 }
@@ -828,8 +681,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_uri` @@ -841,21 +692,16 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation -
public fun is_mutable_collection_uri<T: key>(
-    collection: Object<T>,
-): bool {
+
public fun is_mutable_collection_uri<T: key>(collection: Object<T>): bool {
     initia_nft::is_mutable_collection_uri(collection)
 }
 
-
- ## Function `is_mutable_collection_nft_description` @@ -867,12 +713,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_description<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool {
     initia_nft::is_mutable_collection_nft_description(collection)
 }
@@ -880,8 +725,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_nft_uri` @@ -893,12 +736,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_uri<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool {
     initia_nft::is_mutable_collection_nft_uri(collection)
 }
@@ -906,8 +748,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `is_mutable_collection_nft_properties` @@ -919,12 +759,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_properties<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SimpleNftCollection {
     borrow_collection(collection).mutable_nft_properties
 }
@@ -932,41 +771,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- - - -## Function `authorized_borrow_collection` - - - -
fun authorized_borrow_collection<T: key>(collection: object::Object<T>, creator: &signer): &simple_nft::SimpleNftCollection
-
- - - -
-Implementation - - -
inline fun authorized_borrow_collection<T: key>(collection: Object<T>, creator: &signer): &SimpleNftCollection {
-    let collection_address = object::object_address(collection);
-    assert!(
-        exists<SimpleNftCollection>(collection_address),
-        error::not_found(ECOLLECTION_DOES_NOT_EXIST),
-    );
-    assert!(
-        collection::creator(collection) == signer::address_of(creator),
-        error::permission_denied(ENOT_CREATOR),
-    );
-    borrow_global<SimpleNftCollection>(collection_address)
-}
-
- - - -
- ## Function `set_collection_description` @@ -978,14 +782,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_collection_description<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    description: String,
+    creator: &signer, collection: Object<T>, description: String
 ) {
     initia_nft::set_collection_description(creator, collection, description);
 }
@@ -993,8 +794,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `set_collection_royalties` @@ -1006,14 +805,11 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public fun set_collection_royalties<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    royalty: royalty::Royalty,
+    creator: &signer, collection: Object<T>, royalty: royalty::Royalty
 ) {
     initia_nft::set_collection_royalties(creator, collection, royalty);
 }
@@ -1021,28 +817,25 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `set_collection_royalties_call` -
entry fun set_collection_royalties_call<T: key>(creator: &signer, collection: object::Object<T>, royalty: decimal128::Decimal128, payee_address: address)
+
entry fun set_collection_royalties_call<T: key>(creator: &signer, collection: object::Object<T>, royalty: bigdecimal::BigDecimal, payee_address: address)
 
-
-Implementation +##### Implementation
entry fun set_collection_royalties_call<T: key>(
     creator: &signer,
     collection: Object<T>,
-    royalty: Decimal128,
-    payee_address: address,
+    royalty: BigDecimal,
+    payee_address: address
 ) {
     let royalty = royalty::create(royalty, payee_address);
     set_collection_royalties(creator, collection, royalty);
@@ -1051,8 +844,6 @@ Mint a nft into an existing collection, and retrieve the object / address of the
 
 
 
-
- ## Function `set_collection_uri` @@ -1064,19 +855,12 @@ Mint a nft into an existing collection, and retrieve the object / address of the -
-Implementation +##### Implementation
public entry fun set_collection_uri<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    uri: String,
+    creator: &signer, collection: Object<T>, uri: String
 ) {
     initia_nft::set_collection_uri(creator, collection, uri);
 }
 
- - - -
diff --git a/minitia_stdlib/doc/soul_bound_token.md b/minitia_stdlib/doc/soul_bound_token.md index e7fa1a1..87b4ef2 100644 --- a/minitia_stdlib/doc/soul_bound_token.md +++ b/minitia_stdlib/doc/soul_bound_token.md @@ -14,13 +14,10 @@ minitia_std::nft module. - [Function `create_collection_object`](#0x1_soul_bound_token_create_collection_object) - [Function `mint`](#0x1_soul_bound_token_mint) - [Function `mint_soul_bound_token_object`](#0x1_soul_bound_token_mint_soul_bound_token_object) -- [Function `mint_internal`](#0x1_soul_bound_token_mint_internal) -- [Function `borrow`](#0x1_soul_bound_token_borrow) - [Function `are_properties_mutable`](#0x1_soul_bound_token_are_properties_mutable) - [Function `is_mutable_description`](#0x1_soul_bound_token_is_mutable_description) - [Function `is_mutable_name`](#0x1_soul_bound_token_is_mutable_name) - [Function `is_mutable_uri`](#0x1_soul_bound_token_is_mutable_uri) -- [Function `authorized_borrow`](#0x1_soul_bound_token_authorized_borrow) - [Function `set_description`](#0x1_soul_bound_token_set_description) - [Function `set_uri`](#0x1_soul_bound_token_set_uri) - [Function `add_property`](#0x1_soul_bound_token_add_property) @@ -28,8 +25,6 @@ minitia_std::nft module. - [Function `remove_property`](#0x1_soul_bound_token_remove_property) - [Function `update_property`](#0x1_soul_bound_token_update_property) - [Function `update_typed_property`](#0x1_soul_bound_token_update_typed_property) -- [Function `collection_object`](#0x1_soul_bound_token_collection_object) -- [Function `borrow_collection`](#0x1_soul_bound_token_borrow_collection) - [Function `is_mutable_collection_description`](#0x1_soul_bound_token_is_mutable_collection_description) - [Function `is_mutable_collection_royalty`](#0x1_soul_bound_token_is_mutable_collection_royalty) - [Function `is_mutable_collection_uri`](#0x1_soul_bound_token_is_mutable_collection_uri) @@ -37,15 +32,14 @@ minitia_std::nft module. - [Function `is_mutable_collection_nft_name`](#0x1_soul_bound_token_is_mutable_collection_nft_name) - [Function `is_mutable_collection_nft_uri`](#0x1_soul_bound_token_is_mutable_collection_nft_uri) - [Function `is_mutable_collection_nft_properties`](#0x1_soul_bound_token_is_mutable_collection_nft_properties) -- [Function `authorized_borrow_collection`](#0x1_soul_bound_token_authorized_borrow_collection) - [Function `set_collection_description`](#0x1_soul_bound_token_set_collection_description) - [Function `set_collection_royalties`](#0x1_soul_bound_token_set_collection_royalties) - [Function `set_collection_royalties_call`](#0x1_soul_bound_token_set_collection_royalties_call) - [Function `set_collection_uri`](#0x1_soul_bound_token_set_collection_uri) -
use 0x1::collection;
-use 0x1::decimal128;
+
use 0x1::bigdecimal;
+use 0x1::collection;
 use 0x1::error;
 use 0x1::nft;
 use 0x1::object;
@@ -70,8 +64,7 @@ Storage state for managing the no-code Collection.
 
 
 
-
-Fields +##### Fields
@@ -126,8 +119,6 @@ Storage state for managing the no-code Collection.
-
- ## Resource `SoulBoundToken` @@ -140,8 +131,7 @@ Storage state for managing the no-code Token. -
-Fields +##### Fields
@@ -160,8 +150,6 @@ Storage state for managing the no-code Token.
-
- ## Constants @@ -224,13 +212,12 @@ The property map being mutated is not mutable Create a new collection -
public entry fun create_collection(creator: &signer, description: string::String, max_supply: u64, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_name: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: decimal128::Decimal128)
+
public entry fun create_collection(creator: &signer, description: string::String, max_supply: u64, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_name: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: bigdecimal::BigDecimal)
 
-
-Implementation +##### Implementation
public entry fun create_collection(
@@ -246,7 +233,7 @@ Create a new collection
     mutable_nft_name: bool,
     mutable_nft_properties: bool,
     mutable_nft_uri: bool,
-    royalty: Decimal128,
+    royalty: BigDecimal
 ) {
     create_collection_object(
         creator,
@@ -261,28 +248,25 @@ Create a new collection
         mutable_nft_name,
         mutable_nft_properties,
         mutable_nft_uri,
-        royalty,
+        royalty
     );
 }
 
-
- ## Function `create_collection_object` -
public fun create_collection_object(creator: &signer, description: string::String, max_supply: u64, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_name: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: decimal128::Decimal128): object::Object<soul_bound_token::SoulBoundTokenCollection>
+
public fun create_collection_object(creator: &signer, description: string::String, max_supply: u64, name: string::String, uri: string::String, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_nft_description: bool, mutable_nft_name: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, royalty: bigdecimal::BigDecimal): object::Object<soul_bound_token::SoulBoundTokenCollection>
 
-
-Implementation +##### Implementation
public fun create_collection_object(
@@ -298,31 +282,38 @@ Create a new collection
     mutable_nft_name: bool,
     mutable_nft_properties: bool,
     mutable_nft_uri: bool,
-    royalty: Decimal128,
+    royalty: BigDecimal
 ): Object<SoulBoundTokenCollection> {
     let creator_addr = signer::address_of(creator);
     let royalty = royalty::create(royalty, creator_addr);
-    let constructor_ref = collection::create_fixed_collection(
-        creator,
-        description,
-        max_supply,
-        name,
-        option::some(royalty),
-        uri,
-    );
+    let constructor_ref =
+        collection::create_fixed_collection(
+            creator,
+            description,
+            max_supply,
+            name,
+            option::some(royalty),
+            uri
+        );
 
     let object_signer = object::generate_signer(&constructor_ref);
-    let mutator_ref = if (mutable_description || mutable_uri) {
-        option::some(collection::generate_mutator_ref(&constructor_ref))
-    } else {
-        option::none()
-    };
-
-    let royalty_mutator_ref = if (mutable_royalty) {
-        option::some(royalty::generate_mutator_ref(object::generate_extend_ref(&constructor_ref)))
-    } else {
-        option::none()
-    };
+    let mutator_ref =
+        if (mutable_description || mutable_uri) {
+            option::some(collection::generate_mutator_ref(&constructor_ref))
+        } else {
+            option::none()
+        };
+
+    let royalty_mutator_ref =
+        if (mutable_royalty) {
+            option::some(
+                royalty::generate_mutator_ref(
+                    object::generate_extend_ref(&constructor_ref)
+                )
+            )
+        } else {
+            option::none()
+        };
 
     let soul_bound_token_collection = SoulBoundTokenCollection {
         mutator_ref,
@@ -332,7 +323,7 @@ Create a new collection
         mutable_nft_description,
         mutable_nft_name,
         mutable_nft_properties,
-        mutable_nft_uri,
+        mutable_nft_uri
     };
     move_to(&object_signer, soul_bound_token_collection);
     object::object_from_constructor_ref(&constructor_ref)
@@ -341,8 +332,6 @@ Create a new collection
 
 
 
-
- ## Function `mint` @@ -355,8 +344,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun mint(
@@ -368,7 +356,7 @@ With an existing collection, directly mint a soul bound token into the recipient
     property_keys: vector<String>,
     property_types: vector<String>,
     property_values: vector<vector<u8>>,
-    soul_bound_to: address,
+    soul_bound_to: address
 ) acquires SoulBoundTokenCollection {
     mint_soul_bound_token_object(
         creator,
@@ -386,8 +374,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `mint_soul_bound_token_object` @@ -400,8 +386,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun mint_soul_bound_token_object(
@@ -413,18 +398,19 @@ With an existing collection, directly mint a soul bound token into the recipient
     property_keys: vector<String>,
     property_types: vector<String>,
     property_values: vector<vector<u8>>,
-    soul_bound_to: address,
+    soul_bound_to: address
 ): Object<SoulBoundToken> acquires SoulBoundTokenCollection {
-    let constructor_ref = mint_internal(
-        creator,
-        collection,
-        description,
-        name,
-        uri,
-        property_keys,
-        property_types,
-        property_values,
-    );
+    let constructor_ref =
+        mint_internal(
+            creator,
+            collection,
+            description,
+            name,
+            uri,
+            property_keys,
+            property_types,
+            property_values
+        );
 
     let transfer_ref = object::generate_transfer_ref(&constructor_ref);
     let linear_transfer_ref = object::generate_linear_transfer_ref(&transfer_ref);
@@ -437,104 +423,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- - - -## Function `mint_internal` - - - -
fun mint_internal(creator: &signer, collection: string::String, description: string::String, name: string::String, uri: string::String, property_keys: vector<string::String>, property_types: vector<string::String>, property_values: vector<vector<u8>>): object::ConstructorRef
-
- - - -
-Implementation - - -
fun mint_internal(
-    creator: &signer,
-    collection: String,
-    description: String,
-    name: String,
-    uri: String,
-    property_keys: vector<String>,
-    property_types: vector<String>,
-    property_values: vector<vector<u8>>,
-): ConstructorRef acquires SoulBoundTokenCollection {
-    let constructor_ref = nft::create(
-        creator,
-        collection,
-        description,
-        name,
-        option::none(),
-        uri,
-    );
-    let s = object::generate_signer(&constructor_ref);
-
-    let object_signer = object::generate_signer(&constructor_ref);
-
-    let collection_obj = collection_object(creator, &collection);
-    let collection = borrow_collection(collection_obj);
-
-    let mutator_ref = if (
-        collection.mutable_nft_description
-            || collection.mutable_nft_name
-            || collection.mutable_nft_uri
-    ) {
-        option::some(nft::generate_mutator_ref(&constructor_ref))
-    } else {
-        option::none()
-    };
-
-    let soul_bound_token = SoulBoundToken {
-        mutator_ref,
-        property_mutator_ref: property_map::generate_mutator_ref(&s),
-    };
-    move_to(&object_signer, soul_bound_token);
-
-    let properties = property_map::prepare_input(property_keys, property_types, property_values);
-    property_map::init(&s, properties);
-
-    constructor_ref
-}
-
- - - -
- - - -## Function `borrow` - - - -
fun borrow<T: key>(nft: object::Object<T>): &soul_bound_token::SoulBoundToken
-
- - - -
-Implementation - - -
inline fun borrow<T: key>(nft: Object<T>): &SoulBoundToken {
-    let nft_address = object::object_address(nft);
-    assert!(
-        exists<SoulBoundToken>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-    borrow_global<SoulBoundToken>(nft_address)
-}
-
- - - -
- ## Function `are_properties_mutable` @@ -547,8 +435,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun are_properties_mutable<T: key>(nft: Object<T>): bool acquires SoulBoundTokenCollection {
@@ -559,8 +446,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_description` @@ -573,8 +458,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_description<T: key>(nft: Object<T>): bool acquires SoulBoundTokenCollection {
@@ -584,8 +468,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_name` @@ -598,8 +480,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_name<T: key>(nft: Object<T>): bool acquires SoulBoundTokenCollection {
@@ -609,8 +490,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_uri` @@ -623,8 +502,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_uri<T: key>(nft: Object<T>): bool acquires SoulBoundTokenCollection {
@@ -634,42 +512,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- - - -## Function `authorized_borrow` - - - -
fun authorized_borrow<T: key>(nft: object::Object<T>, creator: &signer): &soul_bound_token::SoulBoundToken
-
- - - -
-Implementation - - -
inline fun authorized_borrow<T: key>(nft: Object<T>, creator: &signer): &SoulBoundToken {
-    let nft_address = object::object_address(nft);
-    assert!(
-        exists<SoulBoundToken>(nft_address),
-        error::not_found(ENFT_DOES_NOT_EXIST),
-    );
-
-    assert!(
-        nft::creator(nft) == signer::address_of(creator),
-        error::permission_denied(ENOT_CREATOR),
-    );
-    borrow_global<SoulBoundToken>(nft_address)
-}
-
- - - -
- ## Function `set_description` @@ -681,28 +523,26 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun set_description<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    description: String,
+    creator: &signer, nft: Object<T>, description: String
 ) acquires SoulBoundTokenCollection, SoulBoundToken {
     assert!(
         is_mutable_description(nft),
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
     );
     let soul_bound_token = authorized_borrow(nft, creator);
-    nft::set_description(option::borrow(&soul_bound_token.mutator_ref), description);
+    nft::set_description(
+        option::borrow(&soul_bound_token.mutator_ref),
+        description
+    );
 }
 
-
- ## Function `set_uri` @@ -714,28 +554,26 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun set_uri<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    uri: String,
+    creator: &signer, nft: Object<T>, uri: String
 ) acquires SoulBoundTokenCollection, SoulBoundToken {
     assert!(
         is_mutable_uri(nft),
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
     );
     let soul_bound_token = authorized_borrow(nft, creator);
-    nft::set_uri(option::borrow(&soul_bound_token.mutator_ref), uri);
+    nft::set_uri(
+        option::borrow(&soul_bound_token.mutator_ref),
+        uri
+    );
 }
 
-
- ## Function `add_property` @@ -747,8 +585,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun add_property<T: key>(
@@ -756,22 +593,25 @@ With an existing collection, directly mint a soul bound token into the recipient
     nft: Object<T>,
     key: String,
     type: String,
-    value: vector<u8>,
+    value: vector<u8>
 ) acquires SoulBoundTokenCollection, SoulBoundToken {
     let soul_bound_token = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
-    property_map::add(&soul_bound_token.property_mutator_ref, key, type, value);
+    property_map::add(
+        &soul_bound_token.property_mutator_ref,
+        key,
+        type,
+        value
+    );
 }
 
-
- ## Function `add_typed_property` @@ -783,30 +623,31 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun add_typed_property<T: key, V: drop>(
     creator: &signer,
     nft: Object<T>,
     key: String,
-    value: V,
+    value: V
 ) acquires SoulBoundTokenCollection, SoulBoundToken {
     let soul_bound_token = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
-    property_map::add_typed(&soul_bound_token.property_mutator_ref, key, value);
+    property_map::add_typed(
+        &soul_bound_token.property_mutator_ref,
+        key,
+        value
+    );
 }
 
-
- ## Function `remove_property` @@ -818,19 +659,16 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun remove_property<T: key>(
-    creator: &signer,
-    nft: Object<T>,
-    key: String,
+    creator: &signer, nft: Object<T>, key: String
 ) acquires SoulBoundTokenCollection, SoulBoundToken {
     let soul_bound_token = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
     property_map::remove(&soul_bound_token.property_mutator_ref, &key);
@@ -839,8 +677,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `update_property` @@ -852,8 +688,7 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun update_property<T: key>(
@@ -861,22 +696,25 @@ With an existing collection, directly mint a soul bound token into the recipient
     nft: Object<T>,
     key: String,
     type: String,
-    value: vector<u8>,
+    value: vector<u8>
 ) acquires SoulBoundTokenCollection, SoulBoundToken {
     let soul_bound_token = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
-    property_map::update(&soul_bound_token.property_mutator_ref, &key, type, value);
+    property_map::update(
+        &soul_bound_token.property_mutator_ref,
+        &key,
+        type,
+        value
+    );
 }
 
-
- ## Function `update_typed_property` @@ -888,84 +726,31 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun update_typed_property<T: key, V: drop>(
     creator: &signer,
     nft: Object<T>,
     key: String,
-    value: V,
+    value: V
 ) acquires SoulBoundTokenCollection, SoulBoundToken {
     let soul_bound_token = authorized_borrow(nft, creator);
     assert!(
         are_properties_mutable(nft),
-        error::permission_denied(EPROPERTIES_NOT_MUTABLE),
+        error::permission_denied(EPROPERTIES_NOT_MUTABLE)
     );
 
-    property_map::update_typed(&soul_bound_token.property_mutator_ref, &key, value);
-}
-
- - - -
- - - -## Function `collection_object` - - - -
fun collection_object(creator: &signer, name: &string::String): object::Object<soul_bound_token::SoulBoundTokenCollection>
-
- - - -
-Implementation - - -
inline fun collection_object(creator: &signer, name: &String): Object<SoulBoundTokenCollection> {
-    let collection_addr = collection::create_collection_address(signer::address_of(creator), name);
-    object::address_to_object<SoulBoundTokenCollection>(collection_addr)
-}
-
- - - -
- - - -## Function `borrow_collection` - - - -
fun borrow_collection<T: key>(nft: object::Object<T>): &soul_bound_token::SoulBoundTokenCollection
-
- - - -
-Implementation - - -
inline fun borrow_collection<T: key>(nft: Object<T>): &SoulBoundTokenCollection {
-    let collection_address = object::object_address(nft);
-    assert!(
-        exists<SoulBoundTokenCollection>(collection_address),
-        error::not_found(ECOLLECTION_DOES_NOT_EXIST),
+    property_map::update_typed(
+        &soul_bound_token.property_mutator_ref,
+        &key,
+        value
     );
-    borrow_global<SoulBoundTokenCollection>(collection_address)
 }
 
-
- ## Function `is_mutable_collection_description` @@ -977,12 +762,11 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_collection_description<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SoulBoundTokenCollection {
     borrow_collection(collection).mutable_description
 }
@@ -990,8 +774,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_collection_royalty` @@ -1003,12 +785,11 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_collection_royalty<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SoulBoundTokenCollection {
     option::is_some(&borrow_collection(collection).royalty_mutator_ref)
 }
@@ -1016,8 +797,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_collection_uri` @@ -1029,12 +808,11 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_collection_uri<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SoulBoundTokenCollection {
     borrow_collection(collection).mutable_uri
 }
@@ -1042,8 +820,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_collection_nft_description` @@ -1055,12 +831,11 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_description<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SoulBoundTokenCollection {
     borrow_collection(collection).mutable_nft_description
 }
@@ -1068,8 +843,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_collection_nft_name` @@ -1081,12 +854,11 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_name<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SoulBoundTokenCollection {
     borrow_collection(collection).mutable_nft_name
 }
@@ -1094,8 +866,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_collection_nft_uri` @@ -1107,12 +877,11 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_uri<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SoulBoundTokenCollection {
     borrow_collection(collection).mutable_nft_uri
 }
@@ -1120,8 +889,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `is_mutable_collection_nft_properties` @@ -1133,12 +900,11 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun is_mutable_collection_nft_properties<T: key>(
-    collection: Object<T>,
+    collection: Object<T>
 ): bool acquires SoulBoundTokenCollection {
     borrow_collection(collection).mutable_nft_properties
 }
@@ -1146,41 +912,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- - - -## Function `authorized_borrow_collection` - - - -
fun authorized_borrow_collection<T: key>(collection: object::Object<T>, creator: &signer): &soul_bound_token::SoulBoundTokenCollection
-
- - - -
-Implementation - - -
inline fun authorized_borrow_collection<T: key>(collection: Object<T>, creator: &signer): &SoulBoundTokenCollection {
-    let collection_address = object::object_address(collection);
-    assert!(
-        exists<SoulBoundTokenCollection>(collection_address),
-        error::not_found(ECOLLECTION_DOES_NOT_EXIST),
-    );
-    assert!(
-        collection::creator(collection) == signer::address_of(creator),
-        error::permission_denied(ENOT_CREATOR),
-    );
-    borrow_global<SoulBoundTokenCollection>(collection_address)
-}
-
- - - -
- ## Function `set_collection_description` @@ -1192,28 +923,27 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun set_collection_description<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    description: String,
+    creator: &signer, collection: Object<T>, description: String
 ) acquires SoulBoundTokenCollection {
-    let soul_bound_token_collection = authorized_borrow_collection(collection, creator);
+    let soul_bound_token_collection =
+        authorized_borrow_collection(collection, creator);
     assert!(
         soul_bound_token_collection.mutable_description,
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
+    );
+    collection::set_description(
+        option::borrow(&soul_bound_token_collection.mutator_ref),
+        description
     );
-    collection::set_description(option::borrow(&soul_bound_token_collection.mutator_ref), description);
 }
 
-
- ## Function `set_collection_royalties` @@ -1225,48 +955,46 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public fun set_collection_royalties<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    royalty: royalty::Royalty,
+    creator: &signer, collection: Object<T>, royalty: royalty::Royalty
 ) acquires SoulBoundTokenCollection {
-    let soul_bound_token_collection = authorized_borrow_collection(collection, creator);
+    let soul_bound_token_collection =
+        authorized_borrow_collection(collection, creator);
     assert!(
         option::is_some(&soul_bound_token_collection.royalty_mutator_ref),
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
+    );
+    royalty::update(
+        option::borrow(&soul_bound_token_collection.royalty_mutator_ref),
+        royalty
     );
-    royalty::update(option::borrow(&soul_bound_token_collection.royalty_mutator_ref), royalty);
 }
 
-
- ## Function `set_collection_royalties_call` -
entry fun set_collection_royalties_call<T: key>(creator: &signer, collection: object::Object<T>, royalty: decimal128::Decimal128, payee_address: address)
+
entry fun set_collection_royalties_call<T: key>(creator: &signer, collection: object::Object<T>, royalty: bigdecimal::BigDecimal, payee_address: address)
 
-
-Implementation +##### Implementation
entry fun set_collection_royalties_call<T: key>(
     creator: &signer,
     collection: Object<T>,
-    royalty: Decimal128,
-    payee_address: address,
+    royalty: BigDecimal,
+    payee_address: address
 ) acquires SoulBoundTokenCollection {
     let royalty = royalty::create(royalty, payee_address);
     set_collection_royalties(creator, collection, royalty);
@@ -1275,8 +1003,6 @@ With an existing collection, directly mint a soul bound token into the recipient
 
 
 
-
- ## Function `set_collection_uri` @@ -1288,24 +1014,21 @@ With an existing collection, directly mint a soul bound token into the recipient -
-Implementation +##### Implementation
public entry fun set_collection_uri<T: key>(
-    creator: &signer,
-    collection: Object<T>,
-    uri: String,
+    creator: &signer, collection: Object<T>, uri: String
 ) acquires SoulBoundTokenCollection {
-    let soul_bound_token_collection = authorized_borrow_collection(collection, creator);
+    let soul_bound_token_collection =
+        authorized_borrow_collection(collection, creator);
     assert!(
         soul_bound_token_collection.mutable_uri,
-        error::permission_denied(EFIELD_NOT_MUTABLE),
+        error::permission_denied(EFIELD_NOT_MUTABLE)
+    );
+    collection::set_uri(
+        option::borrow(&soul_bound_token_collection.mutator_ref),
+        uri
     );
-    collection::set_uri(option::borrow(&soul_bound_token_collection.mutator_ref), uri);
 }
 
- - - -
diff --git a/minitia_stdlib/doc/string_utils.md b/minitia_stdlib/doc/string_utils.md index a084698..274f922 100644 --- a/minitia_stdlib/doc/string_utils.md +++ b/minitia_stdlib/doc/string_utils.md @@ -19,14 +19,6 @@ A module for formatting move values as strings. - [Function `format2`](#0x1_string_utils_format2) - [Function `format3`](#0x1_string_utils_format3) - [Function `format4`](#0x1_string_utils_format4) -- [Function `cons`](#0x1_string_utils_cons) -- [Function `nil`](#0x1_string_utils_nil) -- [Function `list1`](#0x1_string_utils_list1) -- [Function `list2`](#0x1_string_utils_list2) -- [Function `list3`](#0x1_string_utils_list3) -- [Function `list4`](#0x1_string_utils_list4) -- [Function `native_format`](#0x1_string_utils_native_format) -- [Function `native_format_list`](#0x1_string_utils_native_format_list)
use 0x1::string;
@@ -45,8 +37,7 @@ A module for formatting move values as strings.
 
 
 
-
-Fields +##### Fields
@@ -65,8 +56,6 @@ A module for formatting move values as strings.
-
- ## Struct `NIL` @@ -78,8 +67,7 @@ A module for formatting move values as strings. -
-Fields +##### Fields
@@ -92,8 +80,6 @@ A module for formatting move values as strings.
-
- ## Struct `FakeCons` @@ -110,8 +96,7 @@ A module for formatting move values as strings. -
-Fields +##### Fields
@@ -130,8 +115,6 @@ A module for formatting move values as strings.
-
- ## Constants @@ -185,8 +168,7 @@ For std::string::String the output is the string itself including quotes, eg. -
-Implementation +##### Implementation
public fun to_string<T>(s: &T): String {
@@ -196,8 +178,6 @@ For std::string::String the output is the string itself including quotes, eg.
 
 
 
-
- ## Function `to_string_with_canonical_addresses` @@ -210,8 +190,7 @@ Format addresses as 64 zero-padded hexadecimals. -
-Implementation +##### Implementation
public fun to_string_with_canonical_addresses<T>(s: &T): String {
@@ -221,8 +200,6 @@ Format addresses as 64 zero-padded hexadecimals.
 
 
 
-
- ## Function `to_string_with_integer_types` @@ -235,19 +212,16 @@ Format emitting integers with types ie. 6u8 or 128u32. -
-Implementation +##### Implementation
public fun to_string_with_integer_types<T>(s: &T): String {
-    native_format(s, false, true, true, false)
+    native_format(s, false, true, true, true)
 }
 
-
- ## Function `debug_string` @@ -260,8 +234,7 @@ Format vectors and structs with newlines and indentation. -
-Implementation +##### Implementation
public fun debug_string<T>(s: &T): String {
@@ -271,8 +244,6 @@ Format vectors and structs with newlines and indentation.
 
 
 
-
- ## Function `format1` @@ -285,8 +256,7 @@ Formatting with a rust-like format string, eg. format1<T0: drop>(fmt: &vector<u8>, a: T0): String { @@ -296,8 +266,6 @@ Formatting with a rust-like format string, eg. ## Function `format2` @@ -309,8 +277,7 @@ Formatting with a rust-like format string, eg. format2<T0: drop, T1: drop>(fmt: &vector<u8>, a: T0, b: T1): String { @@ -320,8 +287,6 @@ Formatting with a rust-like format string, eg. ## Function `format3` @@ -333,19 +298,18 @@ Formatting with a rust-like format string, eg. format3<T0: drop, T1: drop, T2: drop>(fmt: &vector<u8>, a: T0, b: T1, c: T2): String { +
public fun format3<T0: drop, T1: drop, T2: drop>(
+    fmt: &vector<u8>, a: T0, b: T1, c: T2
+): String {
     native_format_list(fmt, &list3(a, b, c))
 }
 
- - ## Function `format4` @@ -357,191 +321,16 @@ Formatting with a rust-like format string, eg. format4<T0: drop, T1: drop, T2: drop, T3: drop>(fmt: &vector<u8>, a: T0, b: T1, c: T2, d: T3): String { +
public fun format4<T0: drop, T1: drop, T2: drop, T3: drop>(
+    fmt: &vector<u8>,
+    a: T0,
+    b: T1,
+    c: T2,
+    d: T3
+): String {
     native_format_list(fmt, &list4(a, b, c, d))
 }
 
- - - - - - - -## Function `cons` - - - -
fun cons<T, N>(car: T, cdr: N): string_utils::Cons<T, N>
-
- - - -
-Implementation - - -
fun cons<T, N>(car: T, cdr: N): Cons<T, N> { Cons { car, cdr } }
-
- - - -
- - - -## Function `nil` - - - -
fun nil(): string_utils::NIL
-
- - - -
-Implementation - - -
fun nil(): NIL { NIL {} }
-
- - - -
- - - -## Function `list1` - - - -
fun list1<T0>(a: T0): string_utils::Cons<T0, string_utils::NIL>
-
- - - -
-Implementation - - -
inline fun list1<T0>(a: T0): Cons<T0, NIL> { cons(a, nil()) }
-
- - - -
- - - -## Function `list2` - - - -
fun list2<T0, T1>(a: T0, b: T1): string_utils::Cons<T0, string_utils::Cons<T1, string_utils::NIL>>
-
- - - -
-Implementation - - -
inline fun list2<T0, T1>(a: T0, b: T1): Cons<T0, Cons<T1, NIL>> { cons(a, list1(b)) }
-
- - - -
- - - -## Function `list3` - - - -
fun list3<T0, T1, T2>(a: T0, b: T1, c: T2): string_utils::Cons<T0, string_utils::Cons<T1, string_utils::Cons<T2, string_utils::NIL>>>
-
- - - -
-Implementation - - -
inline fun list3<T0, T1, T2>(a: T0, b: T1, c: T2): Cons<T0, Cons<T1, Cons<T2, NIL>>> { cons(a, list2(b, c)) }
-
- - - -
- - - -## Function `list4` - - - -
fun list4<T0, T1, T2, T3>(a: T0, b: T1, c: T2, d: T3): string_utils::Cons<T0, string_utils::Cons<T1, string_utils::Cons<T2, string_utils::Cons<T3, string_utils::NIL>>>>
-
- - - -
-Implementation - - -
inline fun list4<T0, T1, T2, T3>(a: T0, b: T1, c: T2, d: T3): Cons<T0, Cons<T1, Cons<T2, Cons<T3, NIL>>>> { cons(a, list3(b, c, d)) }
-
- - - -
- - - -## Function `native_format` - - - -
fun native_format<T>(s: &T, type_tag: bool, canonicalize: bool, single_line: bool, include_int_types: bool): string::String
-
- - - -
-Implementation - - -
native fun native_format<T>(s: &T, type_tag: bool, canonicalize: bool, single_line: bool, include_int_types: bool): String;
-
- - - -
- - - -## Function `native_format_list` - - - -
fun native_format_list<T>(fmt: &vector<u8>, val: &T): string::String
-
- - - -
-Implementation - - -
native fun native_format_list<T>(fmt: &vector<u8>, val: &T): String;
-
- - - -
diff --git a/minitia_stdlib/doc/table.md b/minitia_stdlib/doc/table.md index 1822bf0..c2b6b3d 100644 --- a/minitia_stdlib/doc/table.md +++ b/minitia_stdlib/doc/table.md @@ -8,7 +8,6 @@ Type of large-scale storage tables. - [Struct `Table`](#0x1_table_Table) - [Struct `TableIter`](#0x1_table_TableIter) -- [Struct `TableIterMut`](#0x1_table_TableIterMut) - [Resource `Box`](#0x1_table_Box) - [Constants](#@Constants_0) - [Function `new`](#0x1_table_new) @@ -30,20 +29,6 @@ Type of large-scale storage tables. - [Function `iter_mut`](#0x1_table_iter_mut) - [Function `prepare_mut`](#0x1_table_prepare_mut) - [Function `next_mut`](#0x1_table_next_mut) -- [Function `new_table_handle`](#0x1_table_new_table_handle) -- [Function `add_box`](#0x1_table_add_box) -- [Function `borrow_box`](#0x1_table_borrow_box) -- [Function `borrow_box_mut`](#0x1_table_borrow_box_mut) -- [Function `contains_box`](#0x1_table_contains_box) -- [Function `remove_box`](#0x1_table_remove_box) -- [Function `destroy_empty_box`](#0x1_table_destroy_empty_box) -- [Function `drop_unchecked_box`](#0x1_table_drop_unchecked_box) -- [Function `new_table_iter`](#0x1_table_new_table_iter) -- [Function `new_table_iter_mut`](#0x1_table_new_table_iter_mut) -- [Function `next_box`](#0x1_table_next_box) -- [Function `prepare_box`](#0x1_table_prepare_box) -- [Function `next_box_mut`](#0x1_table_next_box_mut) -- [Function `prepare_box_mut`](#0x1_table_prepare_box_mut)
use 0x1::account;
@@ -66,8 +51,7 @@ Type of tables
 
 
 
-
-Fields +##### Fields
@@ -86,8 +70,6 @@ Type of tables
-
- ## Struct `TableIter` @@ -100,8 +82,7 @@ Type of table iterators -
-Fields +##### Fields
@@ -114,36 +95,6 @@ Type of table iterators
-
- - - -## Struct `TableIterMut` - -Type of mutable table iterators - - -
struct TableIterMut<K: copy, drop, V> has drop
-
- - - -
-Fields - - -
-
-iterator_id: u64 -
-
- -
-
- - -
- ## Resource `Box` @@ -156,8 +107,7 @@ Wrapper for values. Required for making values appear as resources in the implem -
-Fields +##### Fields
@@ -170,8 +120,6 @@ Wrapper for values. Required for making values appear as resources in the implem
-
- ## Constants @@ -216,24 +164,18 @@ Create a new Table. -
-Implementation +##### Implementation
public fun new<K: copy + drop, V: store>(): Table<K, V> {
     let handle = new_table_handle<K, V>();
     account::create_table_account(handle);
-    Table {
-        handle,
-        length: 0,
-    }
+    Table { handle, length: 0 }
 }
 
-
- ## Function `destroy_empty` @@ -246,12 +188,14 @@ Destroy a table. The table must be empty to succeed. -
-Implementation +##### Implementation
public fun destroy_empty<K: copy + drop, V>(table: Table<K, V>) {
-    assert!(table.length == 0, error::invalid_state(ENOT_EMPTY));
+    assert!(
+        table.length == 0,
+        error::invalid_state(ENOT_EMPTY)
+    );
     destroy_empty_box<K, V, Box<V>>(&table);
     drop_unchecked_box<K, V, Box<V>>(table)
 }
@@ -259,8 +203,6 @@ Destroy a table. The table must be empty to succeed.
 
 
 
-
- ## Function `handle` @@ -273,8 +215,7 @@ Return a table handle address. -
-Implementation +##### Implementation
public fun handle<K: copy + drop, V>(table: &Table<K, V>): address {
@@ -284,8 +225,6 @@ Return a table handle address.
 
 
 
-
- ## Function `add` @@ -300,8 +239,7 @@ table, and cannot be discovered from it. -
-Implementation +##### Implementation
public fun add<K: copy + drop, V>(table: &mut Table<K, V>, key: K, val: V) {
@@ -312,8 +250,6 @@ table, and cannot be discovered from it.
 
 
 
-
- ## Function `borrow` @@ -327,8 +263,7 @@ Aborts if there is no entry for key. -
-Implementation +##### Implementation
public fun borrow<K: copy + drop, V>(table: &Table<K, V>, key: K): &V {
@@ -338,8 +273,6 @@ Aborts if there is no entry for key.
 
 
 
-
- ## Function `borrow_with_default` @@ -353,11 +286,12 @@ Returns specified default value if there is no entry for key. -
-Implementation +##### Implementation -
public fun borrow_with_default<K: copy + drop, V>(table: &Table<K, V>, key: K, default: &V): &V {
+
public fun borrow_with_default<K: copy + drop, V>(
+    table: &Table<K, V>, key: K, default: &V
+): &V {
     if (!contains(table, copy key)) {
         default
     } else {
@@ -368,8 +302,6 @@ Returns specified default value if there is no entry for key.
 
 
 
-
- ## Function `borrow_mut` @@ -383,8 +315,7 @@ Aborts if there is no entry for key. -
-Implementation +##### Implementation
public fun borrow_mut<K: copy + drop, V>(table: &mut Table<K, V>, key: K): &mut V {
@@ -394,8 +325,6 @@ Aborts if there is no entry for key.
 
 
 
-
- ## Function `length` @@ -408,8 +337,7 @@ Returns the length of the table, i.e. the number of entries. -
-Implementation +##### Implementation
public fun length<K: copy + drop, V>(table: &Table<K, V>): u64 {
@@ -419,8 +347,6 @@ Returns the length of the table, i.e. the number of entries.
 
 
 
-
- ## Function `empty` @@ -433,8 +359,7 @@ Returns true if this table is empty. -
-Implementation +##### Implementation
public fun empty<K: copy + drop, V>(table: &Table<K, V>): bool {
@@ -444,8 +369,6 @@ Returns true if this table is empty.
 
 
 
-
- ## Function `borrow_mut_with_default` @@ -459,11 +382,14 @@ Insert the pair (key, default) first if there is no en -
-Implementation +##### Implementation -
public fun borrow_mut_with_default<K: copy + drop, V: drop>(table: &mut Table<K, V>, key: K, default: V): &mut V {
+
public fun borrow_mut_with_default<K: copy + drop, V: drop>(
+    table: &mut Table<K, V>,
+    key: K,
+    default: V
+): &mut V {
     if (!contains(table, copy key)) {
         add(table, copy key, default)
     };
@@ -473,8 +399,6 @@ Insert the pair (key, default) first if there is no en
 
 
 
-
- ## Function `upsert` @@ -488,11 +412,14 @@ update the value of the entry for key to value otherwi -
-Implementation +##### Implementation -
public fun upsert<K: copy + drop, V: drop>(table: &mut Table<K, V>, key: K, value: V) {
+
public fun upsert<K: copy + drop, V: drop>(
+    table: &mut Table<K, V>,
+    key: K,
+    value: V
+) {
     if (!contains(table, copy key)) {
         add(table, copy key, value)
     } else {
@@ -504,8 +431,6 @@ update the value of the entry for key to value otherwi
 
 
 
-
- ## Function `remove` @@ -519,8 +444,7 @@ Aborts if there is no entry for key. -
-Implementation +##### Implementation
public fun remove<K: copy + drop, V>(table: &mut Table<K, V>, key: K): V {
@@ -532,8 +456,6 @@ Aborts if there is no entry for key.
 
 
 
-
- ## Function `contains` @@ -546,8 +468,7 @@ Returns true iff table contains an -
-Implementation +##### Implementation
public fun contains<K: copy + drop, V>(table: &Table<K, V>, key: K): bool {
@@ -557,8 +478,6 @@ Returns true iff table contains an
 
 
 
-
- ## Function `iter` @@ -581,85 +500,76 @@ the numeric order, use iter<K: copy, drop, V>(table: &table::Table<K, V>, start: option::Option<K>, end: option::Option<K>, order: u8): table::TableIter<K, V> +
public fun iter<K: copy, drop, V>(table: &table::Table<K, V>, start: option::Option<K>, end: option::Option<K>, order: u8): &table::TableIter<K, V>
 
-
-Implementation +##### Implementation
public fun iter<K: copy + drop, V>(
     table: &Table<K, V>,
     start: Option<K>, /* inclusive */
     end: Option<K>, /* exclusive */
-    order: u8 /* 1: Ascending, 2: Descending */,
-): TableIter<K, V> {
-    let start_bytes: vector<u8> = if (option::is_some(&start)) {
-        bcs::to_bytes<K>(&option::extract(&mut start))
-    } else {
-        vector::empty()
-    };
-
-    let end_bytes: vector<u8> = if (option::is_some(&end)) {
-        bcs::to_bytes<K>(&option::extract(&mut end))
-    } else {
-        vector::empty()
-    };
-
-    let iterator_id = new_table_iter<K, V, Box<V>>(table, start_bytes, end_bytes, order);
-    TableIter {
-        iterator_id,
-    }
+    order: u8 /* 1: Ascending, 2: Descending */
+): &TableIter<K, V> {
+    let start_bytes: vector<u8> =
+        if (option::is_some(&start)) {
+            bcs::to_bytes<K>(&option::extract(&mut start))
+        } else {
+            vector::empty()
+        };
+
+    let end_bytes: vector<u8> =
+        if (option::is_some(&end)) {
+            bcs::to_bytes<K>(&option::extract(&mut end))
+        } else {
+            vector::empty()
+        };
+
+    new_table_iter<K, V, Box<V>>(table, start_bytes, end_bytes, order)
 }
 
-
- ## Function `prepare` -
public fun prepare<K: copy, drop, V>(table_iter: &mut table::TableIter<K, V>): bool
+
public fun prepare<K: copy, drop, V>(table_iter: &table::TableIter<K, V>): bool
 
-
-Implementation +##### Implementation -
public fun prepare<K: copy + drop, V>(table_iter: &mut TableIter<K, V>): bool {
+
public fun prepare<K: copy + drop, V>(table_iter: &TableIter<K, V>): bool {
     prepare_box<K, V, Box<V>>(table_iter)
 }
 
-
- ## Function `next` -
public fun next<K: copy, drop, V>(table_iter: &mut table::TableIter<K, V>): (K, &V)
+
public fun next<K: copy, drop, V>(table_iter: &table::TableIter<K, V>): (K, &V)
 
-
-Implementation +##### Implementation -
public fun next<K: copy + drop, V>(table_iter: &mut TableIter<K, V>): (K, &V) {
+
public fun next<K: copy + drop, V>(table_iter: &TableIter<K, V>): (K, &V) {
     let (key, box) = next_box<K, V, Box<V>>(table_iter);
     (key, &box.val)
 }
@@ -667,8 +577,6 @@ functions to obtain the Big Endian key bytes of a number.
 
 
 
-
- ## Function `iter_mut` @@ -676,13 +584,13 @@ functions to obtain the Big Endian key bytes of a number. Create mutable iterator for table. A user has to check prepare before calling next to prevent abort. -let iter = table::iter_mut(&t, start, end, order); +let iter = table::iter_mut(&mut t, start, end, order); loop { -if (!table::prepare_mut(&mut iter)) { +if (!table::prepare_mut(iter)) { break; } -let (key, value) = table::next_mut(&mut iter); +let (key, value) = table::next_mut(iter); } NOTE: The default BCS number encoding follows the Little Endian method. @@ -691,408 +599,79 @@ the numeric order, use iter_mut<K: copy, drop, V>(table: &mut table::Table<K, V>, start: option::Option<K>, end: option::Option<K>, order: u8): table::TableIterMut<K, V> +
public fun iter_mut<K: copy, drop, V>(table: &mut table::Table<K, V>, start: option::Option<K>, end: option::Option<K>, order: u8): &mut table::TableIter<K, V>
 
-
-Implementation +##### Implementation
public fun iter_mut<K: copy + drop, V>(
     table: &mut Table<K, V>,
     start: Option<K>, /* inclusive */
     end: Option<K>, /* exclusive */
-    order: u8 /* 1: Ascending, 2: Descending */,
-): TableIterMut<K, V> {
-    let start_bytes: vector<u8> = if (option::is_some(&start)) {
-        bcs::to_bytes<K>(&option::extract(&mut start))
-    } else {
-        vector::empty()
-    };
-
-    let end_bytes: vector<u8> = if (option::is_some(&end)) {
-        bcs::to_bytes<K>(&option::extract(&mut end))
-    } else {
-        vector::empty()
-    };
-
-    let iterator_id = new_table_iter_mut<K, V, Box<V>>(table, start_bytes, end_bytes, order);
-    TableIterMut {
-        iterator_id,
-    }
+    order: u8 /* 1: Ascending, 2: Descending */
+): &mut TableIter<K, V> {
+    let start_bytes: vector<u8> =
+        if (option::is_some(&start)) {
+            bcs::to_bytes<K>(&option::extract(&mut start))
+        } else {
+            vector::empty()
+        };
+
+    let end_bytes: vector<u8> =
+        if (option::is_some(&end)) {
+            bcs::to_bytes<K>(&option::extract(&mut end))
+        } else {
+            vector::empty()
+        };
+
+    new_table_iter_mut<K, V, Box<V>>(table, start_bytes, end_bytes, order)
 }
 
-
- ## Function `prepare_mut` -
public fun prepare_mut<K: copy, drop, V>(table_iter: &mut table::TableIterMut<K, V>): bool
+
public fun prepare_mut<K: copy, drop, V>(table_iter: &mut table::TableIter<K, V>): bool
 
-
-Implementation +##### Implementation -
public fun prepare_mut<K: copy + drop, V>(table_iter: &mut TableIterMut<K, V>): bool {
+
public fun prepare_mut<K: copy + drop, V>(
+    table_iter: &mut TableIter<K, V>
+): bool {
     prepare_box_mut<K, V, Box<V>>(table_iter)
 }
 
-
- ## Function `next_mut` -
public fun next_mut<K: copy, drop, V>(table_iter: &mut table::TableIterMut<K, V>): (K, &mut V)
+
public fun next_mut<K: copy, drop, V>(table_iter: &mut table::TableIter<K, V>): (K, &mut V)
 
-
-Implementation +##### Implementation -
public fun next_mut<K: copy + drop, V>(table_iter: &mut TableIterMut<K, V>): (K, &mut V) {
+
public fun next_mut<K: copy + drop, V>(table_iter: &mut TableIter<K, V>): (K, &mut V) {
     let (key, box) = next_box_mut<K, V, Box<V>>(table_iter);
     (key, &mut box.val)
 }
 
- - - -
- - - -## Function `new_table_handle` - - - -
fun new_table_handle<K, V>(): address
-
- - - -
-Implementation - - -
native fun new_table_handle<K, V>(): address;
-
- - - -
- - - -## Function `add_box` - - - -
fun add_box<K: copy, drop, V, B>(table: &mut table::Table<K, V>, key: K, val: table::Box<V>)
-
- - - -
-Implementation - - -
native fun add_box<K: copy + drop, V, B>(table: &mut Table<K, V>, key: K, val: Box<V>);
-
- - - -
- - - -## Function `borrow_box` - - - -
fun borrow_box<K: copy, drop, V, B>(table: &table::Table<K, V>, key: K): &table::Box<V>
-
- - - -
-Implementation - - -
native fun borrow_box<K: copy + drop, V, B>(table: &Table<K, V>, key: K): &Box<V>;
-
- - - -
- - - -## Function `borrow_box_mut` - - - -
fun borrow_box_mut<K: copy, drop, V, B>(table: &mut table::Table<K, V>, key: K): &mut table::Box<V>
-
- - - -
-Implementation - - -
native fun borrow_box_mut<K: copy + drop, V, B>(table: &mut Table<K, V>, key: K): &mut Box<V>;
-
- - - -
- - - -## Function `contains_box` - - - -
fun contains_box<K: copy, drop, V, B>(table: &table::Table<K, V>, key: K): bool
-
- - - -
-Implementation - - -
native fun contains_box<K: copy + drop, V, B>(table: &Table<K, V>, key: K): bool;
-
- - - -
- - - -## Function `remove_box` - - - -
fun remove_box<K: copy, drop, V, B>(table: &mut table::Table<K, V>, key: K): table::Box<V>
-
- - - -
-Implementation - - -
native fun remove_box<K: copy + drop, V, B>(table: &mut Table<K, V>, key: K): Box<V>;
-
- - - -
- - - -## Function `destroy_empty_box` - - - -
fun destroy_empty_box<K: copy, drop, V, B>(table: &table::Table<K, V>)
-
- - - -
-Implementation - - -
native fun destroy_empty_box<K: copy + drop, V, B>(table: &Table<K, V>);
-
- - - -
- - - -## Function `drop_unchecked_box` - - - -
fun drop_unchecked_box<K: copy, drop, V, B>(table: table::Table<K, V>)
-
- - - -
-Implementation - - -
native fun drop_unchecked_box<K: copy + drop, V, B>(table: Table<K, V>);
-
- - - -
- - - -## Function `new_table_iter` - - - -
fun new_table_iter<K: copy, drop, V, B>(table: &table::Table<K, V>, start: vector<u8>, end: vector<u8>, order: u8): u64
-
- - - -
-Implementation - - -
native fun new_table_iter<K: copy + drop, V, B>(
-    table: &Table<K, V>,
-    start: vector<u8>,
-    end: vector<u8>,
-    order: u8
-): u64;
-
- - - -
- - - -## Function `new_table_iter_mut` - - - -
fun new_table_iter_mut<K: copy, drop, V, B>(table: &mut table::Table<K, V>, start: vector<u8>, end: vector<u8>, order: u8): u64
-
- - - -
-Implementation - - -
native fun new_table_iter_mut<K: copy + drop, V, B>(
-    table: &mut Table<K, V>,
-    start: vector<u8>,
-    end: vector<u8>,
-    order: u8
-): u64;
-
- - - -
- - - -## Function `next_box` - - - -
fun next_box<K: copy, drop, V, B>(table_iter: &mut table::TableIter<K, V>): (K, &mut table::Box<V>)
-
- - - -
-Implementation - - -
native fun next_box<K: copy + drop, V, B>(table_iter: &mut TableIter<K, V>): (K, &mut Box<V>);
-
- - - -
- - - -## Function `prepare_box` - - - -
fun prepare_box<K: copy, drop, V, B>(table_iter: &mut table::TableIter<K, V>): bool
-
- - - -
-Implementation - - -
native fun prepare_box<K: copy + drop, V, B>(table_iter: &mut TableIter<K, V>): bool;
-
- - - -
- - - -## Function `next_box_mut` - - - -
fun next_box_mut<K: copy, drop, V, B>(table_iter: &mut table::TableIterMut<K, V>): (K, &mut table::Box<V>)
-
- - - -
-Implementation - - -
native fun next_box_mut<K: copy + drop, V, B>(table_iter: &mut TableIterMut<K, V>): (K, &mut Box<V>);
-
- - - -
- - - -## Function `prepare_box_mut` - - - -
fun prepare_box_mut<K: copy, drop, V, B>(table_iter: &mut table::TableIterMut<K, V>): bool
-
- - - -
-Implementation - - -
native fun prepare_box_mut<K: copy + drop, V, B>(table_iter: &mut TableIterMut<K, V>): bool;
-
- - - -
diff --git a/minitia_stdlib/doc/table_key.md b/minitia_stdlib/doc/table_key.md index bf6122b..1cd1c31 100644 --- a/minitia_stdlib/doc/table_key.md +++ b/minitia_stdlib/doc/table_key.md @@ -32,8 +32,7 @@ return big endian bytes of u64 -
-Implementation +##### Implementation
public fun encode_u64(key: u64): vector<u8> {
@@ -46,8 +45,6 @@ return big endian bytes of u64
 
 
 
-
- ## Function `decode_u64` @@ -60,8 +57,7 @@ return u64 from the big endian key bytes -
-Implementation +##### Implementation
public fun decode_u64(key_bytes: vector<u8>): u64 {
@@ -72,8 +68,6 @@ return u64 from the big endian key bytes
 
 
 
-
- ## Function `encode_u128` @@ -86,8 +80,7 @@ return big endian bytes of u128 -
-Implementation +##### Implementation
public fun encode_u128(key: u128): vector<u8> {
@@ -100,8 +93,6 @@ return big endian bytes of u128
 
 
 
-
- ## Function `decode_u128` @@ -114,8 +105,7 @@ return u128 from the big endian key bytes -
-Implementation +##### Implementation
public fun decode_u128(key_bytes: vector<u8>): u128 {
@@ -126,8 +116,6 @@ return u128 from the big endian key bytes
 
 
 
-
- ## Function `encode_u256` @@ -140,8 +128,7 @@ return big endian bytes of u256 -
-Implementation +##### Implementation
public fun encode_u256(key: u256): vector<u8> {
@@ -154,8 +141,6 @@ return big endian bytes of u256
 
 
 
-
- ## Function `decode_u256` @@ -168,8 +153,7 @@ return u256 from the big endian key bytes -
-Implementation +##### Implementation
public fun decode_u256(key_bytes: vector<u8>): u256 {
@@ -177,7 +161,3 @@ return u256 from the big endian key bytes
     from_bcs::to_u256(key_bytes)
 }
 
- - - -
diff --git a/minitia_stdlib/doc/timestamp.md b/minitia_stdlib/doc/timestamp.md new file mode 100644 index 0000000..5029854 --- /dev/null +++ b/minitia_stdlib/doc/timestamp.md @@ -0,0 +1,98 @@ + + + +# Module `0x1::timestamp` + +Timestamp module exists to provide compatibility with aptos. + + +- [Constants](#@Constants_0) +- [Function `now_microseconds`](#0x1_timestamp_now_microseconds) +- [Function `now_seconds`](#0x1_timestamp_now_seconds) + + +
use 0x1::block;
+
+ + + + + +## Constants + + + + +An invalid timestamp was provided + + +
const EINVALID_TIMESTAMP: u64 = 2;
+
+ + + + + +The blockchain is not in an operating state yet + + +
const ENOT_OPERATING: u64 = 1;
+
+ + + + + +Conversion factor between seconds and microseconds + + +
const MICRO_CONVERSION_FACTOR: u64 = 1000000;
+
+ + + + + +## Function `now_microseconds` + +Gets the current time in microseconds. + + +
#[view]
+public fun now_microseconds(): u64
+
+ + + +##### Implementation + + +
public fun now_microseconds(): u64 {
+    let timestamp = now_seconds();
+    timestamp * MICRO_CONVERSION_FACTOR
+}
+
+ + + + + +## Function `now_seconds` + +Gets the current time in seconds. + + +
#[view]
+public fun now_seconds(): u64
+
+ + + +##### Implementation + + +
public fun now_seconds(): u64 {
+    let (_, timestamp) = get_block_info();
+    timestamp
+}
+
diff --git a/minitia_stdlib/doc/transaction_context.md b/minitia_stdlib/doc/transaction_context.md index d7155aa..26fd1ba 100644 --- a/minitia_stdlib/doc/transaction_context.md +++ b/minitia_stdlib/doc/transaction_context.md @@ -25,8 +25,7 @@ Return a transaction hash of this execution. -
-Implementation +##### Implementation
native public fun get_transaction_hash(): vector<u8>;
@@ -34,8 +33,6 @@ Return a transaction hash of this execution.
 
 
 
-
- ## Function `generate_unique_address` @@ -52,13 +49,8 @@ the sequence number and generates a new unique address. -
-Implementation +##### Implementation
native public fun generate_unique_address(): address;
 
- - - -
diff --git a/minitia_stdlib/doc/type_info.md b/minitia_stdlib/doc/type_info.md index 22b489f..a1e9258 100644 --- a/minitia_stdlib/doc/type_info.md +++ b/minitia_stdlib/doc/type_info.md @@ -29,8 +29,7 @@ -
-Fields +##### Fields
@@ -55,8 +54,6 @@
-
- ## Function `account_address` @@ -68,8 +65,7 @@ -
-Implementation +##### Implementation
public fun account_address(type_info: &TypeInfo): address {
@@ -79,8 +75,6 @@
 
 
 
-
- ## Function `module_name` @@ -92,8 +86,7 @@ -
-Implementation +##### Implementation
public fun module_name(type_info: &TypeInfo): vector<u8> {
@@ -103,8 +96,6 @@
 
 
 
-
- ## Function `struct_name` @@ -116,8 +107,7 @@ -
-Implementation +##### Implementation
public fun struct_name(type_info: &TypeInfo): vector<u8> {
@@ -127,8 +117,6 @@
 
 
 
-
- ## Function `type_of` @@ -140,17 +128,14 @@ -
-Implementation +##### Implementation -
public native fun type_of<T>(): TypeInfo;
+
native public fun type_of<T>(): TypeInfo;
 
-
- ## Function `type_name` @@ -162,13 +147,8 @@ -
-Implementation +##### Implementation -
public native fun type_name<T>(): string::String;
+
native public fun type_name<T>(): string::String;
 
- - - -
diff --git a/minitia_stdlib/sources/account.move b/minitia_stdlib/sources/account.move index c04476d..fab31b7 100644 --- a/minitia_stdlib/sources/account.move +++ b/minitia_stdlib/sources/account.move @@ -23,7 +23,7 @@ module minitia_std::account { account_number: u64, sequence_number: u64, account_type: u8, - is_blocked: bool, + is_blocked: bool } public entry fun create_account_script(addr: address) { @@ -34,7 +34,7 @@ module minitia_std::account { let (found, _, _, _, _) = account_info(addr); assert!( !found, - error::already_exists(EACCOUNT_ALREADY_EXISTS), + error::already_exists(EACCOUNT_ALREADY_EXISTS) ); request_create_account(addr, 0, ACCOUNT_TYPE_BASE) @@ -45,15 +45,14 @@ module minitia_std::account { public(friend) fun create_table_account(addr: address): u64 { let (found, account_number, sequence, account_type, _) = account_info(addr); assert!( - !found - || (account_type == ACCOUNT_TYPE_BASE && sequence == 0), - error::already_exists(EACCOUNT_ALREADY_EXISTS), + !found || (account_type == ACCOUNT_TYPE_BASE && sequence == 0), + error::already_exists(EACCOUNT_ALREADY_EXISTS) ); request_create_account( addr, account_number, - ACCOUNT_TYPE_TABLE, + ACCOUNT_TYPE_TABLE ) } @@ -67,7 +66,7 @@ module minitia_std::account { request_create_account( addr, account_number, - ACCOUNT_TYPE_OBJECT, + ACCOUNT_TYPE_OBJECT ) } else { // When an Object is deleted, the ObjectAccount in CosmosSDK is designed @@ -179,8 +178,11 @@ module minitia_std::account { info.sequence_number } - native fun request_create_account(addr: address, account_number: u64, account_type: u8): u64; - native public fun account_info(addr: address): ( + native fun request_create_account( + addr: address, account_number: u64, account_type: u8 + ): u64; + native public fun account_info(addr: address): + ( bool /* found */, u64 /* account_number */, u64 /* sequence_number */, @@ -231,7 +233,7 @@ module minitia_std::account { assert!(bob_account_num == get_account_number(bob), 7); assert!( carol_account_num == get_account_number(carol), - 7, + 7 ); // object account @@ -243,7 +245,7 @@ module minitia_std::account { let dan_object_account_num = create_object_account(dan); assert!( dan_object_account_num == get_account_number(dan), - 9, + 9 ); assert!(is_object_account(dan), 10); assert!(exists_at(dan), 11); @@ -257,7 +259,7 @@ module minitia_std::account { let erin_table_account_num = create_table_account(erin); assert!( erin_table_account_num == get_account_number(erin), - 13, + 13 ); assert!(is_table_account(erin), 14); assert!(exists_at(erin), 15); @@ -275,11 +277,11 @@ module minitia_std::account { ); assert!( bob == @0x0000000000000000000000000000000000000000000000000000000000000b0b, - 0, + 0 ); assert!( carol == @0x00000000000000000000000000000000000000000000000000000000000ca501, - 1, + 1 ); } @@ -290,17 +292,24 @@ module minitia_std::account { assert!(vector::length(&authentication_key) == 32, 0); } - #[test(new_address = @0x41, new_address2 = @0x42, new_address3 = @0x43, new_address4 = @0x44)] + #[ + test( + new_address = @0x41, + new_address2 = @0x42, + new_address3 = @0x43, + new_address4 = @0x44 + ) + ] public fun test_create_table_account_and_object_account( new_address: address, new_address2: address, new_address3: address, - new_address4: address, + new_address4: address ) { let table_account_num = create_table_account(new_address); assert!( table_account_num == get_account_number(new_address), - 0, + 0 ); assert!(is_table_account(new_address), 1); assert!(exists_at(new_address), 2); @@ -311,12 +320,12 @@ module minitia_std::account { 100, 0, ACCOUNT_TYPE_BASE, - false, + false ); let table_account_num = create_table_account(new_address2); assert!( table_account_num == get_account_number(new_address2), - 0, + 0 ); assert!(table_account_num == 100, 0); assert!(is_table_account(new_address2), 1); @@ -326,7 +335,7 @@ module minitia_std::account { let object_account_num = create_object_account(new_address3); assert!( object_account_num == get_account_number(new_address3), - 3, + 3 ); assert!(is_object_account(new_address3), 4); assert!(exists_at(new_address3), 5); @@ -337,12 +346,12 @@ module minitia_std::account { 200, 0, ACCOUNT_TYPE_BASE, - false, + false ); let object_account_num = create_object_account(new_address4); assert!( object_account_num == get_account_number(new_address4), - 0, + 0 ); assert!(object_account_num == 200, 0); assert!(is_object_account(new_address4), 1); @@ -359,7 +368,7 @@ module minitia_std::account { 200, 0, ACCOUNT_TYPE_BASE, - true, + true ); assert!(is_blocked(new_address), 1); @@ -368,7 +377,7 @@ module minitia_std::account { 100, 0, ACCOUNT_TYPE_BASE, - false, + false ); assert!(!is_blocked(new_address2), 2); } @@ -397,4 +406,11 @@ module minitia_std::account { create_table_account(new_address); create_object_account(new_address); } + + // functions for compatibility with the aptos + + #[test_only] + public fun create_account_for_test(new_address: address): signer { + create_signer_for_test(new_address) + } } diff --git a/minitia_stdlib/sources/address.move b/minitia_stdlib/sources/address.move index d16b213..6636bad 100644 --- a/minitia_stdlib/sources/address.move +++ b/minitia_stdlib/sources/address.move @@ -6,11 +6,11 @@ module minitia_std::address { use minitia_std::json; struct FromSdkRequest has copy, drop { - sdk_addr: String, + sdk_addr: String } struct FromSdkResponse has copy, drop { - vm_addr: address, + vm_addr: address } public fun from_sdk(sdk_addr: String): address { @@ -18,19 +18,19 @@ module minitia_std::address { json::unmarshal( query::query_custom( b"from_sdk_address", - json::marshal(&FromSdkRequest { sdk_addr: sdk_addr, }), - ), + json::marshal(&FromSdkRequest { sdk_addr: sdk_addr }) + ) ); res.vm_addr } struct ToSdkRequest has copy, drop { - vm_addr: address, + vm_addr: address } struct ToSdkResponse has copy, drop { - sdk_addr: String, + sdk_addr: String } public fun to_sdk(vm_addr: address): String { @@ -38,8 +38,8 @@ module minitia_std::address { json::unmarshal( query::query_custom( b"to_sdk_address", - json::marshal(&ToSdkRequest { vm_addr: vm_addr, }), - ), + json::marshal(&ToSdkRequest { vm_addr: vm_addr }) + ) ); res.sdk_addr diff --git a/minitia_stdlib/sources/any.move b/minitia_stdlib/sources/any.move index 1698099..d6a3b65 100644 --- a/minitia_stdlib/sources/any.move +++ b/minitia_stdlib/sources/any.move @@ -27,14 +27,17 @@ module minitia_std::any { /// Pack a value into the `Any` representation. Because Any can be stored and dropped, this is /// also required from `T`. public fun pack(x: T): Any { - Any { type_name: type_info::type_name(), data: to_bytes(&x) } + Any { + type_name: type_info::type_name(), + data: to_bytes(&x) + } } /// Unpack a value from the `Any` representation. This aborts if the value has not the expected type `T`. public fun unpack(x: Any): T { assert!( type_info::type_name() == x.type_name, - error::invalid_argument(ETYPE_MISMATCH), + error::invalid_argument(ETYPE_MISMATCH) ); from_bytes(x.data) } diff --git a/minitia_stdlib/sources/bigdecimal.move b/minitia_stdlib/sources/bigdecimal.move new file mode 100644 index 0000000..c911fc2 --- /dev/null +++ b/minitia_stdlib/sources/bigdecimal.move @@ -0,0 +1,614 @@ +module minitia_std::bigdecimal { + use minitia_std::error; + use minitia_std::biguint::{Self, BigUint}; + + // Const values + const DECIMAL_FRACTIONAL: u64 = 1000000000000000000; + const FRACTIONAL_LENGTH: u64 = 18; + + // Error codes + const NEGATIVE_RESULT: u64 = 100; + const EDIVISION_BY_ZERO: u64 = 101; + + struct BigDecimal has copy, drop, store { + scaled: BigUint + } + + fun f(): BigUint { + biguint::from_u64(DECIMAL_FRACTIONAL) + } + + fun hf(): BigUint { + biguint::from_u64(DECIMAL_FRACTIONAL / 2) + } + + fun f_1(): BigUint { + biguint::from_u64(DECIMAL_FRACTIONAL - 1) + } + + // creation + + /// Create a BigDecimal from a u64 value by multiplying it by the fractional part. + public fun from_u64(value: u64): BigDecimal { + BigDecimal { + scaled: biguint::mul(biguint::from_u64(value), f()) + } + } + + /// Create a BigDecimal from a u128 value by multiplying it by the fractional part. + public fun from_u128(value: u128): BigDecimal { + BigDecimal { + scaled: biguint::mul(biguint::from_u128(value), f()) + } + } + + /// Create a BigDecimal from a u256 value by multiplying it by the fractional part. + public fun from_u256(value: u256): BigDecimal { + BigDecimal { + scaled: biguint::mul(biguint::from_u256(value), f()) + } + } + + /// Create a BigDecimal from a BigUint value by multiplying it by the fractional part. + public fun new(value: BigUint): BigDecimal { + BigDecimal { + scaled: biguint::mul(value, f()) + } + } + + /// Create a BigDecimal from a scaled BigUint value. + public fun from_scaled(scaled: BigUint): BigDecimal { + BigDecimal { scaled: scaled } + } + + /// Get the scaled value of a BigDecimal. + public fun get_scaled(num: BigDecimal): BigUint { + num.scaled + } + + /// Create a BigDecimal from a scaled BigUint le_bytes value. + public fun from_scaled_le_bytes(le_bytes: vector): BigDecimal { + BigDecimal { scaled: biguint::from_le_bytes(le_bytes) } + } + + public fun get_scaled_le_bytes(num: BigDecimal): vector { + biguint::to_le_bytes(num.scaled) + } + + public fun from_ratio(numerator: BigUint, denominator: BigUint): BigDecimal { + assert!( + !biguint::is_zero(denominator), error::invalid_argument(EDIVISION_BY_ZERO) + ); + + let numerator = biguint::mul(numerator, f()); + BigDecimal { scaled: biguint::div(numerator, denominator) } + } + + public fun from_ratio_u64(numerator: u64, denominator: u64): BigDecimal { + assert!(denominator != 0, error::invalid_argument(EDIVISION_BY_ZERO)); + + let numerator = biguint::from_u128( + (numerator as u128) * (DECIMAL_FRACTIONAL as u128) + ); + let denominator = biguint::from_u64(denominator); + + BigDecimal { scaled: biguint::div(numerator, denominator) } + } + + public fun from_ratio_u128(numerator: u128, denominator: u128): BigDecimal { + assert!(denominator != 0, error::invalid_argument(EDIVISION_BY_ZERO)); + + let numerator = biguint::from_u256( + (numerator as u256) * (DECIMAL_FRACTIONAL as u256) + ); + let denominator = biguint::from_u128(denominator); + + BigDecimal { scaled: biguint::div(numerator, denominator) } + } + + public fun from_ratio_u256(numerator: u256, denominator: u256): BigDecimal { + assert!(denominator != 0, error::invalid_argument(EDIVISION_BY_ZERO)); + + let numerator = biguint::mul(biguint::from_u256(numerator), f()); + let denominator = biguint::from_u256(denominator); + + BigDecimal { scaled: biguint::div(numerator, denominator) } + } + + public fun rev(num: BigDecimal): BigDecimal { + let fractional = f(); + BigDecimal { + scaled: biguint::div(biguint::mul(fractional, fractional), num.scaled) + } + } + + public fun one(): BigDecimal { + BigDecimal { scaled: f() } + } + + public fun zero(): BigDecimal { + BigDecimal { scaled: biguint::zero() } + } + + // cmp + + public fun eq(num1: BigDecimal, num2: BigDecimal): bool { + biguint::eq(num1.scaled, num2.scaled) + } + + public fun lt(num1: BigDecimal, num2: BigDecimal): bool { + biguint::lt(num1.scaled, num2.scaled) + } + + public fun le(num1: BigDecimal, num2: BigDecimal): bool { + biguint::le(num1.scaled, num2.scaled) + } + + public fun gt(num1: BigDecimal, num2: BigDecimal): bool { + biguint::gt(num1.scaled, num2.scaled) + } + + public fun ge(num1: BigDecimal, num2: BigDecimal): bool { + biguint::ge(num1.scaled, num2.scaled) + } + + public fun is_zero(num: BigDecimal): bool { + biguint::is_zero(num.scaled) + } + + public fun is_one(num: BigDecimal): bool { + biguint::eq(num.scaled, f()) + } + + // arithmetic + + public fun add(num1: BigDecimal, num2: BigDecimal): BigDecimal { + BigDecimal { scaled: biguint::add(num1.scaled, num2.scaled) } + } + + public fun add_by_u64(num1: BigDecimal, num2: u64): BigDecimal { + BigDecimal { + scaled: biguint::add(num1.scaled, from_u64(num2).scaled) + } + } + + public fun add_by_u128(num1: BigDecimal, num2: u128): BigDecimal { + BigDecimal { + scaled: biguint::add(num1.scaled, from_u128(num2).scaled) + } + } + + public fun add_by_u256(num1: BigDecimal, num2: u256): BigDecimal { + BigDecimal { + scaled: biguint::add(num1.scaled, from_u256(num2).scaled) + } + } + + public fun sub(num1: BigDecimal, num2: BigDecimal): BigDecimal { + assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT)); + BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) } + } + + public fun sub_by_u64(num1: BigDecimal, num2: u64): BigDecimal { + let num2 = from_u64(num2); + assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT)); + BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) } + } + + public fun sub_by_u128(num1: BigDecimal, num2: u128): BigDecimal { + let num2 = from_u128(num2); + assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT)); + BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) } + } + + public fun sub_by_u256(num1: BigDecimal, num2: u256): BigDecimal { + let num2 = from_u256(num2); + assert!(ge(num1, num2), error::invalid_argument(NEGATIVE_RESULT)); + BigDecimal { scaled: biguint::sub(num1.scaled, num2.scaled) } + } + + public fun mul(num1: BigDecimal, num2: BigDecimal): BigDecimal { + BigDecimal { + scaled: biguint::div(biguint::mul(num1.scaled, num2.scaled), f()) + } + } + + public fun mul_truncate(num1: BigDecimal, num2: BigDecimal): BigUint { + truncate(mul(num1, num2)) + } + + public fun mul_ceil(num1: BigDecimal, num2: BigDecimal): BigUint { + ceil(mul(num1, num2)) + } + + public fun mul_by_u64(num1: BigDecimal, num2: u64): BigDecimal { + BigDecimal { scaled: biguint::mul_by_u64(num1.scaled, num2) } + } + + public fun mul_by_u64_truncate(num1: BigDecimal, num2: u64): u64 { + truncate_u64(mul_by_u64(num1, num2)) + } + + public fun mul_by_u64_ceil(num1: BigDecimal, num2: u64): u64 { + ceil_u64(mul_by_u64(num1, num2)) + } + + public fun mul_by_u128(num1: BigDecimal, num2: u128): BigDecimal { + BigDecimal { scaled: biguint::mul_by_u128(num1.scaled, num2) } + } + + public fun mul_by_u128_truncate(num1: BigDecimal, num2: u128): u128 { + truncate_u128(mul_by_u128(num1, num2)) + } + + public fun mul_by_u128_ceil(num1: BigDecimal, num2: u128): u128 { + ceil_u128(mul_by_u128(num1, num2)) + } + + public fun mul_by_u256(num1: BigDecimal, num2: u256): BigDecimal { + BigDecimal { scaled: biguint::mul_by_u256(num1.scaled, num2) } + } + + public fun mul_by_u256_truncate(num1: BigDecimal, num2: u256): u256 { + truncate_u256(mul_by_u256(num1, num2)) + } + + public fun mul_by_u256_ceil(num1: BigDecimal, num2: u256): u256 { + ceil_u256(mul_by_u256(num1, num2)) + } + + public fun div(num1: BigDecimal, num2: BigDecimal): BigDecimal { + assert!( + !biguint::is_zero(num2.scaled), error::invalid_argument(EDIVISION_BY_ZERO) + ); + + BigDecimal { + scaled: biguint::div(biguint::mul(num1.scaled, f()), num2.scaled) + } + } + + public fun div_by_u64(num1: BigDecimal, num2: u64): BigDecimal { + assert!(num2 != 0, error::invalid_argument(EDIVISION_BY_ZERO)); + + BigDecimal { scaled: biguint::div_by_u64(num1.scaled, num2) } + } + + public fun div_by_u128(num1: BigDecimal, num2: u128): BigDecimal { + assert!(num2 != 0, error::invalid_argument(EDIVISION_BY_ZERO)); + + BigDecimal { scaled: biguint::div_by_u128(num1.scaled, num2) } + } + + public fun div_by_u256(num1: BigDecimal, num2: u256): BigDecimal { + assert!(num2 != 0, error::invalid_argument(EDIVISION_BY_ZERO)); + + BigDecimal { scaled: biguint::div_by_u256(num1.scaled, num2) } + } + + // cast + + public fun truncate(num: BigDecimal): BigUint { + biguint::div(num.scaled, f()) + } + + public fun truncate_u64(num: BigDecimal): u64 { + biguint::to_u64(truncate(num)) + } + + public fun truncate_u128(num: BigDecimal): u128 { + biguint::to_u128(truncate(num)) + } + + public fun truncate_u256(num: BigDecimal): u256 { + biguint::to_u256(truncate(num)) + } + + public fun round_up(num: BigDecimal): BigUint { + biguint::div(biguint::add(num.scaled, hf()), f()) + } + + public fun round_up_u64(num: BigDecimal): u64 { + biguint::to_u64(round_up(num)) + } + + public fun round_up_u128(num: BigDecimal): u128 { + biguint::to_u128(round_up(num)) + } + + public fun round_up_u256(num: BigDecimal): u256 { + biguint::to_u256(round_up(num)) + } + + public fun ceil(num: BigDecimal): BigUint { + biguint::div(biguint::add(num.scaled, f_1()), f()) + } + + public fun ceil_u64(num: BigDecimal): u64 { + biguint::to_u64(ceil(num)) + } + + public fun ceil_u128(num: BigDecimal): u128 { + biguint::to_u128(ceil(num)) + } + + public fun ceil_u256(num: BigDecimal): u256 { + biguint::to_u256(ceil(num)) + } + + // tests + + #[test] + fun test_bigdecimal() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + let num2 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + assert!(eq(num1, num2), 1); + + let num3 = from_ratio(biguint::from_u64(1), biguint::from_u64(3)); + assert!(lt(num3, num1), 2); + assert!(gt(num1, num3), 3); + + let num4 = add(num1, num3); + assert!( + eq(num4, from_ratio(biguint::from_u64(5), biguint::from_u64(6))), + 4 + ); + + let num5 = sub(num1, num2); + assert!(is_zero(num5), 5); + + let num6 = truncate(num1); + assert!(biguint::is_zero(num6), 6); + + let num7 = round_up(num1); + assert!(biguint::is_one(num7), 7); + + let num8 = round_up(num3); + assert!(biguint::is_zero(num8), 8); + + let num9 = ceil(num3); + assert!(biguint::is_one(num9), 9); + + let num10 = add_by_u64(num1, 1); + assert!( + eq(num10, from_ratio(biguint::from_u64(3), biguint::from_u64(2))), + 10 + ); + + let num11 = sub_by_u64(num10, 1); + assert!( + eq(num11, from_ratio(biguint::from_u64(1), biguint::from_u64(2))), + 11 + ); + + let num12 = mul_by_u64(num1, 2); + assert!(eq(num12, from_u64(1)), 12); + + let num13 = div_by_u64(num1, 2); + assert!( + eq(num13, from_ratio(biguint::from_u64(1), biguint::from_u64(4))), + 13 + ); + } + + #[test] + fun test_bigdecimal_u64() { + let num1 = from_ratio_u64(1, 2); + let num2 = from_ratio_u64(1, 2); + assert!(eq(num1, num2), 1); + + let num3 = from_ratio_u64(1, 3); + assert!(lt(num3, num1), 2); + assert!(gt(num1, num3), 3); + + let num4 = add(num1, num3); + assert!(eq(num4, from_ratio_u64(5, 6)), 4); + + let num5 = sub(num1, num2); + assert!(is_zero(num5), 5); + + let num6 = truncate_u64(num1); + assert!(num6 == 0, 7); + + let num7 = round_up_u64(num1); + assert!(num7 == 1, 8); + + let num8 = round_up_u64(num3); + assert!(num8 == 0, 9); + + let num9 = ceil_u64(num3); + assert!(num9 == 1, 10); + + let num10 = add_by_u64(num1, 1); + assert!(eq(num10, from_ratio_u64(3, 2)), 11); + + let num11 = sub_by_u64(num10, 1); + assert!(eq(num11, from_ratio_u64(1, 2)), 12); + + let num12 = mul_by_u64(num1, 2); + assert!(eq(num12, from_u64(1)), 13); + + let num13 = div_by_u64(num1, 2); + assert!(eq(num13, from_ratio_u64(1, 4)), 14); + } + + #[test] + fun test_bigdecimal_u128() { + let num1 = from_ratio_u128(1, 2); + let num2 = from_ratio_u128(1, 2); + assert!(eq(num1, num2), 1); + + let num3 = from_ratio_u128(1, 3); + assert!(lt(num3, num1), 2); + assert!(gt(num1, num3), 3); + + let num4 = add(num1, num3); + assert!(eq(num4, from_ratio_u128(5, 6)), 4); + + let num5 = sub(num1, num2); + assert!(is_zero(num5), 5); + + let num6 = truncate_u128(num1); + assert!(num6 == 0, 7); + + let num7 = round_up_u128(num1); + assert!(num7 == 1, 8); + + let num8 = round_up_u128(num3); + assert!(num8 == 0, 9); + + let num9 = ceil_u128(num3); + assert!(num9 == 1, 10); + + let num10 = add_by_u128(num1, 1); + assert!(eq(num10, from_ratio_u128(3, 2)), 11); + + let num11 = sub_by_u128(num10, 1); + assert!(eq(num11, from_ratio_u128(1, 2)), 12); + + let num12 = mul_by_u128(num1, 2); + assert!(eq(num12, from_u128(1)), 13); + + let num13 = div_by_u128(num1, 2); + assert!(eq(num13, from_ratio_u128(1, 4)), 14); + } + + #[test] + fun test_bigdecimal_u256() { + let num1 = from_ratio_u256(1, 2); + let num2 = from_ratio_u256(1, 2); + assert!(eq(num1, num2), 1); + + let num3 = from_ratio_u256(1, 3); + assert!(lt(num3, num1), 2); + assert!(gt(num1, num3), 3); + + let num4 = add(num1, num3); + assert!(eq(num4, from_ratio_u256(5, 6)), 4); + + let num5 = sub(num1, num2); + assert!(is_zero(num5), 5); + + let num6 = truncate_u256(num1); + assert!(num6 == 0, 7); + + let num7 = round_up_u256(num1); + assert!(num7 == 1, 8); + + let num8 = round_up_u256(num3); + assert!(num8 == 0, 9); + + let num9 = ceil_u256(num3); + assert!(num9 == 1, 10); + + let num10 = add_by_u256(num1, 1); + assert!(eq(num10, from_ratio_u256(3, 2)), 11); + + let num11 = sub_by_u256(num10, 1); + assert!(eq(num11, from_ratio_u256(1, 2)), 12); + + let num12 = mul_by_u256(num1, 2); + assert!(eq(num12, from_u256(1)), 13); + + let num13 = div_by_u256(num1, 2); + assert!(eq(num13, from_ratio_u256(1, 4)), 14); + } + + #[test] + fun test_bigdecimal_sclaed_value() { + let num1 = div_by_u64(new(biguint::from_u64(1)), 2); + let num2 = get_scaled(num1); + assert!(biguint::eq(num2, biguint::from_u64(500000000000000000)), 1); + + let num3 = from_scaled(num2); + assert!(eq(num1, num3), 2); + } + + #[test] + fun test_bigdecimal_one_zero() { + let num1 = one(); + let num2 = zero(); + assert!(is_one(num1), 1); + assert!(is_zero(num2), 2); + } + + #[test] + fun test_bigdecimal_from_scaled_le_bytes() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(3)); + let num2 = from_scaled_le_bytes(biguint::to_le_bytes(num1.scaled)); + assert!(eq(num1, num2), 1); + } + + #[test] + #[expected_failure(abort_code = 0x10064, location = Self)] + fun test_bigdecimal_sub_negative() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(3)); + let num2 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + + sub(num1, num2); + } + + #[test] + #[expected_failure(abort_code = 0x10064, location = Self)] + fun test_bigdecimal_sub_by_u64_negative() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + + sub_by_u64(num1, 1); + } + + #[test] + #[expected_failure(abort_code = 0x10064, location = Self)] + fun test_bigdecimal_sub_by_u128_negative() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + + sub_by_u128(num1, 1); + } + + #[test] + #[expected_failure(abort_code = 0x10064, location = Self)] + fun test_bigdecimal_sub_by_u256_negative() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + + sub_by_u256(num1, 1); + } + + #[test] + #[expected_failure(abort_code = 0x10065, location = Self)] + fun test_bigdecimal_div_by_zero() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + let num2 = zero(); + + div(num1, num2); + } + + #[test] + #[expected_failure(abort_code = 0x10065, location = Self)] + fun test_bigdecimal_div_by_u64_zero() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + + div_by_u64(num1, 0); + } + + #[test] + #[expected_failure(abort_code = 0x10065, location = Self)] + fun test_bigdecimal_div_by_u128_zero() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + + div_by_u128(num1, 0); + } + + #[test] + #[expected_failure(abort_code = 0x10065, location = Self)] + fun test_bigdecimal_div_by_u256_zero() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(2)); + + div_by_u256(num1, 0); + } + + #[test] + fun test_bigdecimal_scaled_le_bytes() { + let num1 = from_ratio(biguint::from_u64(1), biguint::from_u64(3)); + let le_bytes = get_scaled_le_bytes(num1); + let num2 = from_scaled_le_bytes(le_bytes); + assert!(eq(num1, num2), 1); + } +} diff --git a/minitia_stdlib/sources/biguint.move b/minitia_stdlib/sources/biguint.move new file mode 100644 index 0000000..93bf024 --- /dev/null +++ b/minitia_stdlib/sources/biguint.move @@ -0,0 +1,340 @@ +module minitia_std::biguint { + const NEGATIVE_RESULT: u64 = 100; + const EDIVISION_BY_ZERO: u64 = 101; + const CAST_OVERFLOW: u64 = 102; + const INVALID_NUMERIC_TYPE: u64 = 103; + + struct BigUint has copy, drop, store { + bytes: vector + } + + // creation + + /// Create a new BigUint from little-endian bytes. + public fun from_le_bytes(le_bytes: vector): BigUint { + BigUint { bytes: le_bytes } + } + + public fun zero(): BigUint { + from_u64(0) + } + + public fun one(): BigUint { + from_u64(1) + } + + public fun from_u64(num: u64): BigUint { + let num_bytes = new_internal(num); + BigUint { bytes: num_bytes } + } + + public fun to_u64(num: BigUint): u64 { + cast_internal(num.bytes) + } + + public fun from_u128(num: u128): BigUint { + let num_bytes = new_internal(num); + BigUint { bytes: num_bytes } + } + + public fun to_u128(num: BigUint): u128 { + cast_internal(num.bytes) + } + + public fun from_u256(num: u256): BigUint { + let num_bytes = new_internal(num); + BigUint { bytes: num_bytes } + } + + public fun to_u256(num: BigUint): u256 { + cast_internal(num.bytes) + } + + public fun to_le_bytes(num: BigUint): vector { + num.bytes + } + + // arithmetic + + public fun add(num1: BigUint, num2: BigUint): BigUint { + let result_bytes = add_internal(num1.bytes, num2.bytes); + BigUint { bytes: result_bytes } + } + + public fun add_by_u64(num1: BigUint, num2: u64): BigUint { + let num2 = from_u64(num2); + add(num1, num2) + } + + public fun add_by_u128(num1: BigUint, num2: u128): BigUint { + let num2 = from_u128(num2); + add(num1, num2) + } + + public fun add_by_u256(num1: BigUint, num2: u256): BigUint { + let num2 = from_u256(num2); + add(num1, num2) + } + + public fun sub(num1: BigUint, num2: BigUint): BigUint { + let result_bytes = sub_internal(num1.bytes, num2.bytes); + BigUint { bytes: result_bytes } + } + + public fun sub_by_u64(num1: BigUint, num2: u64): BigUint { + let num2 = from_u64(num2); + sub(num1, num2) + } + + public fun sub_by_u128(num1: BigUint, num2: u128): BigUint { + let num2 = from_u128(num2); + sub(num1, num2) + } + + public fun sub_by_u256(num1: BigUint, num2: u256): BigUint { + let num2 = from_u256(num2); + sub(num1, num2) + } + + public fun mul(num1: BigUint, num2: BigUint): BigUint { + let result_bytes = mul_internal(num1.bytes, num2.bytes); + BigUint { bytes: result_bytes } + } + + public fun mul_by_u64(num1: BigUint, num2: u64): BigUint { + let num2 = from_u64(num2); + mul(num1, num2) + } + + public fun mul_by_u128(num1: BigUint, num2: u128): BigUint { + let num2 = from_u128(num2); + mul(num1, num2) + } + + public fun mul_by_u256(num1: BigUint, num2: u256): BigUint { + let num2 = from_u256(num2); + mul(num1, num2) + } + + public fun div(num1: BigUint, num2: BigUint): BigUint { + let result_bytes = div_internal(num1.bytes, num2.bytes); + BigUint { bytes: result_bytes } + } + + public fun div_by_u64(num1: BigUint, num2: u64): BigUint { + let num2 = from_u64(num2); + div(num1, num2) + } + + public fun div_by_u128(num1: BigUint, num2: u128): BigUint { + let num2 = from_u128(num2); + div(num1, num2) + } + + public fun div_by_u256(num1: BigUint, num2: u256): BigUint { + let num2 = from_u256(num2); + div(num1, num2) + } + + // cmp + + public fun eq(num1: BigUint, num2: BigUint): bool { + num1.bytes == num2.bytes + } + + public fun lt(num1: BigUint, num2: BigUint): bool { + lt_internal(num1.bytes, num2.bytes) + } + + public fun le(num1: BigUint, num2: BigUint): bool { + le_internal(num1.bytes, num2.bytes) + } + + public fun gt(num1: BigUint, num2: BigUint): bool { + gt_internal(num1.bytes, num2.bytes) + } + + public fun ge(num1: BigUint, num2: BigUint): bool { + ge_internal(num1.bytes, num2.bytes) + } + + public fun is_zero(num: BigUint): bool { + eq(num, zero()) + } + + public fun is_one(num: BigUint): bool { + eq(num, one()) + } + + native fun add_internal( + num1_bytes: vector, num2_bytes: vector + ): vector; + native fun sub_internal( + num1_bytes: vector, num2_bytes: vector + ): vector; + native fun mul_internal( + num1_bytes: vector, num2_bytes: vector + ): vector; + native fun div_internal( + num1_bytes: vector, num2_bytes: vector + ): vector; + native fun new_internal(num: T): vector; + native fun cast_internal(num_bytes: vector): T; + native fun lt_internal(num1_bytes: vector, num2_bytes: vector): bool; + native fun le_internal(num1_bytes: vector, num2_bytes: vector): bool; + native fun gt_internal(num1_bytes: vector, num2_bytes: vector): bool; + native fun ge_internal(num1_bytes: vector, num2_bytes: vector): bool; + + #[test] + fun test_biguint_u64() { + let num1 = from_u64(4294967295u64 * 2u64); + let num2 = from_u64(4294967295u64 * 2u64); + let num3 = add(num1, num2); + assert!(to_u64(num3) == 4294967295u64 * 4u64, 1); + let num4 = sub(num1, num2); + assert!(to_u64(num4) == 0, 1); + let num5 = mul(num1, from_u64(2)); + assert!(to_u64(num5) == 4294967295u64 * 4u64, 2); + let num6 = div(num1, from_u64(2)); + assert!(to_u64(num6) == 4294967295u64, 3); + + let num7 = add_by_u64(num1, 1); + assert!(to_u64(num7) == 4294967295u64 * 2u64 + 1u64, 4); + let num8 = sub_by_u64(num1, 1); + assert!(to_u64(num8) == 4294967295u64 * 2u64 - 1u64, 5); + let num9 = mul_by_u64(num1, 2); + assert!(to_u64(num9) == 4294967295u64 * 4u64, 6); + let num10 = div_by_u64(num1, 2); + assert!(to_u64(num10) == 4294967295u64, 7); + } + + #[test] + fun test_biguint_u128() { + let num1 = from_u128(18446744073709551615u128 * 2u128); + let num2 = from_u128(18446744073709551615u128 * 2u128); + let num3 = add(num1, num2); + assert!(to_u128(num3) == 18446744073709551615u128 * 4u128, 1); + let num4 = sub(num1, num2); + assert!(to_u128(num4) == 0, 1); + let num5 = mul(num1, from_u128(2)); + assert!(to_u128(num5) == 18446744073709551615u128 * 4u128, 2); + let num6 = div(num1, from_u128(2)); + assert!(to_u128(num6) == 18446744073709551615u128, 3); + + let num7 = add_by_u128(num1, 1); + assert!(to_u128(num7) == 18446744073709551615u128 * 2u128 + 1u128, 4); + let num8 = sub_by_u128(num1, 1); + assert!(to_u128(num8) == 18446744073709551615u128 * 2u128 - 1u128, 5); + let num9 = mul_by_u128(num1, 2); + assert!(to_u128(num9) == 18446744073709551615u128 * 4u128, 6); + let num10 = div_by_u128(num1, 2); + assert!(to_u128(num10) == 18446744073709551615u128, 7); + } + + #[test] + fun test_biguint_u256() { + let num1 = from_u256(340282366920938463463374607431768211455u256 * 2u256); + let num2 = from_u256(340282366920938463463374607431768211455u256 * 2u256); + let num3 = add(num1, num2); + assert!(to_u256(num3) == 340282366920938463463374607431768211455u256 * 4u256, 1); + let num4 = sub(num1, num2); + assert!(to_u256(num4) == 0, 1); + let num5 = mul(num1, from_u256(2)); + assert!(to_u256(num5) == 340282366920938463463374607431768211455u256 * 4u256, 2); + let num6 = div(num1, from_u256(2)); + assert!(to_u256(num6) == 340282366920938463463374607431768211455u256, 3); + + let num7 = add_by_u256(num1, 1); + assert!( + to_u256(num7) + == 340282366920938463463374607431768211455u256 * 2u256 + 1u256, + 4 + ); + let num8 = sub_by_u256(num1, 1); + assert!( + to_u256(num8) + == 340282366920938463463374607431768211455u256 * 2u256 - 1u256, + 5 + ); + let num9 = mul_by_u256(num1, 2); + assert!(to_u256(num9) == 340282366920938463463374607431768211455u256 * 4u256, 6); + let num10 = div_by_u256(num1, 2); + assert!(to_u256(num10) == 340282366920938463463374607431768211455u256, 7); + } + + #[test] + #[expected_failure(abort_code = 0x10064, location = Self)] + fun test_biguint_sub_negative() { + let num1 = from_u64(1); + let num2 = from_u64(2); + let _ = sub(num1, num2); + } + + #[test] + #[expected_failure(abort_code = 0x10066, location = Self)] + fun test_biguint_case_overflow_u64() { + let num1 = from_u128(18446744073709551616u128); + let _ = cast_internal(num1.bytes); + } + + #[test] + #[expected_failure(abort_code = 0x10066, location = Self)] + fun test_biguint_case_overflow_u128() { + let num1 = from_u256(340282366920938463463374607431768211456u256); + let _ = cast_internal(num1.bytes); + } + + #[test] + #[expected_failure(abort_code = 0x10066, location = Self)] + fun test_biguint_case_overflow_u256() { + let num1 = + from_u256( + 115792089237316195423570985008687907853269984665640564039457584007913129639935u256 + ); + let num1 = mul(num1, from_u64(2u64)); + let _ = cast_internal(num1.bytes); + } + + #[test] + fun test_biguint_max_cast() { + let num1 = from_u64(18446744073709551615u64); + let _ = cast_internal(num1.bytes); + + let num1 = from_u128(340282366920938463463374607431768211454u128); + let _ = cast_internal(num1.bytes); + + let num1 = + from_u256( + 115792089237316195423570985008687907853269984665640564039457584007913129639935u256 + ); + let _ = cast_internal(num1.bytes); + } + + #[test] + #[expected_failure(abort_code = 0x10065, location = Self)] + fun test_biguint_div_by_zero() { + let num1 = from_u64(1); + let num2 = from_u64(0); + let _ = div(num1, num2); + } + + #[test] + fun test_biguint_cmp() { + let num1 = from_u64(1); + let num2 = from_u64(2); + assert!(lt(num1, num2), 1); + assert!(le(num1, num2), 2); + assert!(gt(num2, num1), 3); + assert!(ge(num2, num1), 4); + assert!(eq(num1, num1), 5); + assert!(!eq(num1, num2), 6); + } + + #[test] + fun test_biguint_from_le_bytes() { + let num1 = from_u64(1123); + let bytes = to_le_bytes(num1); + let num2 = from_le_bytes(bytes); + assert!(eq(num1, num2), 1); + } +} diff --git a/minitia_stdlib/sources/block.move b/minitia_stdlib/sources/block.move index 4e461a4..118f187 100644 --- a/minitia_stdlib/sources/block.move +++ b/minitia_stdlib/sources/block.move @@ -12,4 +12,44 @@ module minitia_std::block { assert!(height == 12321u64, 0); assert!(timestamp == 9999999u64, 1); } + + // Functions for compatibility with the aptos + + #[view] + public fun get_current_block_height(): u64 { + let (height, _) = get_block_info(); + height + } + + #[view] + public fun get_current_block_timestamp(): u64 { + let (_, timestamp) = get_block_info(); + timestamp + } + + #[test_only] + public fun initialize_for_test( + _vm: &signer, _epoch_interval_microsecs: u64 + ) { + // no-op + } + + #[test_only] + use minitia_std::signer; + + #[test_only] + struct HasGenesisBlock has key {} + + #[test_only] + public fun emit_writeset_block_event( + vm: &signer, _fake_block_hash: address + ) { + if (!exists(signer::address_of(vm))) { + move_to(vm, HasGenesisBlock {}); + return + }; + + let (block_height, block_time) = get_block_info(); + set_block_info(block_height + 1, block_time); + } } diff --git a/minitia_stdlib/sources/code.move b/minitia_stdlib/sources/code.move index 09e178f..34bc7d9 100644 --- a/minitia_stdlib/sources/code.move +++ b/minitia_stdlib/sources/code.move @@ -4,7 +4,9 @@ module minitia_std::code { use std::signer; use std::vector; use std::event; + use std::option; + use minitia_std::object::{Self, Object}; use minitia_std::table::{Self, Table}; use minitia_std::simple_map; @@ -17,11 +19,11 @@ module minitia_std::code { allowed_publishers: vector
, /// The total number of modules published. - total_modules: u64, + total_modules: u64 } struct MetadataStore has key { - metadata: Table, + metadata: Table } /// Describes an upgrade policy @@ -32,7 +34,7 @@ module minitia_std::code { #[event] struct ModulePublishedEvent has store, drop { module_id: String, - upgrade_policy: u8, + upgrade_policy: u8 } /// Cannot upgrade an immutable package. @@ -56,6 +58,12 @@ module minitia_std::code { /// The module ID is duplicated. const EDUPLICATE_MODULE_ID: u64 = 0x7; + /// Not the owner of the package registry. + const ENOT_PACKAGE_OWNER: u64 = 0x8; + + /// `code_object` does not exist. + const ECODE_OBJECT_DOES_NOT_EXIST: u64 = 0x9; + /// Whether a compatibility check should be performed for upgrades. The check only passes if /// a new module has (a) the same public functions (b) for existing resources, no layout change. const UPGRADE_POLICY_COMPATIBLE: u8 = 1; @@ -72,7 +80,7 @@ module minitia_std::code { fun init_module(chain: &signer) { move_to( chain, - ModuleStore { allowed_publishers: vector[], total_modules: 0, }, + ModuleStore { allowed_publishers: vector[], total_modules: 0 } ); } @@ -103,18 +111,16 @@ module minitia_std::code { assert!( vector::is_empty(allowed_publishers) || vector::contains(allowed_publishers, &addr), - error::invalid_argument(EINVALID_ALLOWED_PUBLISHERS), + error::invalid_argument(EINVALID_ALLOWED_PUBLISHERS) ) } public entry fun init_genesis( - chain: &signer, - module_ids: vector, - allowed_publishers: vector
, + chain: &signer, module_ids: vector, allowed_publishers: vector
) acquires ModuleStore { assert!( signer::address_of(chain) == @minitia_std, - error::permission_denied(EINVALID_CHAIN_OPERATOR), + error::permission_denied(EINVALID_CHAIN_OPERATOR) ); let metadata_table = table::new(); @@ -124,14 +130,14 @@ module minitia_std::code { table::add( &mut metadata_table, *module_id, - ModuleMetadata { upgrade_policy: UPGRADE_POLICY_COMPATIBLE, }, + ModuleMetadata { upgrade_policy: UPGRADE_POLICY_COMPATIBLE } ); - }, + } ); move_to( chain, - MetadataStore { metadata: metadata_table, }, + MetadataStore { metadata: metadata_table } ); set_allowed_publishers(chain, allowed_publishers); @@ -143,7 +149,7 @@ module minitia_std::code { ) acquires ModuleStore { assert!( signer::address_of(chain) == @minitia_std, - error::permission_denied(EINVALID_CHAIN_OPERATOR), + error::permission_denied(EINVALID_CHAIN_OPERATOR) ); assert_allowed(&allowed_publishers, @minitia_std); @@ -151,18 +157,43 @@ module minitia_std::code { module_store.allowed_publishers = allowed_publishers; } + public fun freeze_code_object( + publisher: &signer, code_object: Object + ) acquires MetadataStore { + let code_object_addr = object::object_address(&code_object); + assert!( + exists(code_object_addr), + error::not_found(ECODE_OBJECT_DOES_NOT_EXIST) + ); + assert!( + object::is_owner(code_object, signer::address_of(publisher)), + error::permission_denied(ENOT_PACKAGE_OWNER) + ); + + let registry = borrow_global_mut(code_object_addr); + let iter = table::iter_mut( + &mut registry.metadata, option::none(), option::none(), 1 + ); + loop { + if (!table::prepare_mut(iter)) { break }; + + let (_, metadata) = table::next_mut(iter); + metadata.upgrade_policy = UPGRADE_POLICY_IMMUTABLE; + } + } + /// Publishes a package at the given signer's address. The caller must provide package metadata describing the /// package. public entry fun publish( owner: &signer, module_ids: vector, // 0x1::coin code: vector>, - upgrade_policy: u8, + upgrade_policy: u8 ) acquires ModuleStore, MetadataStore { // Disallow incompatible upgrade mode. Governance can decide later if this should be reconsidered. assert!( vector::length(&code) == vector::length(&module_ids), - error::invalid_argument(EINVALID_ARGUMENTS), + error::invalid_argument(EINVALID_ARGUMENTS) ); // duplication check @@ -172,14 +203,14 @@ module minitia_std::code { |module_id| { assert!( !simple_map::contains_key(&module_ids_set, module_id), - error::invalid_argument(EDUPLICATE_MODULE_ID), + error::invalid_argument(EDUPLICATE_MODULE_ID) ); simple_map::add( &mut module_ids_set, *module_id, - true, + true ); - }, + } ); // Check whether arbitrary publish is allowed or not. @@ -187,7 +218,7 @@ module minitia_std::code { assert!( upgrade_policy == UPGRADE_POLICY_COMPATIBLE || upgrade_policy == UPGRADE_POLICY_IMMUTABLE, - error::invalid_argument(EUPGRADE_POLICY_UNSPECIFIED), + error::invalid_argument(EUPGRADE_POLICY_UNSPECIFIED) ); let addr = signer::address_of(owner); @@ -196,7 +227,7 @@ module minitia_std::code { if (!exists(addr)) { move_to( owner, - MetadataStore { metadata: table::new(), }, + MetadataStore { metadata: table::new() } ); }; @@ -212,14 +243,14 @@ module minitia_std::code { ); assert!( metadata.upgrade_policy < UPGRADE_POLICY_IMMUTABLE, - error::invalid_argument(EUPGRADE_IMMUTABLE), + error::invalid_argument(EUPGRADE_IMMUTABLE) ); assert!( can_change_upgrade_policy_to( metadata.upgrade_policy, - upgrade_policy, + upgrade_policy ), - error::invalid_argument(EUPGRADE_WEAKER_POLICY), + error::invalid_argument(EUPGRADE_WEAKER_POLICY) ); metadata.upgrade_policy = upgrade_policy; @@ -227,14 +258,14 @@ module minitia_std::code { table::add( metadata_table, *module_id, - ModuleMetadata { upgrade_policy, }, + ModuleMetadata { upgrade_policy } ); }; event::emit( - ModulePublishedEvent { module_id: *module_id, upgrade_policy, }, + ModulePublishedEvent { module_id: *module_id, upgrade_policy } ); - }, + } ); // Request publish @@ -244,6 +275,6 @@ module minitia_std::code { /// Native function to initiate module loading native fun request_publish( - owner: address, expected_modules: vector, code: vector>, + owner: address, expected_modules: vector, code: vector> ); } diff --git a/minitia_stdlib/sources/coin.move b/minitia_stdlib/sources/coin.move index e2af926..73052bb 100644 --- a/minitia_stdlib/sources/coin.move +++ b/minitia_stdlib/sources/coin.move @@ -25,7 +25,7 @@ module minitia_std::coin { struct ManagingRefs has key { mint_ref: MintRef, burn_ref: BurnRef, - transfer_ref: TransferRef, + transfer_ref: TransferRef } /// Only fungible asset metadata owner can make changes. @@ -36,19 +36,19 @@ module minitia_std::coin { #[event] struct CoinCreatedEvent has drop, store { - metadata_addr: address, + metadata_addr: address } struct MintCapability has drop, store { - metadata: Object, + metadata: Object } struct BurnCapability has drop, store { - metadata: Object, + metadata: Object } struct FreezeCapability has drop, store { - metadata: Object, + metadata: Object } const EUNAUTHORIZED: u64 = 1; @@ -60,7 +60,7 @@ module minitia_std::coin { fun check_sudo(account: &signer) { assert!( signer::address_of(account) == @minitia_std, - error::permission_denied(EUNAUTHORIZED), + error::permission_denied(EUNAUTHORIZED) ); } @@ -69,7 +69,7 @@ module minitia_std::coin { sender: &signer, recipient: address, metadata: Object, - amount: u64, + amount: u64 ) { check_sudo(chain); @@ -77,7 +77,7 @@ module minitia_std::coin { } public(friend) fun sudo_deposit( - account_addr: address, fa: FungibleAsset, + account_addr: address, fa: FungibleAsset ) { primary_fungible_store::sudo_deposit(account_addr, fa) } @@ -93,7 +93,7 @@ module minitia_std::coin { symbol: String, decimals: u8, icon_uri: String, - project_uri: String, + project_uri: String ): (MintCapability, BurnCapability, FreezeCapability) { let (mint_cap, burn_cap, freeze_cap, _) = initialize_and_generate_extend_ref( @@ -103,7 +103,7 @@ module minitia_std::coin { symbol, decimals, icon_uri, - project_uri, + project_uri ); (mint_cap, burn_cap, freeze_cap) @@ -116,13 +116,13 @@ module minitia_std::coin { symbol: String, decimals: u8, icon_uri: String, - project_uri: String, + project_uri: String ): (MintCapability, BurnCapability, FreezeCapability, ExtendRef) { // create object for fungible asset metadata let constructor_ref = &object::create_named_object( creator, - *string::bytes(&symbol), + *string::bytes(&symbol) ); primary_fungible_store::create_primary_store_enabled_fungible_asset( @@ -132,7 +132,7 @@ module minitia_std::coin { symbol, decimals, icon_uri, - project_uri, + project_uri ); let mint_ref = fungible_asset::generate_mint_ref(constructor_ref); @@ -142,11 +142,11 @@ module minitia_std::coin { let object_signer = object::generate_signer(constructor_ref); move_to( &object_signer, - ManagingRefs { mint_ref, burn_ref, transfer_ref, }, + ManagingRefs { mint_ref, burn_ref, transfer_ref } ); let metadata_addr = object::address_from_constructor_ref(constructor_ref); - event::emit(CoinCreatedEvent { metadata_addr, }); + event::emit(CoinCreatedEvent { metadata_addr }); let metadata = object::object_from_constructor_ref(constructor_ref); ( @@ -158,14 +158,12 @@ module minitia_std::coin { } public fun withdraw( - account: &signer, - metadata: Object, - amount: u64, + account: &signer, metadata: Object, amount: u64 ): FungibleAsset { primary_fungible_store::withdraw(account, metadata, amount) } - public fun deposit(account_addr: address, fa: FungibleAsset,) { + public fun deposit(account_addr: address, fa: FungibleAsset) { primary_fungible_store::deposit(account_addr, fa) } @@ -173,7 +171,7 @@ module minitia_std::coin { sender: &signer, recipient: address, metadata: Object, - amount: u64, + amount: u64 ) { primary_fungible_store::transfer(sender, metadata, recipient, amount) } @@ -183,13 +181,13 @@ module minitia_std::coin { // /// Mint FAs as the owner of metadat object. - public fun mint(mint_cap: &MintCapability, amount: u64,): FungibleAsset acquires ManagingRefs { + public fun mint(mint_cap: &MintCapability, amount: u64): FungibleAsset acquires ManagingRefs { let metadata = mint_cap.metadata; let metadata_addr = object::object_address(&metadata); assert!( exists(metadata_addr), - ERR_MANAGING_REFS_NOT_FOUND, + ERR_MANAGING_REFS_NOT_FOUND ); let refs = borrow_global(metadata_addr); @@ -198,16 +196,14 @@ module minitia_std::coin { /// Mint FAs as the owner of metadat object to the primary fungible store of the given recipient. public fun mint_to( - mint_cap: &MintCapability, - recipient: address, - amount: u64, + mint_cap: &MintCapability, recipient: address, amount: u64 ) acquires ManagingRefs { let metadata = mint_cap.metadata; let metadata_addr = object::object_address(&metadata); assert!( exists(metadata_addr), - ERR_MANAGING_REFS_NOT_FOUND, + ERR_MANAGING_REFS_NOT_FOUND ); let refs = borrow_global(metadata_addr); @@ -215,13 +211,13 @@ module minitia_std::coin { } /// Burn FAs as the owner of metadat object. - public fun burn(burn_cap: &BurnCapability, fa: FungibleAsset,) acquires ManagingRefs { + public fun burn(burn_cap: &BurnCapability, fa: FungibleAsset) acquires ManagingRefs { let metadata = burn_cap.metadata; let metadata_addr = object::object_address(&metadata); assert!( exists(metadata_addr), - ERR_MANAGING_REFS_NOT_FOUND, + ERR_MANAGING_REFS_NOT_FOUND ); let refs = borrow_global(metadata_addr); @@ -230,41 +226,41 @@ module minitia_std::coin { /// Freeze the primary store of an account. public fun freeze_coin_store( - freeze_cap: &FreezeCapability, account_addr: address, + freeze_cap: &FreezeCapability, account_addr: address ) acquires ManagingRefs { let metadata = freeze_cap.metadata; let metadata_addr = object::object_address(&metadata); assert!( exists(metadata_addr), - ERR_MANAGING_REFS_NOT_FOUND, + ERR_MANAGING_REFS_NOT_FOUND ); let refs = borrow_global(metadata_addr); primary_fungible_store::set_frozen_flag( &refs.transfer_ref, account_addr, - true, + true ) } /// Unfreeze the primary store of an account. public fun unfreeze_coin_store( - freeze_cap: &FreezeCapability, account_addr: address, + freeze_cap: &FreezeCapability, account_addr: address ) acquires ManagingRefs { let metadata = freeze_cap.metadata; let metadata_addr = object::object_address(&metadata); assert!( exists(metadata_addr), - ERR_MANAGING_REFS_NOT_FOUND, + ERR_MANAGING_REFS_NOT_FOUND ); let refs = borrow_global(metadata_addr); primary_fungible_store::set_frozen_flag( &refs.transfer_ref, account_addr, - false, + false ) } @@ -284,9 +280,7 @@ module minitia_std::coin { #[view] public fun balances( - account: address, - start_after: Option
, - limit: u8, + account: address, start_after: Option
, limit: u8 ): (vector>, vector) { primary_fungible_store::balances(account, start_after, limit) } @@ -363,7 +357,7 @@ module minitia_std::coin { public fun denom_to_metadata(denom: String): Object { let addr = if (string::length(&denom) > 5 - && &b"move/" == string::bytes(&string::sub_string(&denom, 0, 5))) { + && &b"move/" == string::bytes(&string::sub_string(&denom, 0, 5))) { let len = string::length(&denom); let hex_string = string::sub_string(&denom, 5, len); from_bcs::to_address(hex::decode_string(&hex_string)) @@ -374,11 +368,13 @@ module minitia_std::coin { object::address_to_object(addr) } + // for lz compatibility + struct Coin {} + #[test_only] - fun initialized_coin(account: &signer, symbol: String,) - : ( - BurnCapability, FreezeCapability, MintCapability - ) { + fun initialize_coin_for_testing( + account: &signer, symbol: String + ): (BurnCapability, FreezeCapability, MintCapability) { let (mint_cap, burn_cap, freeze_cap, _) = initialize_and_generate_extend_ref( account, @@ -387,25 +383,25 @@ module minitia_std::coin { symbol, 6, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); return (burn_cap, freeze_cap, mint_cap) } #[test(chain = @0x1, not_chain = @0x2)] - fun test_denom_metadata_convert(chain: signer, not_chain: signer,) { + fun test_denom_metadata_convert(chain: signer, not_chain: signer) { minitia_std::primary_fungible_store::init_module_for_test(); - initialized_coin(&chain, string::utf8(b"INIT")); - initialized_coin(¬_chain, string::utf8(b"INIT")); + initialize_coin_for_testing(&chain, string::utf8(b"INIT")); + initialize_coin_for_testing(¬_chain, string::utf8(b"INIT")); let metadata = metadata( std::signer::address_of(&chain), - string::utf8(b"INIT"), + string::utf8(b"INIT") ); let metadata_ = metadata( std::signer::address_of(¬_chain), - string::utf8(b"INIT"), + string::utf8(b"INIT") ); let denom = metadata_to_denom(metadata); let denom_ = metadata_to_denom(metadata_); diff --git a/minitia_stdlib/sources/comparator.move b/minitia_stdlib/sources/comparator.move index cf2ad15..7e1929a 100644 --- a/minitia_stdlib/sources/comparator.move +++ b/minitia_stdlib/sources/comparator.move @@ -8,7 +8,7 @@ module minitia_std::comparator { const GREATER: u8 = 2; struct Result has drop { - inner: u8, + inner: u8 } public fun is_equal(result: &Result): bool { @@ -73,29 +73,29 @@ module minitia_std::comparator { assert!( is_greater_than(&compare(&value0, &value1)), - 3, + 3 ); assert!( is_smaller_than(&compare(&value1, &value0)), - 4, + 4 ); assert!( is_smaller_than(&compare(&value0, &value2)), - 5, + 5 ); assert!( is_greater_than(&compare(&value2, &value0)), - 6, + 6 ); assert!( is_smaller_than(&compare(&value1, &value2)), - 7, + 7 ); assert!( is_greater_than(&compare(&value2, &value1)), - 8, + 8 ); } @@ -111,29 +111,29 @@ module minitia_std::comparator { assert!( is_smaller_than(&compare(&value0, &value1)), - 2, + 2 ); assert!( is_greater_than(&compare(&value1, &value0)), - 3, + 3 ); assert!( is_smaller_than(&compare(&value0, &value2)), - 3, + 3 ); assert!( is_greater_than(&compare(&value2, &value0)), - 4, + 4 ); assert!( is_smaller_than(&compare(&value1, &value2)), - 5, + 5 ); assert!( is_greater_than(&compare(&value2, &value1)), - 6, + 6 ); } @@ -141,7 +141,7 @@ module minitia_std::comparator { struct Complex has drop { value0: vector, value1: u8, - value2: u64, + value2: u64 } #[test] @@ -157,13 +157,13 @@ module minitia_std::comparator { vector::push_back(&mut value0_1, 5); vector::push_back(&mut value0_1, 1); - let base = Complex { value0: value0_0, value1: 13, value2: 41, }; + let base = Complex { value0: value0_0, value1: 13, value2: 41 }; - let other_0 = Complex { value0: value0_1, value1: 13, value2: 41, }; + let other_0 = Complex { value0: value0_1, value1: 13, value2: 41 }; - let other_1 = Complex { value0: copy value0_0, value1: 14, value2: 41, }; + let other_1 = Complex { value0: copy value0_0, value1: 14, value2: 41 }; - let other_2 = Complex { value0: value0_0, value1: 13, value2: 42, }; + let other_2 = Complex { value0: value0_0, value1: 13, value2: 42 }; assert!(is_equal(&compare(&base, &base)), 0); assert!(is_smaller_than(&compare(&base, &other_0)), 1); diff --git a/minitia_stdlib/sources/compatibility/aptos_coin.move b/minitia_stdlib/sources/compatibility/aptos_coin.move index 0e8edfa..fde1691 100644 --- a/minitia_stdlib/sources/compatibility/aptos_coin.move +++ b/minitia_stdlib/sources/compatibility/aptos_coin.move @@ -16,14 +16,14 @@ module minitia_std::aptos_coin { string::utf8(b"uinit"), 0, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); }; managed_coin::mint( &account::create_signer_for_test(@minitia_std), coin::metadata(@minitia_std, string::utf8(b"uinit")), - amount, + amount ) } diff --git a/minitia_stdlib/sources/compatibility/reconfiguration.move b/minitia_stdlib/sources/compatibility/reconfiguration.move new file mode 100644 index 0000000..b36fac9 --- /dev/null +++ b/minitia_stdlib/sources/compatibility/reconfiguration.move @@ -0,0 +1,6 @@ +#[test_only] +module minitia_std::reconfiguration { + public fun initialize_for_test(_: &signer) { + // no-op + } +} diff --git a/minitia_stdlib/sources/copyable_any.move b/minitia_stdlib/sources/copyable_any.move index 01171e7..6739db7 100644 --- a/minitia_stdlib/sources/copyable_any.move +++ b/minitia_stdlib/sources/copyable_any.move @@ -17,14 +17,17 @@ module minitia_std::copyable_any { /// Pack a value into the `Any` representation. Because Any can be stored, dropped, and copied this is /// also required from `T`. public fun pack(x: T): Any { - Any { type_name: type_info::type_name(), data: bcs::to_bytes(&x) } + Any { + type_name: type_info::type_name(), + data: bcs::to_bytes(&x) + } } /// Unpack a value from the `Any` representation. This aborts if the value has not the expected type `T`. public fun unpack(x: Any): T { assert!( type_info::type_name() == x.type_name, - error::invalid_argument(ETYPE_MISMATCH), + error::invalid_argument(ETYPE_MISMATCH) ); from_bytes(x.data) } diff --git a/minitia_stdlib/sources/cosmos.move b/minitia_stdlib/sources/cosmos.move index b432fe4..fd37bbf 100644 --- a/minitia_stdlib/sources/cosmos.move +++ b/minitia_stdlib/sources/cosmos.move @@ -15,7 +15,7 @@ module minitia_std::cosmos { proposal_id: u64, voter: String, option: u64, - metadata: String, + metadata: String } public entry fun stargate_vote( @@ -33,9 +33,9 @@ module minitia_std::cosmos { proposal_id, voter, option, - metadata, - }, - ), + metadata + } + ) ); } @@ -49,7 +49,7 @@ module minitia_std::cosmos { module_name: String, function_name: String, type_args: vector, - args: vector>, + args: vector> ) { move_execute_internal( signer::address_of(sender), @@ -58,7 +58,7 @@ module minitia_std::cosmos { *string::bytes(&function_name), vector::map_ref(&type_args, |v| *string::bytes(v)), args, - false, + false ) } @@ -68,7 +68,7 @@ module minitia_std::cosmos { module_name: String, function_name: String, type_args: vector, - args: vector, + args: vector ) { move_execute_internal( signer::address_of(sender), @@ -77,7 +77,7 @@ module minitia_std::cosmos { *string::bytes(&function_name), vector::map_ref(&type_args, |v| *string::bytes(v)), vector::map_ref(&args, |v| *string::bytes(v)), - true, + true ) } @@ -85,14 +85,14 @@ module minitia_std::cosmos { sender: &signer, code_bytes: vector, type_args: vector, - args: vector>, + args: vector> ) { move_script_internal( signer::address_of(sender), code_bytes, vector::map_ref(&type_args, |v| *string::bytes(v)), args, - false, + false ) } @@ -100,14 +100,14 @@ module minitia_std::cosmos { sender: &signer, code_bytes: vector, type_args: vector, - args: vector, + args: vector ) { move_script_internal( signer::address_of(sender), code_bytes, vector::map_ref(&type_args, |v| *string::bytes(v)), vector::map_ref(&args, |v| *string::bytes(v)), - true, + true ) } @@ -115,25 +115,23 @@ module minitia_std::cosmos { delegator: &signer, validator: String, metadata: Object, - amount: u64, + amount: u64 ) { delegate_internal( signer::address_of(delegator), *string::bytes(&validator), &metadata, - amount, + amount ) } public entry fun fund_community_pool( - sender: &signer, - metadata: Object, - amount: u64, + sender: &signer, metadata: Object, amount: u64 ) { fund_community_pool_internal( signer::address_of(sender), &metadata, - amount, + amount ) } @@ -149,7 +147,7 @@ module minitia_std::cosmos { revision_number: u64, revision_height: u64, timeout_timestamp: u64, - memo: String, + memo: String ) { transfer_internal( signer::address_of(sender), @@ -161,7 +159,7 @@ module minitia_std::cosmos { revision_number, revision_height, timeout_timestamp, - *string::bytes(&memo), + *string::bytes(&memo) ) } @@ -177,7 +175,7 @@ module minitia_std::cosmos { revision_number: u64, revision_height: u64, timeout_timestamp: u64, - memo: String, + memo: String ) { nft_transfer_internal( signer::address_of(sender), @@ -189,7 +187,7 @@ module minitia_std::cosmos { revision_number, revision_height, timeout_timestamp, - *string::bytes(&memo), + *string::bytes(&memo) ) } @@ -204,7 +202,7 @@ module minitia_std::cosmos { ack_fee_metadata: Object, ack_fee_amount: u64, timeout_fee_metadata: Object, - timeout_fee_amount: u64, + timeout_fee_amount: u64 ) { pay_fee_internal( signer::address_of(sender), @@ -215,11 +213,11 @@ module minitia_std::cosmos { &ack_fee_metadata, ack_fee_amount, &timeout_fee_metadata, - timeout_fee_amount, + timeout_fee_amount ) } - native fun stargate_internal(sender: address, data: vector,); + native fun stargate_internal(sender: address, data: vector); native fun move_execute_internal( sender: address, @@ -228,7 +226,7 @@ module minitia_std::cosmos { function_name: vector, type_args: vector>, args: vector>, - is_json: bool, + is_json: bool ); native fun move_script_internal( @@ -236,18 +234,18 @@ module minitia_std::cosmos { code_bytes: vector, type_args: vector>, args: vector>, - is_json: bool, + is_json: bool ); native fun delegate_internal( delegator: address, validator: vector, metadata: &Object, - amount: u64, + amount: u64 ); native fun fund_community_pool_internal( - sender: address, metadata: &Object, amount: u64, + sender: address, metadata: &Object, amount: u64 ); native fun transfer_internal( @@ -260,7 +258,7 @@ module minitia_std::cosmos { revision_number: u64, revision_height: u64, timeout_timestamp: u64, - memo: vector, + memo: vector ); native fun nft_transfer_internal( @@ -273,7 +271,7 @@ module minitia_std::cosmos { revision_number: u64, revision_height: u64, timeout_timestamp: u64, - memo: vector, + memo: vector ); native fun pay_fee_internal( @@ -285,6 +283,6 @@ module minitia_std::cosmos { ack_fee_metadata: &Object, ack_fee_amount: u64, timeout_fee_metadata: &Object, - timeout_fee_amount: u64, + timeout_fee_amount: u64 ); } diff --git a/minitia_stdlib/sources/crypto/ed25519.move b/minitia_stdlib/sources/crypto/ed25519.move index 11a4c07..c8c8629 100644 --- a/minitia_stdlib/sources/crypto/ed25519.move +++ b/minitia_stdlib/sources/crypto/ed25519.move @@ -44,7 +44,7 @@ module minitia_std::ed25519 { public fun public_key_from_bytes(bytes: vector): PublicKey { assert!( std::vector::length(&bytes) == PUBLIC_KEY_SIZE, - std::error::invalid_argument(PUBLIC_KEY_SIZE), + std::error::invalid_argument(PUBLIC_KEY_SIZE) ); PublicKey { bytes } } @@ -53,7 +53,7 @@ module minitia_std::ed25519 { public fun signature_from_bytes(bytes: vector): Signature { assert!( std::vector::length(&bytes) == SIGNATURE_SIZE, - std::error::invalid_argument(E_WRONG_SIGNATURE_SIZE), + std::error::invalid_argument(E_WRONG_SIGNATURE_SIZE) ); Signature { bytes } } @@ -70,14 +70,12 @@ module minitia_std::ed25519 { /// Verifies a Ed25519 `signature` under an `public_key` on the specified `message`. public fun verify( - message: vector, - public_key: &PublicKey, - signature: &Signature, + message: vector, public_key: &PublicKey, signature: &Signature ): bool { verify_internal( message, public_key.bytes, - signature.bytes, + signature.bytes ) } @@ -100,7 +98,7 @@ module minitia_std::ed25519 { public fun batch_verify( messages: vector>, public_keys: vector, - signatures: vector, + signatures: vector ): bool { let message_length = std::vector::length(&messages); let public_key_length = std::vector::length(&public_keys); @@ -109,19 +107,20 @@ module minitia_std::ed25519 { if (message_length == 1) { assert!( public_key_length == signature_length, - std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH), + std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH) ); if (public_key_length == 0) return true; } else if (public_key_length == 1) { assert!( message_length == signature_length, - std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH), + std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH) ); if (message_length == 0) return true; } else { assert!( - message_length == public_key_length && public_key_length == signature_length, - std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH), + message_length == public_key_length + && public_key_length == signature_length, + std::error::invalid_argument(E_UNMATCHED_ARGS_LENGTH) ); if (message_length == 0) return true; }; diff --git a/minitia_stdlib/sources/crypto/secp256k1.move b/minitia_stdlib/sources/crypto/secp256k1.move index c39125c..c493245 100644 --- a/minitia_stdlib/sources/crypto/secp256k1.move +++ b/minitia_stdlib/sources/crypto/secp256k1.move @@ -45,7 +45,7 @@ module minitia_std::secp256k1 { public fun ecdsa_signature_from_bytes(bytes: vector): ECDSASignature { assert!( std::vector::length(&bytes) == SIGNATURE_NUM_BYTES, - std::error::invalid_argument(E_DESERIALIZE), + std::error::invalid_argument(E_DESERIALIZE) ); ECDSASignature { bytes } } @@ -59,17 +59,17 @@ module minitia_std::secp256k1 { public fun ecdsa_raw_public_key_from_bytes(bytes: vector): ECDSARawPublicKey { assert!( std::vector::length(&bytes) == RAW_PUBLIC_KEY_NUM_BYTES, - std::error::invalid_argument(E_DESERIALIZE), + std::error::invalid_argument(E_DESERIALIZE) ); ECDSARawPublicKey { bytes } } /// Constructs an ECDSACompressedPublicKey struct, given a 33-byte raw representation. - public fun ecdsa_compressed_public_key_from_bytes(bytes: vector) - : ECDSACompressedPublicKey { + public fun ecdsa_compressed_public_key_from_bytes(bytes: vector): + ECDSACompressedPublicKey { assert!( std::vector::length(&bytes) == COMPRESSED_PUBLIC_KEY_SIZE, - std::error::invalid_argument(E_DESERIALIZE), + std::error::invalid_argument(E_DESERIALIZE) ); ECDSACompressedPublicKey { bytes } } @@ -91,6 +91,24 @@ module minitia_std::secp256k1 { sig.bytes } + /// Returns `true` if the signature can verify the public key on the message + public fun verify( + message: vector, + public_key: &ECDSACompressedPublicKey, + signature: &ECDSASignature + ): bool { + assert!( + std::vector::length(&message) == MESSAGE_SIZE, + std::error::invalid_argument(E_DESERIALIZE) + ); + + return verify_internal( + message, + public_key.bytes, + signature.bytes + ) + } + /// Recovers the signer's raw (64-byte) public key from a secp256k1 ECDSA `signature` given the `recovery_id` and the signed /// `message` (32 byte digest). /// @@ -98,13 +116,11 @@ module minitia_std::secp256k1 { /// incorrect public key. This recovery algorithm can only be used to check validity of a signature if the signer's /// public key (or its hash) is known beforehand. public fun ecdsa_recover( - message: vector, - recovery_id: u8, - signature: &ECDSASignature, + message: vector, recovery_id: u8, signature: &ECDSASignature ): Option { assert!( std::vector::length(&message) == MESSAGE_SIZE, - std::error::invalid_argument(E_DESERIALIZE), + std::error::invalid_argument(E_DESERIALIZE) ); let (pk, success) = @@ -112,7 +128,7 @@ module minitia_std::secp256k1 { recovery_id, message, signature.bytes, - false, + false ); if (success) { std::option::some(ecdsa_raw_public_key_from_bytes(pk)) @@ -128,13 +144,11 @@ module minitia_std::secp256k1 { /// incorrect public key. This recovery algorithm can only be used to check validity of a signature if the signer's /// public key (or its hash) is known beforehand. public fun ecdsa_recover_compressed( - message: vector, - recovery_id: u8, - signature: &ECDSASignature, + message: vector, recovery_id: u8, signature: &ECDSASignature ): Option { assert!( std::vector::length(&message) == MESSAGE_SIZE, - std::error::invalid_argument(E_DESERIALIZE), + std::error::invalid_argument(E_DESERIALIZE) ); let (pk, success) = @@ -142,7 +156,7 @@ module minitia_std::secp256k1 { recovery_id, message, signature.bytes, - true, + true ); if (success) { std::option::some(ecdsa_compressed_public_key_from_bytes(pk)) @@ -155,10 +169,25 @@ module minitia_std::secp256k1 { // Native functions // + /// Returns `true` if `signature` verifies on `public_key` and `message` + /// and returns `false` otherwise. + /// + /// - `message`: A 32-byte hashed message. + /// - `public_key`: A compressed public key in bytes. + /// - `signature`: A 64-byte ECDSA signature. + native fun verify_internal( + message: vector, + public_key: vector, + signature: vector + ): bool; + /// Returns `(public_key, true)` if `signature` verifies on `message` under the recovered `public_key` /// and returns `([], false)` otherwise. native fun recover_public_key_internal( - recovery_id: u8, message: vector, signature: vector, compressed: bool, + recovery_id: u8, + message: vector, + signature: vector, + compressed: bool ): (vector, bool); #[test_only] @@ -173,6 +202,29 @@ module minitia_std::secp256k1 { // Tests // + #[test] + fun test_secp256k1_sign_verify() { + use std::hash; + + let (sk, vk) = generate_keys(true); + let pk = ecdsa_compressed_public_key_from_bytes(vk); + + let msg: vector = hash::sha2_256(b"test initia secp256k1"); + let (_rid, sig_bytes) = sign(msg, sk); + let sig = ecdsa_signature_from_bytes(sig_bytes); + assert!(verify(msg, &pk, &sig), 1); + + // Test with an incorrect message + let wrong_msg: vector = hash::sha2_256(b"wrong message"); + assert!(!verify(wrong_msg, &pk, &sig), 2); + + // Test with an incorrect signature + let invalid_sig_bytes = sig_bytes; + *std::vector::borrow_mut(&mut invalid_sig_bytes, 0) = 0xFF; // Corrupt the signature + let invalid_sig = ecdsa_signature_from_bytes(invalid_sig_bytes); + assert!(!verify(msg, &pk, &invalid_sig), 3); + } + #[test] fun test_gen_sign_recover() { use std::hash; @@ -187,7 +239,7 @@ module minitia_std::secp256k1 { assert!(std::option::is_some(&recovered_pk), 1); assert!( std::option::extract(&mut recovered_pk).bytes == pk.bytes, - 2, + 2 ); let wrong_msg: vector = hash::sha2_256(b"test initia"); @@ -195,7 +247,7 @@ module minitia_std::secp256k1 { assert!(std::option::is_some(&recovered_pk), 3); assert!( std::option::extract(&mut recovered_pk).bytes != pk.bytes, - 4, + 4 ); } @@ -213,7 +265,7 @@ module minitia_std::secp256k1 { assert!(std::option::is_some(&recovered_pk), 1); assert!( std::option::extract(&mut recovered_pk).bytes == pk.bytes, - 2, + 2 ); let wrong_msg: vector = hash::sha2_256(b"test initia"); @@ -221,7 +273,7 @@ module minitia_std::secp256k1 { assert!(std::option::is_some(&recovered_pk), 3); assert!( std::option::extract(&mut recovered_pk).bytes != pk.bytes, - 4, + 4 ); } } diff --git a/minitia_stdlib/sources/debug.move b/minitia_stdlib/sources/debug.move index 8731c8b..3dcda84 100644 --- a/minitia_stdlib/sources/debug.move +++ b/minitia_stdlib/sources/debug.move @@ -38,7 +38,7 @@ module minitia_std::debug { #[test_only] struct GenericStruct has drop { - val: u64, + val: u64 } #[test_only] @@ -54,7 +54,7 @@ module minitia_std::debug { number: u8, bytes: vector, name: String, - vec: vector, + vec: vector } #[test_only] @@ -70,7 +70,7 @@ module minitia_std::debug { fun assert_string_equal(x: vector, expected: vector) { assert!( std::string::bytes(&format(&std::string::utf8(x))) == &expected, - 1, + 1 ); } @@ -88,19 +88,19 @@ module minitia_std::debug { let foo = Foo {}; assert_equal( &foo, - b"0x1::debug::Foo {\n dummy_field: false\n}", + b"0x1::debug::Foo {\n dummy_field: false\n}" ); let bar = Bar { x: 404, y: Foo {}, z: true }; assert_equal( &bar, - b"0x1::debug::Bar {\n x: 404,\n y: 0x1::debug::Foo {\n dummy_field: false\n },\n z: true\n}", + b"0x1::debug::Bar {\n x: 404,\n y: 0x1::debug::Foo {\n dummy_field: false\n },\n z: true\n}" ); let box = Box { x: Foo {} }; assert_equal( &box, - b"0x1::debug::Box<0x1::debug::Foo> {\n x: 0x1::debug::Foo {\n dummy_field: false\n }\n}", + b"0x1::debug::Box<0x1::debug::Foo> {\n x: 0x1::debug::Foo {\n dummy_field: false\n }\n}" ); } @@ -110,7 +110,7 @@ module minitia_std::debug { assert_equal( &str_bytes, - b"0x48656c6c6f2c2073616e65204d6f766520646562756767696e6721", + b"0x48656c6c6f2c2073616e65204d6f766520646562756767696e6721" ); let str = std::string::utf8(str_bytes); @@ -142,15 +142,14 @@ module minitia_std::debug { let u128 = 340282366920938463463374607431768211455u128; assert_equal( &u128, - b"340282366920938463463374607431768211455", + b"340282366920938463463374607431768211455" ); let u256 = - - 115792089237316195423570985008687907853269984665640564039457584007913129639935u256; + 115792089237316195423570985008687907853269984665640564039457584007913129639935u256; assert_equal( &u256, - b"115792089237316195423570985008687907853269984665640564039457584007913129639935", + b"115792089237316195423570985008687907853269984665640564039457584007913129639935" ); let bool = false; @@ -174,19 +173,23 @@ module minitia_std::debug { let obj = TestInner { val: 100, vec: vector[200u128, 400u128], - msgs: vector[MSG_1, MSG_2], + msgs: vector[MSG_1, MSG_2] }; assert_equal( &obj, - b"0x1::debug::TestInner {\n val: 100,\n vec: [ 200, 400 ],\n msgs: [\n 0x616263646566,\n 0x313233343536\n ]\n}", + b"0x1::debug::TestInner {\n val: 100,\n vec: [ 200, 400 ],\n msgs: [\n 0x616263646566,\n 0x313233343536\n ]\n}" ); - let obj = TestInner { val: 10, vec: vector[], msgs: vector[], }; + let obj = TestInner { + val: 10, + vec: vector[], + msgs: vector[] + }; assert_equal( &obj, - b"0x1::debug::TestInner {\n val: 10,\n vec: [],\n msgs: []\n}", + b"0x1::debug::TestInner {\n val: 10,\n vec: [],\n msgs: []\n}" ); } @@ -219,19 +222,24 @@ module minitia_std::debug { let v_signer = vector[s1, s2]; assert_equal( &v_signer, - b"[ signer(@0x123), signer(@0x456) ]", + b"[ signer(@0x123), signer(@0x456) ]" ); let v = vector[ TestInner { val: 4u128, vec: vector[127u128, 128u128], - msgs: vector[x"00ff", x"abcd"], + msgs: vector[x"00ff", x"abcd"] }, - TestInner { val: 8u128, vec: vector[128u128, 129u128], msgs: vector[x"0000"], }]; + TestInner { + val: 8u128, + vec: vector[128u128, 129u128], + msgs: vector[x"0000"] + } + ]; assert_equal( &v, - b"[\n 0x1::debug::TestInner {\n val: 4,\n vec: [ 127, 128 ],\n msgs: [\n 0x00ff,\n 0xabcd\n ]\n },\n 0x1::debug::TestInner {\n val: 8,\n vec: [ 128, 129 ],\n msgs: [\n 0x0000\n ]\n }\n]", + b"[\n 0x1::debug::TestInner {\n val: 4,\n vec: [ 127, 128 ],\n msgs: [\n 0x00ff,\n 0xabcd\n ]\n },\n 0x1::debug::TestInner {\n val: 8,\n vec: [ 128, 129 ],\n msgs: [\n 0x0000\n ]\n }\n]" ); } @@ -252,43 +260,62 @@ module minitia_std::debug { let v_u128 = vector[vector[128u128, 129u128], vector[130u128, 131u128]]; assert_equal( &v_u128, - b"[\n [ 128, 129 ],\n [ 130, 131 ]\n]", + b"[\n [ 128, 129 ],\n [ 130, 131 ]\n]" ); let v_u256 = vector[vector[256u256, 257u256], vector[258u256, 259u256]]; assert_equal( &v_u256, - b"[\n [ 256, 257 ],\n [ 258, 259 ]\n]", + b"[\n [ 256, 257 ],\n [ 258, 259 ]\n]" ); let v_bool = vector[vector[true, false], vector[false, true]]; assert_equal( &v_bool, - b"[\n [ true, false ],\n [ false, true ]\n]", + b"[\n [ true, false ],\n [ false, true ]\n]" ); let v_addr = vector[vector[@0x1234, @0x5678], vector[@0xabcdef, @0x9999]]; assert_equal( &v_addr, - b"[\n [ @0x1234, @0x5678 ],\n [ @0xabcdef, @0x9999 ]\n]", + b"[\n [ @0x1234, @0x5678 ],\n [ @0xabcdef, @0x9999 ]\n]" ); let v_signer = vector[vector[s1], vector[s2]]; assert_equal( &v_signer, - b"[\n [ signer(@0x123) ],\n [ signer(@0x456) ]\n]", + b"[\n [ signer(@0x123) ],\n [ signer(@0x456) ]\n]" ); let v = vector[ vector[ - TestInner { val: 4u128, vec: vector[127u128, 128u128], msgs: vector[] }, - TestInner { val: 8u128, vec: vector[128u128, 129u128], msgs: vector[] }], + TestInner { + val: 4u128, + vec: vector[127u128, 128u128], + msgs: vector[] + }, + TestInner { + val: 8u128, + vec: vector[128u128, 129u128], + msgs: vector[] + } + ], vector[ - TestInner { val: 4u128, vec: vector[127u128, 128u128], msgs: vector[] }, - TestInner { val: 8u128, vec: vector[128u128, 129u128], msgs: vector[] }]]; + TestInner { + val: 4u128, + vec: vector[127u128, 128u128], + msgs: vector[] + }, + TestInner { + val: 8u128, + vec: vector[128u128, 129u128], + msgs: vector[] + } + ] + ]; assert_equal( &v, - b"[\n [\n 0x1::debug::TestInner {\n val: 4,\n vec: [ 127, 128 ],\n msgs: []\n },\n 0x1::debug::TestInner {\n val: 8,\n vec: [ 128, 129 ],\n msgs: []\n }\n ],\n [\n 0x1::debug::TestInner {\n val: 4,\n vec: [ 127, 128 ],\n msgs: []\n },\n 0x1::debug::TestInner {\n val: 8,\n vec: [ 128, 129 ],\n msgs: []\n }\n ]\n]", + b"[\n [\n 0x1::debug::TestInner {\n val: 4,\n vec: [ 127, 128 ],\n msgs: []\n },\n 0x1::debug::TestInner {\n val: 8,\n vec: [ 128, 129 ],\n msgs: []\n }\n ],\n [\n 0x1::debug::TestInner {\n val: 4,\n vec: [ 127, 128 ],\n msgs: []\n },\n 0x1::debug::TestInner {\n val: 8,\n vec: [ 128, 129 ],\n msgs: []\n }\n ]\n]" ); } @@ -300,23 +327,32 @@ module minitia_std::debug { bytes: x"c0ffee", name: std::string::utf8(b"He\"llo"), vec: vector[ - TestInner { val: 1, vec: vector[130u128, 131u128], msgs: vector[] }, - TestInner { val: 2, vec: vector[132u128, 133u128], msgs: vector[] }], + TestInner { + val: 1, + vec: vector[130u128, 131u128], + msgs: vector[] + }, + TestInner { + val: 2, + vec: vector[132u128, 133u128], + msgs: vector[] + } + ] }; assert_equal( &obj, - b"0x1::debug::TestStruct {\n addr: @0x1,\n number: 255,\n bytes: 0xc0ffee,\n name: \"He\\\"llo\",\n vec: [\n 0x1::debug::TestInner {\n val: 1,\n vec: [ 130, 131 ],\n msgs: []\n },\n 0x1::debug::TestInner {\n val: 2,\n vec: [ 132, 133 ],\n msgs: []\n }\n ]\n}", + b"0x1::debug::TestStruct {\n addr: @0x1,\n number: 255,\n bytes: 0xc0ffee,\n name: \"He\\\"llo\",\n vec: [\n 0x1::debug::TestInner {\n val: 1,\n vec: [ 130, 131 ],\n msgs: []\n },\n 0x1::debug::TestInner {\n val: 2,\n vec: [ 132, 133 ],\n msgs: []\n }\n ]\n}" ); } #[test] fun test_print_generic_struct() { - let obj = GenericStruct { val: 60u64, }; + let obj = GenericStruct { val: 60u64 }; assert_equal( &obj, - b"0x1::debug::GenericStruct<0x1::debug::Foo> {\n val: 60\n}", + b"0x1::debug::GenericStruct<0x1::debug::Foo> {\n val: 60\n}" ); } } diff --git a/minitia_stdlib/sources/decimal128.move b/minitia_stdlib/sources/decimal128.move deleted file mode 100644 index 415a569..0000000 --- a/minitia_stdlib/sources/decimal128.move +++ /dev/null @@ -1,669 +0,0 @@ -module minitia_std::decimal128 { - use std::string::{Self, String}; - use std::vector; - use std::error; - - const EDIV_WITH_ZERO: u64 = 0; - const EFAILED_TO_DESERIALIZE: u64 = 1; - const EOUT_OF_RANGE: u64 = 2; - - const DECIMAL_FRACTIONAL: u128 = 1000000000000000000; - const FRACTIONAL_LENGTH: u64 = 18; - - // const MAX_U128: u128 = 340282366920938463463374607431768211455; - const MAX_INTEGER_PART: u128 = 340282366920938463463; - - /// A fixed-point decimal value with 18 fractional digits, i.e. Decimal128{ val: 1_000_000_000_000_000_000 } == 1.0 - struct Decimal128 has copy, drop, store { - val: u128 - } - - public fun new(val: u128): Decimal128 { - Decimal128 { val } - } - - public fun new_u64(val: u64): Decimal128 { - Decimal128 { val: (val as u128) } - } - - public fun one(): Decimal128 { - Decimal128 { val: DECIMAL_FRACTIONAL } - } - - public fun zero(): Decimal128 { - Decimal128 { val: 0 } - } - - public fun from_ratio_u64(numerator: u64, denominator: u64): Decimal128 { - assert!(denominator != 0, EDIV_WITH_ZERO); - - new( - (numerator as u128) * DECIMAL_FRACTIONAL / (denominator as u128), - ) - } - - public fun from_ratio(numerator: u128, denominator: u128): Decimal128 { - assert!(denominator != 0, EDIV_WITH_ZERO); - - new(numerator * DECIMAL_FRACTIONAL / denominator) - } - - public fun add(left: &Decimal128, right: &Decimal128): Decimal128 { - new(left.val + right.val) - } - - public fun sub(left: &Decimal128, right: &Decimal128): Decimal128 { - new(left.val - right.val) - } - - public fun mul_u64(decimal: &Decimal128, val: u64): u64 { - ((decimal.val as u256) * (val as u256) / (DECIMAL_FRACTIONAL as u256) as u64) - } - - public fun mul_u64_with_round_up(decimal: &Decimal128, val: u64): u64 { - let val = (decimal.val as u256) * (val as u256); - let val = val + (DECIMAL_FRACTIONAL as u256) / 2; - (val / (DECIMAL_FRACTIONAL as u256) as u64) - } - - public fun mul_u64_with_ceil(decimal: &Decimal128, val: u64): u64 { - let val = (decimal.val as u256) * (val as u256); - let val = val + (DECIMAL_FRACTIONAL as u256) - 1; - (val / (DECIMAL_FRACTIONAL as u256) as u64) - } - - public fun mul_u128(decimal: &Decimal128, val: u128): u128 { - ((decimal.val as u256) * (val as u256) / (DECIMAL_FRACTIONAL as u256) as u128) - } - - public fun mul_u128_with_round_up(decimal: &Decimal128, val: u128): u128 { - let val = (decimal.val as u256) * (val as u256); - let val = val + (DECIMAL_FRACTIONAL as u256) / 2; - (val / (DECIMAL_FRACTIONAL as u256) as u128) - } - - public fun mul_u128_with_ceil(decimal: &Decimal128, val: u128): u128 { - let val = (decimal.val as u256) * (val as u256); - let val = val + (DECIMAL_FRACTIONAL as u256) - 1; - (val / (DECIMAL_FRACTIONAL as u256) as u128) - } - - public fun mul(a: &Decimal128, b: &Decimal128): Decimal128 { - new( - ((a.val as u256) * (b.val as u256) / (DECIMAL_FRACTIONAL as u256) as u128), - ) - } - - public fun div_u64(decimal: &Decimal128, val: u64): Decimal128 { - new(decimal.val / (val as u128)) - } - - public fun div(decimal: &Decimal128, val: u128): Decimal128 { - new(decimal.val / val) - } - - public fun val(decimal: &Decimal128): u128 { - decimal.val - } - - public fun round_up_u64(decimal: &Decimal128): u64 { - let val = decimal.val + DECIMAL_FRACTIONAL / 2; - (val / DECIMAL_FRACTIONAL as u64) - } - - public fun round_up_u128(decimal: &Decimal128): u128 { - let val = decimal.val + DECIMAL_FRACTIONAL / 2; - (val / DECIMAL_FRACTIONAL as u128) - } - - public fun ceil_u64(decimal: &Decimal128): u64 { - let val = decimal.val + DECIMAL_FRACTIONAL - 1; - (val / DECIMAL_FRACTIONAL as u64) - } - - public fun ceil_u128(decimal: &Decimal128): u128 { - let val = decimal.val + DECIMAL_FRACTIONAL - 1; - val / DECIMAL_FRACTIONAL - } - - public fun is_same(left: &Decimal128, right: &Decimal128): bool { - left.val == right.val - } - - public fun from_string(num: &String): Decimal128 { - let vec = string::bytes(num); - let len = vector::length(vec); - - let cursor = 0; - let dot_index = 0; - - let int_part = 0; - let frac_part = 0; - - while (cursor < len) { - let s = *vector::borrow(vec, cursor); - cursor = cursor + 1; - - // find `.` position - if (s == 46) break; - - int_part = int_part * 10; - assert!( - s >= 48 && s <= 57, - error::invalid_argument(EFAILED_TO_DESERIALIZE), - ); - - let n = (s - 48 as u128); - int_part = int_part + n; - assert!( - int_part < MAX_INTEGER_PART, - error::invalid_argument(EOUT_OF_RANGE), - ); - dot_index = dot_index + 1; - }; - - while (cursor < len) { - let s = *vector::borrow(vec, cursor); - cursor = cursor + 1; - - frac_part = frac_part * 10; - assert!( - s >= 48 && s <= 57, - error::invalid_argument(EFAILED_TO_DESERIALIZE), - ); - - let n = (s - 48 as u128); - frac_part = frac_part + n; - assert!( - frac_part < MAX_INTEGER_PART, - error::invalid_argument(EOUT_OF_RANGE), - ); - }; - - // ignore fractional part longer than `FRACTIONAL_LENGTH` - let frac_part_val = - if (dot_index == len) { 0 } - else { - let fractional_length = len - dot_index - 1; - if (fractional_length > FRACTIONAL_LENGTH) { - frac_part / pow( - 10, - fractional_length - FRACTIONAL_LENGTH, - ) - } else { - frac_part * pow( - 10, - FRACTIONAL_LENGTH - fractional_length, - ) - } - }; - - new(int_part * DECIMAL_FRACTIONAL + frac_part_val) - } - - fun pow(num: u128, pow_amount: u64): u128 { - let index = 0; - let val = 1; - while (index < pow_amount) { - val = val * num; - index = index + 1; - }; - - val - } - - #[test] - fun test() { - assert!( - from_string(&string::utf8(b"1234.5678")) == new(1234567800000000000000), - 0, - ); - assert!( - from_string(&string::utf8(b"340282366920938463462")) - == new(340282366920938463462 * DECIMAL_FRACTIONAL), - 0, - ); - assert!( - from_string(&string::utf8(b"340282366920938463462.0")) - == new(340282366920938463462 * DECIMAL_FRACTIONAL), - 0, - ); - - let max_a = from_ratio(10000, 1); - let result = mul(&max_a, &from_ratio(34028236692093, 1)); - assert!( - result == from_ratio(340282366920930000, 1), - 0, - ); - } - - #[test] - fun test_round_up() { - // u64 - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u128 - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u64 - assert!( - round_up_u64(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.1"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.2"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.3"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.4"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - - // u128 - assert!( - round_up_u128(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.1"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.2"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.3"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.4"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - } - - #[test] - fun test_ceil() { - // u64 - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u128 - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u64 - assert!( - ceil_u64(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.1"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.2"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.3"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.4"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - - // u128 - assert!( - ceil_u128(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.1"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.2"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.3"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.4"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - } - - #[test] - #[expected_failure(abort_code = 0x10001, location = Self)] - fun multible_dots() { - from_string(&string::utf8(b".1.1.")); - } - - #[test] - #[expected_failure(abort_code = 0x10002, location = Self)] - fun failed_out_of_range() { - _ = from_string(&string::utf8(b"340282366920938463463.0")); - } -} diff --git a/minitia_stdlib/sources/decimal256.move b/minitia_stdlib/sources/decimal256.move deleted file mode 100644 index 7083812..0000000 --- a/minitia_stdlib/sources/decimal256.move +++ /dev/null @@ -1,925 +0,0 @@ -module minitia_std::decimal256 { - use std::string::{Self, String}; - use std::vector; - use std::error; - - const EDIV_WITH_ZERO: u64 = 0; - const EFAILED_TO_DESERIALIZE: u64 = 1; - const EOUT_OF_RANGE: u64 = 2; - - const DECIMAL_FRACTIONAL: u256 = 1000000000000000000; - const FRACTIONAL_LENGTH: u64 = 18; - - // const MAX_U256: u256 = 115792089237316195423570985008687907853269984665640564039457584007913129639935; - const MAX_INTEGER_PART: u256 = - 115792089237316195423570985008687907853269984665640564039457; - - /// A fixed-point decimal value with 18 fractional digits, i.e. Decimal256{ val: 1_000_000_000_000_000_000 } == 1.0 - struct Decimal256 has copy, drop, store { - val: u256 - } - - public fun new(val: u256): Decimal256 { - Decimal256 { val } - } - - public fun new_u64(val: u64): Decimal256 { - Decimal256 { val: (val as u256) } - } - - public fun new_u128(val: u128): Decimal256 { - Decimal256 { val: (val as u256) } - } - - public fun one(): Decimal256 { - Decimal256 { val: DECIMAL_FRACTIONAL } - } - - public fun zero(): Decimal256 { - Decimal256 { val: 0 } - } - - public fun from_ratio_u64(numerator: u64, denominator: u64): Decimal256 { - assert!(denominator != 0, EDIV_WITH_ZERO); - - new( - (numerator as u256) * DECIMAL_FRACTIONAL / (denominator as u256), - ) - } - - public fun from_ratio_u128(numerator: u128, denominator: u128): Decimal256 { - assert!(denominator != 0, EDIV_WITH_ZERO); - - new( - (numerator as u256) * DECIMAL_FRACTIONAL / (denominator as u256), - ) - } - - public fun from_ratio(numerator: u256, denominator: u256): Decimal256 { - assert!(denominator != 0, EDIV_WITH_ZERO); - - new(numerator * DECIMAL_FRACTIONAL / denominator) - } - - public fun add(left: &Decimal256, right: &Decimal256): Decimal256 { - new(left.val + right.val) - } - - public fun sub(left: &Decimal256, right: &Decimal256): Decimal256 { - new(left.val - right.val) - } - - public fun mul_u64(decimal: &Decimal256, val: u64): u64 { - (decimal.val * (val as u256) / DECIMAL_FRACTIONAL as u64) - } - - public fun mul_u64_with_round_up(decimal: &Decimal256, val: u64): u64 { - let val = decimal.val * (val as u256); - let val = val + DECIMAL_FRACTIONAL / 2; - (val / DECIMAL_FRACTIONAL as u64) - } - - public fun mul_u64_with_ceil(decimal: &Decimal256, val: u64): u64 { - let val = decimal.val * (val as u256); - let val = val + DECIMAL_FRACTIONAL - 1; - (val / DECIMAL_FRACTIONAL as u64) - } - - public fun mul_u128(decimal: &Decimal256, val: u128): u128 { - (decimal.val * (val as u256) / DECIMAL_FRACTIONAL as u128) - } - - public fun mul_u128_with_round_up(decimal: &Decimal256, val: u128): u128 { - let val = decimal.val * (val as u256); - let val = val + DECIMAL_FRACTIONAL / 2; - (val / DECIMAL_FRACTIONAL as u128) - } - - public fun mul_u128_with_ceil(decimal: &Decimal256, val: u128): u128 { - let val = decimal.val * (val as u256); - let val = val + DECIMAL_FRACTIONAL - 1; - (val / DECIMAL_FRACTIONAL as u128) - } - - public fun mul_u256(decimal: &Decimal256, val: u256): u256 { - decimal.val * val / DECIMAL_FRACTIONAL - } - - public fun mul_u256_with_round_up(decimal: &Decimal256, val: u256): u256 { - let val = decimal.val * val; - let val = val + DECIMAL_FRACTIONAL / 2; - val / DECIMAL_FRACTIONAL - } - - public fun mul_u256_with_ceil(decimal: &Decimal256, val: u256): u256 { - let val = decimal.val * val; - let val = val + DECIMAL_FRACTIONAL - 1; - val / DECIMAL_FRACTIONAL - } - - public fun mul(a: &Decimal256, b: &Decimal256): Decimal256 { - new(a.val * b.val / DECIMAL_FRACTIONAL) - } - - public fun div_u64(decimal: &Decimal256, val: u64): Decimal256 { - new(decimal.val / (val as u256)) - } - - public fun div_u128(decimal: &Decimal256, val: u128): Decimal256 { - new(decimal.val / (val as u256)) - } - - public fun div(decimal: &Decimal256, val: u256): Decimal256 { - new(decimal.val / val) - } - - public fun val(decimal: &Decimal256): u256 { - decimal.val - } - - public fun round_up_u64(decimal: &Decimal256): u64 { - let val = decimal.val + DECIMAL_FRACTIONAL / 2; - (val / DECIMAL_FRACTIONAL as u64) - } - - public fun round_up_u128(decimal: &Decimal256): u128 { - let val = decimal.val + DECIMAL_FRACTIONAL / 2; - (val / DECIMAL_FRACTIONAL as u128) - } - - public fun round_up_u256(decimal: &Decimal256): u256 { - let val = decimal.val + DECIMAL_FRACTIONAL / 2; - (val / DECIMAL_FRACTIONAL as u256) - } - - public fun ceil_u64(decimal: &Decimal256): u64 { - let val = decimal.val + DECIMAL_FRACTIONAL - 1; - (val / DECIMAL_FRACTIONAL as u64) - } - - public fun ceil_u128(decimal: &Decimal256): u128 { - let val = decimal.val + DECIMAL_FRACTIONAL - 1; - (val / DECIMAL_FRACTIONAL as u128) - } - - public fun ceil_u256(decimal: &Decimal256): u256 { - let val = decimal.val + DECIMAL_FRACTIONAL - 1; - val / DECIMAL_FRACTIONAL - } - - public fun is_same(left: &Decimal256, right: &Decimal256): bool { - left.val == right.val - } - - public fun from_string(num: &String): Decimal256 { - let vec = string::bytes(num); - let len = vector::length(vec); - - let cursor = 0; - let dot_index = 0; - - let int_part = 0; - let frac_part = 0; - - while (cursor < len) { - let s = *vector::borrow(vec, cursor); - cursor = cursor + 1; - - // find `.` position - if (s == 46) break; - - int_part = int_part * 10; - assert!( - s >= 48 && s <= 57, - error::invalid_argument(EFAILED_TO_DESERIALIZE), - ); - - let n = (s - 48 as u256); - int_part = int_part + n; - assert!( - int_part < MAX_INTEGER_PART, - error::invalid_argument(EOUT_OF_RANGE), - ); - dot_index = dot_index + 1; - }; - - while (cursor < len) { - let s = *vector::borrow(vec, cursor); - cursor = cursor + 1; - - frac_part = frac_part * 10; - assert!( - s >= 48 && s <= 57, - error::invalid_argument(EFAILED_TO_DESERIALIZE), - ); - - let n = (s - 48 as u256); - frac_part = frac_part + n; - assert!( - frac_part < MAX_INTEGER_PART, - error::invalid_argument(EOUT_OF_RANGE), - ); - }; - - // ignore fractional part longer than `FRACTIONAL_LENGTH` - let frac_part_val = - if (dot_index == len) { 0 } - else { - let fractional_length = len - dot_index - 1; - if (fractional_length > FRACTIONAL_LENGTH) { - frac_part / pow( - 10, - fractional_length - FRACTIONAL_LENGTH, - ) - } else { - frac_part * pow( - 10, - FRACTIONAL_LENGTH - fractional_length, - ) - } - }; - - new(int_part * DECIMAL_FRACTIONAL + frac_part_val) - } - - fun pow(num: u256, pow_amount: u64): u256 { - let index = 0; - let val = 1; - while (index < pow_amount) { - val = val * num; - index = index + 1; - }; - - val - } - - #[test] - fun test() { - assert!( - from_string(&string::utf8(b"1234.5678")) == new(1234567800000000000000), - 0, - ); - assert!( - from_string( - &string::utf8( - b"115792089237316195423570985008687907853269984665640564039456" - ), - ) == new( - 115792089237316195423570985008687907853269984665640564039456 - * DECIMAL_FRACTIONAL, - ), - 0, - ); - assert!( - from_string( - &string::utf8( - b"115792089237316195423570985008687907853269984665640564039456.0" - ), - ) == new( - 115792089237316195423570985008687907853269984665640564039456 - * DECIMAL_FRACTIONAL, - ), - 0, - ); - } - - #[test] - fun test_round_up() { - // u64 - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_round_up( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u128 - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_round_up( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u256 - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u64 - assert!( - round_up_u64(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.1"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.2"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.3"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.4"))) == 200, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - round_up_u64(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - - // u128 - assert!( - round_up_u128(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.1"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.2"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.3"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.4"))) == 200, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - round_up_u128(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - - // u256 - assert!( - round_up_u256(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.1"))) == 200, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.2"))) == 200, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.3"))) == 200, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.4"))) == 200, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - round_up_u256(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - } - - #[test] - fun test_ceil() { - // u64 - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u64_with_ceil( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u128 - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 202, - 0, - ); - assert!( - mul_u128_with_ceil( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u256 - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.0")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.1")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.2")), - 2, - ) == 200, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.3")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.4")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.5")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.6")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.7")), - 2, - ) == 201, - 0, - ); - assert!( - mul_u256_with_round_up( - &from_string(&string::utf8(b"100.8")), - 2, - ) == 202, - 0, - ); - - // u64 - assert!( - ceil_u64(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.1"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.2"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.3"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.4"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - ceil_u64(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - - // u128 - assert!( - ceil_u128(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.1"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.2"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.3"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.4"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - ceil_u128(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - - // u256 - assert!( - ceil_u256(&from_string(&string::utf8(b"200.0"))) == 200, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.1"))) == 201, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.2"))) == 201, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.3"))) == 201, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.4"))) == 201, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.5"))) == 201, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.6"))) == 201, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.7"))) == 201, - 0, - ); - assert!( - ceil_u256(&from_string(&string::utf8(b"200.8"))) == 201, - 0, - ); - } - - #[test] - #[expected_failure(abort_code = 0x10001, location = Self)] - fun multible_dots() { - from_string(&string::utf8(b".1.1.")); - } - - #[test] - #[expected_failure(abort_code = 0x10002, location = Self)] - fun failed_out_of_range() { - _ = from_string( - &string::utf8( - b"115792089237316195423570985008687907853269984665640564039457.0" - ), - ); - } -} diff --git a/minitia_stdlib/sources/dex.move b/minitia_stdlib/sources/dex.move index ec8bbef..1e90d09 100644 --- a/minitia_stdlib/sources/dex.move +++ b/minitia_stdlib/sources/dex.move @@ -9,39 +9,40 @@ module minitia_std::dex { use minitia_std::block::get_block_info; use minitia_std::fungible_asset::{Self, Metadata, FungibleAsset, FungibleStore}; use minitia_std::primary_fungible_store; - use minitia_std::decimal128::{Self, Decimal128}; use minitia_std::string::{Self, String}; use minitia_std::table::{Self, Table}; use minitia_std::coin; + use minitia_std::bigdecimal::{Self, BigDecimal}; + use minitia_std::biguint; /// Pool configuration struct Config has key { extend_ref: ExtendRef, weights: Weights, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal } struct Pool has key { coin_a_store: Object, - coin_b_store: Object, + coin_b_store: Object } struct Weights has copy, drop, store { weights_before: Weight, - weights_after: Weight, + weights_after: Weight } struct Weight has copy, drop, store { - coin_a_weight: Decimal128, - coin_b_weight: Decimal128, - timestamp: u64, + coin_a_weight: BigDecimal, + coin_b_weight: BigDecimal, + timestamp: u64 } /// Key for pair struct PairKey has copy, drop { coin_a: address, coin_b: address, - liquidity_token: address, + liquidity_token: address } struct PairResponse has copy, drop, store { @@ -49,7 +50,7 @@ module minitia_std::dex { coin_b: address, liquidity_token: address, weights: Weights, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal } struct PairByDenomResponse has copy, drop, store { @@ -57,14 +58,14 @@ module minitia_std::dex { coin_b: String, liquidity_token: String, weights: Weights, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal } /// Coin capabilities struct CoinCapabilities has key { burn_cap: coin::BurnCapability, freeze_cap: coin::FreezeCapability, - mint_cap: coin::MintCapability, + mint_cap: coin::MintCapability } #[event] @@ -75,7 +76,7 @@ module minitia_std::dex { liquidity_token: address, coin_a_amount: u64, coin_b_amount: u64, - liquidity: u64, + liquidity: u64 } #[event] @@ -86,7 +87,7 @@ module minitia_std::dex { liquidity_token: address, coin_a_amount: u64, coin_b_amount: u64, - liquidity: u64, + liquidity: u64 } #[event] @@ -97,7 +98,7 @@ module minitia_std::dex { liquidity_token: address, offer_amount: u64, return_amount: u64, - fee_amount: u64, + fee_amount: u64 } #[event] @@ -108,33 +109,33 @@ module minitia_std::dex { provide_coin: address, provide_amount: u64, fee_amount: u64, - liquidity: u64, + liquidity: u64 } struct PoolInfoResponse has drop { coin_a_amount: u64, coin_b_amount: u64, - total_share: u128, + total_share: u128 } struct ConfigResponse has drop { weights: Weights, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal } struct CurrentWeightResponse has drop { - coin_a_weight: Decimal128, - coin_b_weight: Decimal128, + coin_a_weight: BigDecimal, + coin_b_weight: BigDecimal } struct PairMetadataResponse has drop { coin_a_metadata: Object, - coin_b_metadata: Object, + coin_b_metadata: Object } struct PairDenomResponse has drop { coin_a_denom: String, - coin_b_denom: String, + coin_b_denom: String } #[event] @@ -143,7 +144,7 @@ module minitia_std::dex { coin_b: address, liquidity_token: address, weights: Weights, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal } #[event] @@ -151,13 +152,13 @@ module minitia_std::dex { coin_a: address, coin_b: address, liquidity_token: address, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal } /// Module store for storing pair infos struct ModuleStore has key { pairs: Table, - pair_count: u64, + pair_count: u64 } // Errors @@ -210,31 +211,32 @@ module minitia_std::dex { /// Zero amount in the swap simulation is not allowed const EZERO_AMOUNT_IN: u64 = 20; + /// Weights sum must be 1.0 + const EINVALID_WEIGHTS: u64 = 21; + // Constants const MAX_LIMIT: u8 = 30; // TODO - find the resonable percision /// Result Precision of `pow` and `ln` function - const PRECISION: u128 = 100000; - - const MAX_FEE_RATE: u128 = 50_000_000_000_000_000; // 5% + const PRECISION: u64 = 100000; #[view] - public fun get_pair_metadata(pair: Object,): PairMetadataResponse acquires Pool { + public fun get_pair_metadata(pair: Object): PairMetadataResponse acquires Pool { let pool = borrow_global_mut(object::object_address(&pair)); let coin_a_metadata = fungible_asset::store_metadata(pool.coin_a_store); let coin_b_metadata = fungible_asset::store_metadata(pool.coin_b_store); - PairMetadataResponse { coin_a_metadata, coin_b_metadata, } + PairMetadataResponse { coin_a_metadata, coin_b_metadata } } #[view] - public fun get_pair_denom(pair: Object,): PairDenomResponse acquires Pool { + public fun get_pair_denom(pair: Object): PairDenomResponse acquires Pool { let pair_metadata = get_pair_metadata(pair); PairDenomResponse { coin_a_denom: coin::metadata_to_denom(pair_metadata.coin_a_metadata), - coin_b_denom: coin::metadata_to_denom(pair_metadata.coin_b_metadata), + coin_b_denom: coin::metadata_to_denom(pair_metadata.coin_b_metadata) } } @@ -242,8 +244,8 @@ module minitia_std::dex { /// Calculate spot price /// https://balancer.fi/whitepaper.pdf (2) public fun get_spot_price( - pair: Object, base_coin: Object, - ): Decimal128 acquires Config, Pool { + pair: Object, base_coin: Object + ): BigDecimal acquires Config, Pool { let (coin_a_pool, coin_b_pool, coin_a_weight, coin_b_weight, _) = pool_info(pair, false); @@ -251,7 +253,7 @@ module minitia_std::dex { let base_addr = object::object_address(&base_coin); assert!( base_addr == pair_key.coin_a || base_addr == pair_key.coin_b, - error::invalid_argument(ECOIN_TYPE), + error::invalid_argument(ECOIN_TYPE) ); let is_base_a = base_addr == pair_key.coin_a; let (base_pool, quote_pool, base_weight, quote_weight) = @@ -261,16 +263,16 @@ module minitia_std::dex { (coin_b_pool, coin_a_pool, coin_b_weight, coin_a_weight) }; - decimal128::from_ratio_u64( - decimal128::mul_u64(&base_weight, quote_pool), - decimal128::mul_u64("e_weight, base_pool), + bigdecimal::div( + bigdecimal::mul_by_u64(base_weight, quote_pool), + bigdecimal::mul_by_u64(quote_weight, base_pool) ) } #[view] public fun get_spot_price_by_denom( - pair_denom: String, base_coin: String, - ): Decimal128 acquires Config, Pool { + pair_denom: String, base_coin: String + ): BigDecimal acquires Config, Pool { let pair_metadata = coin::denom_to_metadata(pair_denom); let base_metadata = coin::denom_to_metadata(base_coin); get_spot_price(object::convert(pair_metadata), base_metadata) @@ -279,15 +281,13 @@ module minitia_std::dex { #[view] /// Return swap simulation result public fun get_swap_simulation( - pair: Object, - offer_metadata: Object, - offer_amount: u64, + pair: Object, offer_metadata: Object, offer_amount: u64 ): u64 acquires Config, Pool { let pair_key = generate_pair_key(pair); let offer_address = object::object_address(&offer_metadata); assert!( offer_address == pair_key.coin_a || offer_address == pair_key.coin_b, - error::invalid_argument(ECOIN_TYPE), + error::invalid_argument(ECOIN_TYPE) ); let is_offer_a = offer_address == pair_key.coin_a; let (pool_a, pool_b, weight_a, weight_b, swap_fee_rate) = pool_info(pair, true); @@ -304,7 +304,7 @@ module minitia_std::dex { offer_weight, return_weight, offer_amount, - swap_fee_rate, + swap_fee_rate ); return_amount @@ -312,31 +312,27 @@ module minitia_std::dex { #[view] public fun get_swap_simulation_by_denom( - pair_denom: String, - offer_denom: String, - offer_amount: u64, + pair_denom: String, offer_denom: String, offer_amount: u64 ): u64 acquires Config, Pool { let pair_metadata = coin::denom_to_metadata(pair_denom); let offer_metadata = coin::denom_to_metadata(offer_denom); get_swap_simulation( object::convert(pair_metadata), offer_metadata, - offer_amount, + offer_amount ) } #[view] /// Return swap simulation result public fun get_swap_simulation_given_out( - pair: Object, - offer_metadata: Object, - return_amount: u64, + pair: Object, offer_metadata: Object, return_amount: u64 ): u64 acquires Config, Pool { let pair_key = generate_pair_key(pair); let offer_address = object::object_address(&offer_metadata); assert!( offer_address == pair_key.coin_a || offer_address == pair_key.coin_b, - error::invalid_argument(ECOIN_TYPE), + error::invalid_argument(ECOIN_TYPE) ); let is_offer_a = offer_address == pair_key.coin_a; let (pool_a, pool_b, weight_a, weight_b, swap_fee_rate) = pool_info(pair, true); @@ -353,7 +349,7 @@ module minitia_std::dex { offer_weight, return_weight, return_amount, - swap_fee_rate, + swap_fee_rate ); offer_amount @@ -361,19 +357,46 @@ module minitia_std::dex { #[view] public fun get_swap_simulation_given_out_by_denom( - pair_denom: String, - offer_denom: String, - return_amount: u64, + pair_denom: String, offer_denom: String, return_amount: u64 ): u64 acquires Config, Pool { let pair_metadata = coin::denom_to_metadata(pair_denom); let offer_metadata = coin::denom_to_metadata(offer_denom); get_swap_simulation_given_out( object::convert(pair_metadata), offer_metadata, - return_amount, + return_amount ) } + #[view] + public fun get_provide_simulation( + pair: Object, + coin_a_amount_in: u64, + coin_b_amount_in: u64 + ): u64 acquires Pool { + let pool_addr = object::object_address(&pair); + let pool = borrow_global(pool_addr); + + calculate_provide_liquidity_return_amount( + pool, pair, coin_a_amount_in, coin_b_amount_in + ) + } + + #[view] + public fun get_single_asset_provide_simulation( + pair: Object, offer_asset_metadata: Object, amount_in: u64 + ): u64 acquires Config, Pool { + let pair_addr = object::object_address(&pair); + let pool = borrow_global(pair_addr); + + let (liquidity_amount, _, _) = + calculate_single_asset_provide_liquidity_return_amount( + pool, pair, offer_asset_metadata, amount_in + ); + + liquidity_amount + } + #[view] /// get pool info public fun get_pool_info(pair: Object): PoolInfoResponse acquires Pool { @@ -382,7 +405,7 @@ module minitia_std::dex { PoolInfoResponse { coin_a_amount: fungible_asset::balance(pool.coin_a_store), coin_b_amount: fungible_asset::balance(pool.coin_b_store), - total_share: option::extract(&mut fungible_asset::supply(pair)), + total_share: option::extract(&mut fungible_asset::supply(pair)) } } @@ -399,7 +422,7 @@ module minitia_std::dex { let pair_addr = object::object_address(&pair); let config = borrow_global(pair_addr); - ConfigResponse { weights: config.weights, swap_fee_rate: config.swap_fee_rate, } + ConfigResponse { weights: config.weights, swap_fee_rate: config.swap_fee_rate } } #[view] @@ -414,11 +437,13 @@ module minitia_std::dex { let pair_addr = object::object_address(&pair); let config = borrow_global(pair_addr); let (coin_a_weight, coin_b_weight) = get_weight(&config.weights); - CurrentWeightResponse { coin_a_weight, coin_b_weight, } + CurrentWeightResponse { coin_a_weight, coin_b_weight } } #[view] - public fun get_current_weight_by_denom(pair_denom: String): CurrentWeightResponse acquires Config { + public fun get_current_weight_by_denom( + pair_denom: String + ): CurrentWeightResponse acquires Config { let pair_metadata = coin::denom_to_metadata(pair_denom); get_current_weight(object::convert(pair_metadata)) } @@ -430,17 +455,18 @@ module minitia_std::dex { coin_a_start_after: Option
, coin_b_start_after: Option
, liquidity_token_start_after: Option
, - limit: u8, + limit: u8 ): vector acquires ModuleStore { if (limit > MAX_LIMIT) { limit = MAX_LIMIT; }; assert!( - option::is_some(&coin_a_start_after) == option::is_some(&coin_b_start_after) + option::is_some(&coin_a_start_after) + == option::is_some(&coin_b_start_after) && option::is_some(&coin_b_start_after) == option::is_some(&liquidity_token_start_after), - ESTART_AFTER, + ESTART_AFTER ); let module_store = borrow_global(@minitia_std); @@ -451,12 +477,12 @@ module minitia_std::dex { PairKey { coin_a: option::extract(&mut coin_a_start_after), coin_b: option::extract(&mut coin_b_start_after), - liquidity_token: option::extract(&mut liquidity_token_start_after), - }, + liquidity_token: option::extract(&mut liquidity_token_start_after) + } ) } else { option::some( - PairKey { coin_a: @0x0, coin_b: @0x0, liquidity_token: @0x0, }, + PairKey { coin_a: @0x0, coin_b: @0x0, liquidity_token: @0x0 } ) }; @@ -465,11 +491,11 @@ module minitia_std::dex { &module_store.pairs, start_after, option::none(), - 1, + 1 ); while (vector::length(&res) < (limit as u64) - && table::prepare(pairs_iter)) { + && table::prepare(pairs_iter)) { let (key, value) = table::next(pairs_iter); if (&key != option::borrow(&start_after)) { vector::push_back(&mut res, *value) @@ -486,17 +512,18 @@ module minitia_std::dex { coin_a_start_after: Option, coin_b_start_after: Option, liquidity_token_start_after: Option, - limit: u8, + limit: u8 ): vector acquires ModuleStore { if (limit > MAX_LIMIT) { limit = MAX_LIMIT; }; assert!( - option::is_some(&coin_a_start_after) == option::is_some(&coin_b_start_after) + option::is_some(&coin_a_start_after) + == option::is_some(&coin_b_start_after) && option::is_some(&coin_b_start_after) == option::is_some(&liquidity_token_start_after), - ESTART_AFTER, + ESTART_AFTER ); let module_store = borrow_global(@minitia_std); @@ -517,12 +544,12 @@ module minitia_std::dex { coin_b: object::object_address(&coin_b_start_after), liquidity_token: object::object_address( &liquidity_token_start_after - ), - }, + ) + } ) } else { option::some( - PairKey { coin_a: @0x0, coin_b: @0x0, liquidity_token: @0x0, }, + PairKey { coin_a: @0x0, coin_b: @0x0, liquidity_token: @0x0 } ) }; @@ -531,11 +558,11 @@ module minitia_std::dex { &module_store.pairs, start_after, option::none(), - 1, + 1 ); while (vector::length(&res) < (limit as u64) - && table::prepare(pairs_iter)) { + && table::prepare(pairs_iter)) { let (key, value) = table::next(pairs_iter); if (&key != option::borrow(&start_after)) { vector::push_back( @@ -551,8 +578,8 @@ module minitia_std::dex { object::address_to_object(value.liquidity_token) ), weights: value.weights, - swap_fee_rate: value.swap_fee_rate, - }, + swap_fee_rate: value.swap_fee_rate + } ) } }; @@ -567,7 +594,7 @@ module minitia_std::dex { coin_a: address, coin_b: address, start_after: Option
, - limit: u8, + limit: u8 ): vector acquires ModuleStore { if (limit > MAX_LIMIT) { limit = MAX_LIMIT; @@ -581,13 +608,11 @@ module minitia_std::dex { PairKey { coin_a, coin_b, - liquidity_token: option::extract(&mut start_after), - }, + liquidity_token: option::extract(&mut start_after) + } ) } else { - option::some( - PairKey { coin_a, coin_b, liquidity_token: @0x0, }, - ) + option::some(PairKey { coin_a, coin_b, liquidity_token: @0x0 }) }; let res = vector[]; @@ -595,14 +620,14 @@ module minitia_std::dex { &module_store.pairs, start_after, option::none(), - 1, + 1 ); while (vector::length(&res) < (limit as u64) - && table::prepare(pairs_iter)) { + && table::prepare(pairs_iter)) { let (key, value) = table::next(pairs_iter); if (coin_a != key.coin_a || coin_b != key.coin_b) - break; + break; if (&key != option::borrow(&start_after)) { vector::push_back(&mut res, *value) } @@ -633,7 +658,7 @@ module minitia_std::dex { public fun get_swap_fee_rate_from_config_response( res: &ConfigResponse - ): Decimal128 { + ): BigDecimal { res.swap_fee_rate } @@ -647,11 +672,11 @@ module minitia_std::dex { res.weights.weights_after } - public fun get_coin_a_weight_from_weight(weight: &Weight): Decimal128 { + public fun get_coin_a_weight_from_weight(weight: &Weight): BigDecimal { weight.coin_a_weight } - public fun get_coin_b_weight_from_weight(weight: &Weight): Decimal128 { + public fun get_coin_b_weight_from_weight(weight: &Weight): BigDecimal { weight.coin_b_weight } @@ -659,10 +684,9 @@ module minitia_std::dex { weight.timestamp } - public fun unpack_pair_response(pair_response: &PairResponse) - : ( - address, address, address, Weights, Decimal128 - ) { + public fun unpack_pair_response( + pair_response: &PairResponse + ): (address, address, address, Weights, BigDecimal) { ( pair_response.coin_a, pair_response.coin_b, @@ -674,22 +698,25 @@ module minitia_std::dex { public fun unpack_current_weight_response( current_weight_response: &CurrentWeightResponse - ): (Decimal128, Decimal128) { - (current_weight_response.coin_a_weight, current_weight_response.coin_b_weight,) + ): (BigDecimal, BigDecimal) { + (current_weight_response.coin_a_weight, current_weight_response.coin_b_weight) } /// Check signer is chain fun check_chain_permission(chain: &signer) { assert!( signer::address_of(chain) == @minitia_std, - error::permission_denied(EUNAUTHORIZED), + error::permission_denied(EUNAUTHORIZED) ); } fun init_module(chain: &signer) { move_to( chain, - ModuleStore { pairs: table::new(), pair_count: 0, }, + ModuleStore { + pairs: table::new(), + pair_count: 0 + } ); } @@ -697,13 +724,13 @@ module minitia_std::dex { creator: &signer, name: String, symbol: String, - swap_fee_rate: Decimal128, - coin_a_weight: Decimal128, - coin_b_weight: Decimal128, + swap_fee_rate: BigDecimal, + coin_a_weight: BigDecimal, + coin_b_weight: BigDecimal, coin_a_metadata: Object, coin_b_metadata: Object, coin_a_amount: u64, - coin_b_amount: u64, + coin_b_amount: u64 ) acquires CoinCapabilities, Config, Pool, ModuleStore { let (_, timestamp) = get_block_info(); let weights = Weights { @@ -714,12 +741,12 @@ module minitia_std::dex { let coin_a = coin::withdraw( creator, coin_a_metadata, - coin_a_amount, + coin_a_amount ); let coin_b = coin::withdraw( creator, coin_b_metadata, - coin_b_amount, + coin_b_amount ); let liquidity_token = @@ -730,7 +757,7 @@ module minitia_std::dex { swap_fee_rate, coin_a, coin_b, - weights, + weights ); coin::deposit(signer::address_of(creator), liquidity_token); } @@ -742,49 +769,49 @@ module minitia_std::dex { creator: &signer, name: String, symbol: String, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal, start_time: u64, - coin_a_start_weight: Decimal128, - coin_b_start_weight: Decimal128, + coin_a_start_weight: BigDecimal, + coin_b_start_weight: BigDecimal, end_time: u64, - coin_a_end_weight: Decimal128, - coin_b_end_weight: Decimal128, + coin_a_end_weight: BigDecimal, + coin_b_end_weight: BigDecimal, coin_a_metadata: Object, coin_b_metadata: Object, coin_a_amount: u64, - coin_b_amount: u64, + coin_b_amount: u64 ) acquires CoinCapabilities, Config, ModuleStore, Pool { let (_, timestamp) = get_block_info(); assert!( start_time > timestamp, - error::invalid_argument(ELBP_START_TIME), + error::invalid_argument(ELBP_START_TIME) ); assert!( end_time > start_time, - error::invalid_argument(EWEIGHTS_TIMESTAMP), + error::invalid_argument(EWEIGHTS_TIMESTAMP) ); let weights = Weights { weights_before: Weight { coin_a_weight: coin_a_start_weight, coin_b_weight: coin_b_start_weight, - timestamp: start_time, + timestamp: start_time }, weights_after: Weight { coin_a_weight: coin_a_end_weight, coin_b_weight: coin_b_end_weight, - timestamp: end_time, + timestamp: end_time } }; let coin_a = coin::withdraw( creator, coin_a_metadata, - coin_a_amount, + coin_a_amount ); let coin_b = coin::withdraw( creator, coin_b_metadata, - coin_b_amount, + coin_b_amount ); let liquidity_token = @@ -795,23 +822,25 @@ module minitia_std::dex { swap_fee_rate, coin_a, coin_b, - weights, + weights ); coin::deposit(signer::address_of(creator), liquidity_token); } + fun max_fee_rate(): BigDecimal { + bigdecimal::from_ratio_u64(5, 100) + } + /// update swap fee rate public entry fun update_swap_fee_rate( - chain: &signer, - pair: Object, - swap_fee_rate: Decimal128, + chain: &signer, pair: Object, swap_fee_rate: BigDecimal ) acquires Config, Pool, ModuleStore { check_chain_permission(chain); let config = borrow_global_mut(object::object_address(&pair)); assert!( - decimal128::val(&swap_fee_rate) <= MAX_FEE_RATE, - error::invalid_argument(EOUT_OF_SWAP_FEE_RATE_RANGE), + bigdecimal::le(swap_fee_rate, max_fee_rate()), + error::invalid_argument(EOUT_OF_SWAP_FEE_RATE_RANGE) ); config.swap_fee_rate = swap_fee_rate; @@ -829,8 +858,8 @@ module minitia_std::dex { coin_a: pair_key.coin_a, coin_b: pair_key.coin_b, liquidity_token: pair_key.liquidity_token, - swap_fee_rate, - }, + swap_fee_rate + } ); } @@ -847,7 +876,7 @@ module minitia_std::dex { pair, coin_a_amount_in, coin_b_amount_in, - min_liquidity, + min_liquidity ); } @@ -872,27 +901,26 @@ module minitia_std::dex { coin::withdraw( account, fungible_asset::store_metadata(pool.coin_a_store), - coin_a_amount_in, + coin_a_amount_in ), coin::withdraw( account, fungible_asset::store_metadata(pool.coin_b_store), - coin_b_amount_in, - ), + coin_b_amount_in + ) ) } else { let coin_a_share_ratio = - decimal128::from_ratio_u64(coin_a_amount_in, coin_a_amount); + bigdecimal::from_ratio_u64(coin_a_amount_in, coin_a_amount); let coin_b_share_ratio = - decimal128::from_ratio_u64(coin_b_amount_in, coin_b_amount); - if (decimal128::val(&coin_a_share_ratio) - > decimal128::val(&coin_b_share_ratio)) { - coin_a_amount_in = decimal128::mul_u64( - &coin_b_share_ratio, coin_a_amount + bigdecimal::from_ratio_u64(coin_b_amount_in, coin_b_amount); + if (bigdecimal::gt(coin_a_share_ratio, coin_b_share_ratio)) { + coin_a_amount_in = bigdecimal::mul_by_u64_truncate( + coin_b_share_ratio, coin_a_amount ); } else { - coin_b_amount_in = decimal128::mul_u64( - &coin_a_share_ratio, coin_b_amount + coin_b_amount_in = bigdecimal::mul_by_u64_truncate( + coin_a_share_ratio, coin_b_amount ); }; @@ -900,13 +928,13 @@ module minitia_std::dex { coin::withdraw( account, fungible_asset::store_metadata(pool.coin_a_store), - coin_a_amount_in, + coin_a_amount_in ), coin::withdraw( account, fungible_asset::store_metadata(pool.coin_b_store), - coin_b_amount_in, - ), + coin_b_amount_in + ) ) }; @@ -924,11 +952,11 @@ module minitia_std::dex { pair: Object, liquidity: u64, min_coin_a_amount: Option, - min_coin_b_amount: Option, + min_coin_b_amount: Option ) acquires CoinCapabilities, Config, Pool { assert!( liquidity != 0, - error::invalid_argument(EZERO_LIQUIDITY), + error::invalid_argument(EZERO_LIQUIDITY) ); let addr = signer::address_of(account); @@ -936,13 +964,13 @@ module minitia_std::dex { coin::withdraw( account, object::convert(pair), - liquidity, + liquidity ); let (coin_a, coin_b) = withdraw_liquidity( liquidity_token, min_coin_a_amount, - min_coin_b_amount, + min_coin_b_amount ); coin::deposit(addr, coin_a); @@ -955,12 +983,12 @@ module minitia_std::dex { pair: Object, offer_coin: Object, offer_coin_amount: u64, - min_return: Option, + min_return: Option ) acquires Config, Pool { let offer_coin = coin::withdraw( account, offer_coin, - offer_coin_amount, + offer_coin_amount ); let return_coin = swap(pair, offer_coin); @@ -969,7 +997,7 @@ module minitia_std::dex { || *option::borrow(&min_return) <= fungible_asset::amount( &return_coin ), - error::invalid_state(EMIN_RETURN), + error::invalid_state(EMIN_RETURN) ); coin::deposit(signer::address_of(account), return_coin); @@ -996,7 +1024,7 @@ module minitia_std::dex { public fun withdraw_liquidity( lp_token: FungibleAsset, min_coin_a_amount: Option, - min_coin_b_amount: Option, + min_coin_b_amount: Option ): (FungibleAsset, FungibleAsset) acquires CoinCapabilities, Config, Pool { let pair_addr = coin_address(&lp_token); let pool = borrow_global_mut(pair_addr); @@ -1005,33 +1033,35 @@ module minitia_std::dex { option::extract( &mut fungible_asset::supply( fungible_asset::metadata_from_asset(&lp_token) - ), + ) ); let coin_a_amount = fungible_asset::balance(pool.coin_a_store); let given_token_amount = fungible_asset::amount(&lp_token); let coin_b_amount = fungible_asset::balance(pool.coin_b_store); let given_share_ratio = - decimal128::from_ratio((given_token_amount as u128), total_share); - let coin_a_amount_out = decimal128::mul_u64(&given_share_ratio, coin_a_amount); - let coin_b_amount_out = decimal128::mul_u64(&given_share_ratio, coin_b_amount); + bigdecimal::from_ratio_u128((given_token_amount as u128), total_share); + let coin_a_amount_out = + bigdecimal::mul_by_u64_truncate(given_share_ratio, coin_a_amount); + let coin_b_amount_out = + bigdecimal::mul_by_u64_truncate(given_share_ratio, coin_b_amount); check_lbp_ended(&config.weights); assert!( option::is_none(&min_coin_a_amount) || *option::borrow(&min_coin_a_amount) <= coin_a_amount_out, - error::invalid_state(EMIN_WITHDRAW), + error::invalid_state(EMIN_WITHDRAW) ); assert!( option::is_none(&min_coin_b_amount) || *option::borrow(&min_coin_b_amount) <= coin_b_amount_out, - error::invalid_state(EMIN_WITHDRAW), + error::invalid_state(EMIN_WITHDRAW) ); // burn liquidity token let liquidity_token_capabilities = borrow_global(pair_addr); coin::burn( &liquidity_token_capabilities.burn_cap, - lp_token, + lp_token ); // emit events @@ -1043,8 +1073,8 @@ module minitia_std::dex { liquidity_token: pair_addr, coin_a_amount: coin_a_amount_out, coin_b_amount: coin_b_amount_out, - liquidity: given_token_amount, - }, + liquidity: given_token_amount + } ); let pool = borrow_global_mut(pair_addr); @@ -1054,13 +1084,13 @@ module minitia_std::dex { fungible_asset::withdraw( pair_signer, pool.coin_a_store, - coin_a_amount_out, + coin_a_amount_out ), fungible_asset::withdraw( pair_signer, pool.coin_b_store, - coin_b_amount_out, - ), + coin_b_amount_out + ) ) } @@ -1070,96 +1100,33 @@ module minitia_std::dex { public fun single_asset_provide_liquidity( pair: Object, provide_coin: FungibleAsset, - min_liquidity_amount: Option, + min_liquidity_amount: Option ): FungibleAsset acquires Config, CoinCapabilities, Pool { let pair_addr = object::object_address(&pair); - let config = borrow_global(pair_addr); - check_lbp_ended(&config.weights); - - // provide coin type must be one of coin a or coin b coin type - let provide_metadata = fungible_asset::metadata_from_asset(&provide_coin); - let provide_address = object::object_address(&provide_metadata); - let pair_key = generate_pair_key(pair); - assert!( - provide_address == pair_key.coin_a || provide_address == pair_key.coin_b, - error::invalid_argument(ECOIN_TYPE), - ); - let is_provide_a = provide_address == pair_key.coin_a; - - let total_share = option::extract(&mut fungible_asset::supply(pair)); - assert!( - total_share != 0, - error::invalid_state(EZERO_LIQUIDITY), - ); - - // load values for fee and increased liquidity amount calculation - let amount_in = fungible_asset::amount(&provide_coin); - let (coin_a_weight, coin_b_weight) = get_weight(&config.weights); let pool = borrow_global_mut(pair_addr); - let (normalized_weight, pool_amount_in, provide_coin_addr) = - if (is_provide_a) { - let normalized_weight = - decimal128::from_ratio( - decimal128::val(&coin_a_weight), - decimal128::val(&coin_a_weight) + decimal128::val(&coin_b_weight), - ); - - let pool_amount_in = fungible_asset::balance(pool.coin_a_store); - fungible_asset::deposit(pool.coin_a_store, provide_coin); - - (normalized_weight, pool_amount_in, pair_key.coin_a) - } else { - let normalized_weight = - decimal128::from_ratio( - decimal128::val(&coin_b_weight), - decimal128::val(&coin_a_weight) + decimal128::val(&coin_b_weight), - ); - - let pool_amount_in = fungible_asset::balance(pool.coin_b_store); - fungible_asset::deposit(pool.coin_b_store, provide_coin); - - (normalized_weight, pool_amount_in, pair_key.coin_b) - }; - // CONTRACT: cannot provide more than the pool amount to prevent huge price impact - assert!( - pool_amount_in > amount_in, - error::invalid_argument(EPRICE_IMPACT), - ); + let provide_metadata = fungible_asset::metadata_from_asset(&provide_coin); + let provide_amount = fungible_asset::amount(&provide_coin); - // compute fee amount with the assumption that we will swap (1 - normalized_weight) of amount_in - let adjusted_swap_amount = - decimal128::mul_u64( - &decimal128::sub( - &decimal128::one(), - &normalized_weight, - ), - amount_in, - ); - let fee_amount = - calculate_fee_with_minimum( - &config.swap_fee_rate, - adjusted_swap_amount, + let (liquidity, fee_amount, is_provide_a) = + calculate_single_asset_provide_liquidity_return_amount( + pool, pair, provide_metadata, provide_amount ); - // actual amount in after deducting fee amount - let adjusted_amount_in = amount_in - fee_amount; + // deposit token + if (is_provide_a) { + fungible_asset::deposit(pool.coin_a_store, provide_coin); + } else { + fungible_asset::deposit(pool.coin_b_store, provide_coin); + }; - // calculate new total share and new liquidity - let base = - decimal128::from_ratio_u64( - adjusted_amount_in + pool_amount_in, - pool_amount_in, - ); - let pool_ratio = pow(&base, &normalized_weight); - let new_total_share = decimal128::mul_u128(&pool_ratio, total_share); - let liquidity = (new_total_share - total_share as u64); + let pair_key = generate_pair_key(pair); // check min liquidity assertion assert!( option::is_none(&min_liquidity_amount) || *option::borrow(&min_liquidity_amount) <= liquidity, - error::invalid_state(EMIN_LIQUIDITY), + error::invalid_state(EMIN_LIQUIDITY) ); // emit events @@ -1167,31 +1134,33 @@ module minitia_std::dex { SingleAssetProvideEvent { coin_a: pair_key.coin_a, coin_b: pair_key.coin_b, - provide_coin: provide_coin_addr, + provide_coin: object::object_address(&provide_metadata), liquidity_token: pair_addr, - provide_amount: amount_in, + provide_amount, fee_amount, - liquidity, - }, + liquidity + } ); // mint liquidity tokens to provider let liquidity_token_capabilities = borrow_global(pair_addr); coin::mint( &liquidity_token_capabilities.mint_cap, - liquidity, + liquidity ) } /// Swap directly - public fun swap(pair: Object, offer_coin: FungibleAsset,): FungibleAsset acquires Config, Pool { + public fun swap( + pair: Object, offer_coin: FungibleAsset + ): FungibleAsset acquires Config, Pool { let offer_amount = fungible_asset::amount(&offer_coin); let offer_metadata = fungible_asset::metadata_from_asset(&offer_coin); let offer_address = object::object_address(&offer_metadata); let pair_key = generate_pair_key(pair); assert!( offer_address == pair_key.coin_a || offer_address == pair_key.coin_b, - error::invalid_argument(ECOIN_TYPE), + error::invalid_argument(ECOIN_TYPE) ); let is_offer_a = offer_address == pair_key.coin_a; @@ -1216,7 +1185,7 @@ module minitia_std::dex { offer_weight, return_weight, fungible_asset::amount(&offer_coin), - swap_fee_rate, + swap_fee_rate ); // apply swap result to pool @@ -1230,14 +1199,14 @@ module minitia_std::dex { fungible_asset::withdraw( pair_signer, pool.coin_b_store, - return_amount, + return_amount ) } else { fungible_asset::deposit(pool.coin_b_store, offer_coin); fungible_asset::withdraw( pair_signer, pool.coin_a_store, - return_amount, + return_amount ) }; @@ -1249,21 +1218,45 @@ module minitia_std::dex { liquidity_token: pair_addr, fee_amount, offer_amount, - return_amount, - }, + return_amount + } ); return_coin } + /// Sum of weights must be 1 + fun assert_weights(weights: Weights) { + assert!( + bigdecimal::eq( + bigdecimal::one(), + bigdecimal::add( + weights.weights_before.coin_a_weight, + weights.weights_before.coin_b_weight + ) + ), + EINVALID_WEIGHTS + ); + assert!( + bigdecimal::eq( + bigdecimal::one(), + bigdecimal::add( + weights.weights_after.coin_a_weight, + weights.weights_after.coin_b_weight + ) + ), + EINVALID_WEIGHTS + ); + } + public fun create_pair( creator: &signer, name: String, symbol: String, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal, coin_a: FungibleAsset, coin_b: FungibleAsset, - weights: Weights, + weights: Weights ): FungibleAsset acquires CoinCapabilities, Config, ModuleStore, Pool { let (mint_cap, burn_cap, freeze_cap, extend_ref) = coin::initialize_and_generate_extend_ref( @@ -1273,17 +1266,19 @@ module minitia_std::dex { symbol, 6, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); + assert_weights(weights); + assert!( - decimal128::val(&swap_fee_rate) <= MAX_FEE_RATE, - error::invalid_argument(EOUT_OF_SWAP_FEE_RATE_RANGE), + bigdecimal::le(swap_fee_rate, max_fee_rate()), + error::invalid_argument(EOUT_OF_SWAP_FEE_RATE_RANGE) ); assert!( coin_address(&coin_a) != coin_address(&coin_b), - error::invalid_argument(ESAME_COIN_TYPE), + error::invalid_argument(ESAME_COIN_TYPE) ); let pair_signer = &object::generate_signer_for_extending(&extend_ref); @@ -1294,24 +1289,24 @@ module minitia_std::dex { let coin_a_store = primary_fungible_store::create_primary_store( pair_address, - fungible_asset::asset_metadata(&coin_a), + fungible_asset::asset_metadata(&coin_a) ); let coin_b_store = primary_fungible_store::create_primary_store( pair_address, - fungible_asset::asset_metadata(&coin_b), + fungible_asset::asset_metadata(&coin_b) ); let coin_a_addr = coin_address(&coin_a); let coin_b_addr = coin_address(&coin_b); move_to( pair_signer, - Pool { coin_a_store, coin_b_store }, + Pool { coin_a_store, coin_b_store } ); move_to( pair_signer, - CoinCapabilities { mint_cap, freeze_cap, burn_cap }, + CoinCapabilities { mint_cap, freeze_cap, burn_cap } ); move_to( @@ -1321,18 +1316,18 @@ module minitia_std::dex { // temp weights for initial provide weights: Weights { weights_before: Weight { - coin_a_weight: decimal128::one(), - coin_b_weight: decimal128::one(), - timestamp: 0, + coin_a_weight: bigdecimal::one(), + coin_b_weight: bigdecimal::one(), + timestamp: 0 }, weights_after: Weight { - coin_a_weight: decimal128::one(), - coin_b_weight: decimal128::one(), - timestamp: 0, + coin_a_weight: bigdecimal::one(), + coin_b_weight: bigdecimal::one(), + timestamp: 0 } }, - swap_fee_rate, - }, + swap_fee_rate + } ); let liquidity_token = @@ -1340,7 +1335,7 @@ module minitia_std::dex { object::address_to_object(pair_address), coin_a, coin_b, - option::none(), + option::none() ); // update weights @@ -1369,8 +1364,8 @@ module minitia_std::dex { coin_b: coin_b_addr, liquidity_token: pair_address, weights, - swap_fee_rate, - }, + swap_fee_rate + } ); // emit create pair event @@ -1380,8 +1375,8 @@ module minitia_std::dex { coin_b: coin_b_addr, liquidity_token: pair_address, weights, - swap_fee_rate, - }, + swap_fee_rate + } ); liquidity_token @@ -1393,7 +1388,7 @@ module minitia_std::dex { pair: Object, coin_a: FungibleAsset, coin_b: FungibleAsset, - min_liquidity_amount: Option, + min_liquidity_amount: Option ): FungibleAsset acquires Config, Pool, CoinCapabilities { let pool_addr = object::object_address(&pair); let config = borrow_global_mut(pool_addr); @@ -1401,35 +1396,20 @@ module minitia_std::dex { check_lbp_ended(&config.weights); let coin_a_amount_in = fungible_asset::amount(&coin_a); - let coin_a_amount = fungible_asset::balance(pool.coin_a_store); let coin_b_amount_in = fungible_asset::amount(&coin_b); - let coin_b_amount = fungible_asset::balance(pool.coin_b_store); - let total_share = option::extract(&mut fungible_asset::supply(pair)); let liquidity = - if (total_share == 0) { - if (coin_a_amount_in > coin_b_amount_in) { - coin_a_amount_in - } else { - coin_b_amount_in - } - } else { - let coin_a_share_ratio = - decimal128::from_ratio_u64(coin_a_amount_in, coin_a_amount); - let coin_b_share_ratio = - decimal128::from_ratio_u64(coin_b_amount_in, coin_b_amount); - if (decimal128::val(&coin_a_share_ratio) - > decimal128::val(&coin_b_share_ratio)) { - (decimal128::mul_u128(&coin_b_share_ratio, total_share) as u64) - } else { - (decimal128::mul_u128(&coin_a_share_ratio, total_share) as u64) - } - }; + calculate_provide_liquidity_return_amount( + pool, + pair, + coin_a_amount_in, + coin_b_amount_in + ); assert!( option::is_none(&min_liquidity_amount) || *option::borrow(&min_liquidity_amount) <= liquidity, - error::invalid_state(EMIN_LIQUIDITY), + error::invalid_state(EMIN_LIQUIDITY) ); event::emit( @@ -1439,8 +1419,8 @@ module minitia_std::dex { liquidity_token: pool_addr, coin_a_amount: coin_a_amount_in, coin_b_amount: coin_b_amount_in, - liquidity, - }, + liquidity + } ); fungible_asset::deposit(pool.coin_a_store, coin_a); @@ -1449,7 +1429,7 @@ module minitia_std::dex { let liquidity_token_capabilities = borrow_global(pool_addr); coin::mint( &liquidity_token_capabilities.mint_cap, - liquidity, + liquidity ) } @@ -1463,7 +1443,7 @@ module minitia_std::dex { assert!( timestamp >= weights.weights_after.timestamp, - error::invalid_state(ELBP_NOT_ENDED), + error::invalid_state(ELBP_NOT_ENDED) ) } @@ -1480,17 +1460,16 @@ module minitia_std::dex { } /// return (coin_a_weight, coin_b_weight) - fun get_weight(weights: &Weights): (Decimal128, Decimal128) { + fun get_weight(weights: &Weights): (BigDecimal, BigDecimal) { let (_, timestamp) = get_block_info(); if (timestamp <= weights.weights_before.timestamp) { (weights.weights_before.coin_a_weight, weights.weights_before.coin_b_weight) } else if (timestamp < weights.weights_after.timestamp) { let interval = - ( - weights.weights_after.timestamp - weights.weights_before.timestamp as u128 - ); - let time_diff_after = (weights.weights_after.timestamp - timestamp as u128); - let time_diff_before = (timestamp - weights.weights_before.timestamp as u128); + weights.weights_after.timestamp - weights.weights_before.timestamp; + + let time_diff_after = weights.weights_after.timestamp - timestamp; + let time_diff_before = timestamp - weights.weights_before.timestamp; // when timestamp_before < timestamp < timestamp_after // weight is linearly change from before to after @@ -1505,35 +1484,150 @@ module minitia_std::dex { // l = m + n = g * t * (t_a - t_b) + c * (t_a - t_b) // weight = l / (t_a - t_b) = g * t + c let coin_a_m = - decimal128::new( - decimal128::val(&weights.weights_after.coin_a_weight) * time_diff_before, + bigdecimal::mul_by_u64( + weights.weights_after.coin_a_weight, time_diff_before ); let coin_a_n = - decimal128::new( - decimal128::val(&weights.weights_before.coin_a_weight) * time_diff_after, + bigdecimal::mul_by_u64( + weights.weights_before.coin_a_weight, time_diff_after ); - let coin_a_l = decimal128::add(&coin_a_m, &coin_a_n); + let coin_a_l = bigdecimal::add(coin_a_m, coin_a_n); let coin_b_m = - decimal128::new( - decimal128::val(&weights.weights_after.coin_b_weight) * time_diff_before, + bigdecimal::mul_by_u64( + weights.weights_after.coin_b_weight, time_diff_before ); let coin_b_n = - decimal128::new( - decimal128::val(&weights.weights_before.coin_b_weight) * time_diff_after, + bigdecimal::mul_by_u64( + weights.weights_before.coin_b_weight, time_diff_after ); - let coin_b_l = decimal128::add(&coin_b_m, &coin_b_n); - (decimal128::div(&coin_a_l, interval), decimal128::div(&coin_b_l, interval)) + let coin_b_l = bigdecimal::add(coin_b_m, coin_b_n); + ( + bigdecimal::div_by_u64(coin_a_l, interval), + bigdecimal::div_by_u64(coin_b_l, interval) + ) } else { (weights.weights_after.coin_a_weight, weights.weights_after.coin_b_weight) } } + fun calculate_provide_liquidity_return_amount( + pool: &Pool, + pair: Object, + coin_a_amount_in: u64, + coin_b_amount_in: u64 + ): u64 { + let coin_a_amount = fungible_asset::balance(pool.coin_a_store); + let coin_b_amount = fungible_asset::balance(pool.coin_b_store); + let total_share = option::extract(&mut fungible_asset::supply(pair)); + + if (total_share == 0) { + if (coin_a_amount_in > coin_b_amount_in) { + coin_a_amount_in + } else { + coin_b_amount_in + } + } else { + let coin_a_share_ratio = + bigdecimal::from_ratio_u64(coin_a_amount_in, coin_a_amount); + let coin_b_share_ratio = + bigdecimal::from_ratio_u64(coin_b_amount_in, coin_b_amount); + if (bigdecimal::gt(coin_a_share_ratio, coin_b_share_ratio)) { + (bigdecimal::mul_by_u128_truncate(coin_b_share_ratio, total_share) as u64) + } else { + (bigdecimal::mul_by_u128_truncate(coin_a_share_ratio, total_share) as u64) + } + } + } + + fun calculate_single_asset_provide_liquidity_return_amount( + pool: &Pool, + pair: Object, + provide_metadata: Object, + amount_in: u64 + ): (u64, u64, bool) acquires Config { + let pair_addr = object::object_address(&pair); + let config = borrow_global(pair_addr); + check_lbp_ended(&config.weights); + + // provide coin type must be one of coin a or coin b coin type + assert!( + provide_metadata == fungible_asset::store_metadata(pool.coin_a_store) + || provide_metadata + == fungible_asset::store_metadata(pool.coin_b_store), + error::invalid_argument(ECOIN_TYPE) + ); + let is_provide_a = + provide_metadata == fungible_asset::store_metadata(pool.coin_a_store); + + let total_share = option::extract(&mut fungible_asset::supply(pair)); + assert!( + total_share != 0, + error::invalid_state(EZERO_LIQUIDITY) + ); + + // load values for fee and increased liquidity amount calculation + let (coin_a_weight, coin_b_weight) = get_weight(&config.weights); + let (normalized_weight, pool_amount_in) = + if (is_provide_a) { + let normalized_weight = + bigdecimal::div( + coin_a_weight, + bigdecimal::add(coin_a_weight, coin_b_weight) + ); + let pool_amount_in = fungible_asset::balance(pool.coin_a_store); + (normalized_weight, pool_amount_in) + } else { + let normalized_weight = + bigdecimal::div( + coin_b_weight, + bigdecimal::add(coin_a_weight, coin_b_weight) + ); + + let pool_amount_in = fungible_asset::balance(pool.coin_b_store); + + (normalized_weight, pool_amount_in) + }; + + // CONTRACT: cannot provide more than the pool amount to prevent huge price impact + assert!( + pool_amount_in >= amount_in, + error::invalid_argument(EPRICE_IMPACT) + ); + + // compute fee amount with the assumption that we will swap (1 - normalized_weight) of amount_in + let adjusted_swap_amount = + bigdecimal::mul_by_u64_truncate( + bigdecimal::sub( + bigdecimal::one(), + normalized_weight + ), + amount_in + ); + let fee_amount = + calculate_fee_with_minimum( + config.swap_fee_rate, + adjusted_swap_amount + ); + + // actual amount in after deducting fee amount + let adjusted_amount_in = amount_in - fee_amount; + + // calculate new total share and new liquidity + let base = + bigdecimal::from_ratio_u64( + adjusted_amount_in + pool_amount_in, + pool_amount_in + ); + let pool_ratio = pow(base, normalized_weight); + let new_total_share = bigdecimal::mul_by_u128_truncate(pool_ratio, total_share); + ((new_total_share - total_share as u64), fee_amount, is_provide_a) + } + /// get all pool info at once (a_amount, b_amount, a_weight, b_weight, fee_rate) - public fun pool_info(pair: Object, lbp_assertion: bool) - : ( - u64, u64, Decimal128, Decimal128, Decimal128 - ) acquires Config, Pool { + public fun pool_info( + pair: Object, lbp_assertion: bool + ): (u64, u64, BigDecimal, BigDecimal, BigDecimal) acquires Config, Pool { let pair_addr = object::object_address(&pair); let config = borrow_global(pair_addr); if (lbp_assertion) { @@ -1541,7 +1635,7 @@ module minitia_std::dex { let (_, timestamp) = get_block_info(); assert!( timestamp >= config.weights.weights_before.timestamp, - error::invalid_state(ELBP_NOT_STARTED), + error::invalid_state(ELBP_NOT_STARTED) ); }; @@ -1553,15 +1647,15 @@ module minitia_std::dex { fungible_asset::balance(pool.coin_b_store), coin_a_weight, coin_b_weight, - config.swap_fee_rate, + config.swap_fee_rate ) } // avoid zero fee amount to prevent fee bypass attack fun calculate_fee_with_minimum( - swap_fee_rate: &Decimal128, amount_in: u64 + swap_fee_rate: BigDecimal, amount_in: u64 ): u64 { - let fee_amount = decimal128::mul_u64_with_ceil(swap_fee_rate, amount_in); + let fee_amount = bigdecimal::mul_by_u64_ceil(swap_fee_rate, amount_in); if (fee_amount == 0) { fee_amount = 1; }; @@ -1575,35 +1669,31 @@ module minitia_std::dex { public fun swap_simulation( pool_amount_in: u64, pool_amount_out: u64, - weight_in: Decimal128, - weight_out: Decimal128, + weight_in: BigDecimal, + weight_out: BigDecimal, amount_in: u64, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal ): (u64, u64) { assert!( amount_in > 0, - error::invalid_argument(EZERO_AMOUNT_IN), + error::invalid_argument(EZERO_AMOUNT_IN) ); - let one = decimal128::one(); - let exp = - decimal128::from_ratio( - decimal128::val(&weight_in), - decimal128::val(&weight_out), - ); + let one = bigdecimal::one(); + let exp = bigdecimal::div(weight_in, weight_out); - let fee_amount = calculate_fee_with_minimum(&swap_fee_rate, amount_in); + let fee_amount = calculate_fee_with_minimum(swap_fee_rate, amount_in); let adjusted_amount_in = amount_in - fee_amount; let base = - decimal128::from_ratio_u64( + bigdecimal::from_ratio_u64( pool_amount_in, - pool_amount_in + adjusted_amount_in, + pool_amount_in + adjusted_amount_in ); - let sub_amount = pow(&base, &exp); + let sub_amount = pow(base, exp); ( - decimal128::mul_u64( - &decimal128::sub(&one, &sub_amount), - pool_amount_out, + bigdecimal::mul_by_u64_truncate( + bigdecimal::sub(one, sub_amount), + pool_amount_out ), fee_amount ) @@ -1612,32 +1702,30 @@ module minitia_std::dex { public fun swap_simulation_given_out( pool_amount_in: u64, pool_amount_out: u64, - weight_in: Decimal128, - weight_out: Decimal128, + weight_in: BigDecimal, + weight_out: BigDecimal, amount_out: u64, - swap_fee_rate: Decimal128, + swap_fee_rate: BigDecimal ): (u64, u64) { - let one = decimal128::one(); - let exp = - decimal128::from_ratio( - decimal128::val(&weight_out), - decimal128::val(&weight_in), - ); - let base = decimal128::from_ratio_u64( + let one = bigdecimal::one(); + let exp = bigdecimal::div(weight_out, weight_in); + let base = bigdecimal::from_ratio_u64( pool_amount_out, pool_amount_out - amount_out ); - let base_exp = pow(&base, &exp); + let base_exp = pow(base, exp); let adjusted_amount_in = - decimal128::val(&decimal128::sub(&base_exp, &one)) * (pool_amount_in as u128); - let sub_one_fee = decimal128::sub(&one, &swap_fee_rate); - - let amount_in = (adjusted_amount_in / decimal128::val(&sub_one_fee) as u64); - let fee_amount = calculate_fee_with_minimum(&swap_fee_rate, amount_in); + bigdecimal::mul_by_u64(bigdecimal::sub(base_exp, one), pool_amount_in); + let sub_one_fee = bigdecimal::sub(one, swap_fee_rate); + let amount_in = + bigdecimal::truncate_u64(bigdecimal::div(adjusted_amount_in, sub_one_fee)); + let fee_amount = calculate_fee_with_minimum(swap_fee_rate, amount_in); (amount_in, fee_amount) } - public fun pool_metadata(pair: Object): (Object, Object) acquires Pool { + public fun pool_metadata( + pair: Object + ): (Object, Object) acquires Pool { let pair_addr = object::object_address(&pair); let pool = borrow_global(pair_addr); ( @@ -1648,33 +1736,35 @@ module minitia_std::dex { /// a^x = 1 + sigma[(k^n)/n!] /// k = x * ln(a) - fun pow(base: &Decimal128, exp: &Decimal128): Decimal128 { + fun pow(base: BigDecimal, exp: BigDecimal): BigDecimal { assert!( - decimal128::val(base) != 0 && decimal128::val(base) < 2000000000000000000, - error::invalid_argument(EOUT_OF_BASE_RANGE), + !bigdecimal::is_zero(base) && bigdecimal::lt(base, bigdecimal::from_u64(2)), + error::invalid_argument(EOUT_OF_BASE_RANGE) ); - let res = decimal128::one(); + let res = bigdecimal::one(); let (ln_a, neg) = ln(base); - let k = mul_decimal128s(&ln_a, exp); + let k = bigdecimal::mul(ln_a, exp); let comp = k; let index = 1; - let subs: vector = vector[]; - while (decimal128::val(&comp) > PRECISION) { + let subs: vector = vector[]; + + let precision = bigdecimal::from_scaled(biguint::from_u64(PRECISION)); + while (bigdecimal::gt(comp, precision)) { if (index & 1 == 1 && neg) { vector::push_back(&mut subs, comp) } else { - res = decimal128::add(&res, &comp) + res = bigdecimal::add(res, comp) }; - comp = decimal128::div(&mul_decimal128s(&comp, &k), index + 1); + comp = bigdecimal::div_by_u64(bigdecimal::mul(comp, k), index + 1); index = index + 1; }; let index = 0; while (index < vector::length(&subs)) { let comp = vector::borrow(&subs, index); - res = decimal128::sub(&res, comp); + res = bigdecimal::sub(res, *comp); index = index + 1; }; @@ -1683,32 +1773,32 @@ module minitia_std::dex { /// ln(1 + a) = sigma[(-1) ^ (n + 1) * (a ^ n / n)] /// https://en.wikipedia.org/wiki/Taylor_series#Natural_logarithm - fun ln(num: &Decimal128): (Decimal128, bool) { - let one = decimal128::val(&decimal128::one()); - let num_val = decimal128::val(num); + fun ln(num: BigDecimal): (BigDecimal, bool) { + let one = bigdecimal::one(); let (a, a_neg) = - if (num_val >= one) { - (decimal128::sub(num, &decimal128::one()), false) + if (bigdecimal::ge(num, one)) { + (bigdecimal::sub(num, one), false) } else { - (decimal128::sub(&decimal128::one(), num), true) + (bigdecimal::sub(one, num), true) }; - let res = decimal128::zero(); + let res = bigdecimal::zero(); let comp = a; let index = 1; - while (decimal128::val(&comp) > PRECISION) { + let precision = bigdecimal::from_scaled(biguint::from_u64(PRECISION)); + while (bigdecimal::gt(comp, precision)) { if (index & 1 == 0 && !a_neg) { - res = decimal128::sub(&res, &comp); + res = bigdecimal::sub(res, comp); } else { - res = decimal128::add(&res, &comp); + res = bigdecimal::add(res, comp); }; // comp(old) = a ^ n / n // comp(new) = comp(old) * a * n / (n + 1) = a ^ (n + 1) / (n + 1) - comp = decimal128::div( - &decimal128::new(decimal128::val(&mul_decimal128s(&comp, &a)) * index), // comp * a * index - index + 1, + comp = bigdecimal::div_by_u64( + bigdecimal::mul_by_u64(bigdecimal::mul(comp, a), index), // comp * a * index + index + 1 ); index = index + 1; @@ -1717,16 +1807,6 @@ module minitia_std::dex { (res, a_neg) } - fun mul_decimal128s( - decimal128_0: &Decimal128, decimal128_1: &Decimal128 - ): Decimal128 { - let one = (decimal128::val(&decimal128::one()) as u256); - let val_mul = - (decimal128::val(decimal128_0) as u256) - * (decimal128::val(decimal128_1) as u256); - decimal128::new((val_mul / one as u128)) - } - #[test_only] public fun init_module_for_test() { init_module(&minitia_std::account::create_signer_for_test(@minitia_std)); @@ -1739,21 +1819,20 @@ module minitia_std::dex { struct CoinCapsInit has key { burn_cap: coin::BurnCapability, freeze_cap: coin::FreezeCapability, - mint_cap: coin::MintCapability, + mint_cap: coin::MintCapability } #[test_only] struct CoinCapsUsdc has key { burn_cap: coin::BurnCapability, freeze_cap: coin::FreezeCapability, - mint_cap: coin::MintCapability, + mint_cap: coin::MintCapability } #[test_only] - fun initialized_coin(account: &signer, symbol: String,) - : ( - coin::BurnCapability, coin::FreezeCapability, coin::MintCapability - ) { + fun initialized_coin( + account: &signer, symbol: String + ): (coin::BurnCapability, coin::FreezeCapability, coin::MintCapability) { let (mint_cap, burn_cap, freeze_cap, _) = coin::initialize_and_generate_extend_ref( account, @@ -1762,14 +1841,14 @@ module minitia_std::dex { symbol, 6, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); return (burn_cap, freeze_cap, mint_cap) } #[test(chain = @0x1)] - fun end_to_end(chain: signer,) acquires Config, CoinCapabilities, ModuleStore, Pool { + fun end_to_end(chain: signer) acquires Config, CoinCapabilities, ModuleStore, Pool { init_module(&chain); minitia_std::primary_fungible_store::init_module_for_test(); @@ -1785,12 +1864,12 @@ module minitia_std::dex { coin::mint_to( &initia_mint_cap, chain_addr, - 100000000, + 100000000 ); coin::mint_to( &usdc_mint_cap, chain_addr, - 100000000, + 100000000 ); // spot price is 1 @@ -1798,13 +1877,13 @@ module minitia_std::dex { &chain, std::string::utf8(b"name"), std::string::utf8(b"SYMBOL"), - decimal128::from_ratio(3, 1000), - decimal128::from_ratio(8, 10), - decimal128::from_ratio(2, 10), + bigdecimal::from_ratio_u64(3, 1000), + bigdecimal::from_ratio_u64(8, 10), + bigdecimal::from_ratio_u64(2, 10), coin::metadata(chain_addr, string::utf8(b"INIT")), coin::metadata(chain_addr, string::utf8(b"USDC")), 80000000, - 20000000, + 20000000 ); let lp_metadata = coin::metadata(chain_addr, string::utf8(b"SYMBOL")); @@ -1812,15 +1891,15 @@ module minitia_std::dex { assert!( coin::balance(chain_addr, init_metadata) == 20000000, - 0, + 0 ); assert!( coin::balance(chain_addr, usdc_metadata) == 80000000, - 1, + 1 ); assert!( coin::balance(chain_addr, lp_metadata) == 80000000, - 2, + 2 ); // swap init to usdc @@ -1829,15 +1908,15 @@ module minitia_std::dex { pair, init_metadata, 1000, - option::none(), + option::none() ); assert!( coin::balance(chain_addr, init_metadata) == 20000000 - 1000, - 3, + 3 ); assert!( coin::balance(chain_addr, usdc_metadata) == 80000000 + 996, - 4, + 4 ); // return 999 commission 3 // swap usdc to init @@ -1846,15 +1925,15 @@ module minitia_std::dex { pair, usdc_metadata, 1000, - option::none(), + option::none() ); assert!( coin::balance(chain_addr, init_metadata) == 20000000 - 1000 + 997, - 5, + 5 ); // return 1000 commission 3 assert!( coin::balance(chain_addr, usdc_metadata) == 80000000 + 996 - 1000, - 6, + 6 ); // withdraw liquidity @@ -1863,15 +1942,17 @@ module minitia_std::dex { pair, 40000000, option::none(), - option::none(), + option::none() ); assert!( - coin::balance(chain_addr, init_metadata) == 20000000 - 1000 + 997 + 40000001, - 7, + coin::balance(chain_addr, init_metadata) == 20000000 - 1000 + 997 + + 40000001, + 7 ); assert!( - coin::balance(chain_addr, usdc_metadata) == 80000000 + 996 - 1000 + 10000002, - 8, + coin::balance(chain_addr, usdc_metadata) == 80000000 + 996 - 1000 + + 10000002, + 8 ); // single asset provide liquidity (coin b) @@ -1881,11 +1962,11 @@ module minitia_std::dex { pair, usdc_metadata, 100000, - option::none(), + option::none() ); assert!( coin::balance(chain_addr, lp_metadata) == 40000000 + 79491, - 9, + 9 ); // single asset provide liquidity (coin a) @@ -1895,11 +1976,11 @@ module minitia_std::dex { pair, init_metadata, 100000, - option::none(), + option::none() ); assert!( coin::balance(chain_addr, lp_metadata) == 40000000 + 79491 + 80090, - 10, + 10 ); move_to( @@ -1907,8 +1988,8 @@ module minitia_std::dex { CoinCapsInit { burn_cap: initia_burn_cap, freeze_cap: initia_freeze_cap, - mint_cap: initia_mint_cap, - }, + mint_cap: initia_mint_cap + } ); move_to( @@ -1916,13 +1997,13 @@ module minitia_std::dex { CoinCapsUsdc { burn_cap: usdc_burn_cap, freeze_cap: usdc_freeze_cap, - mint_cap: usdc_mint_cap, - }, + mint_cap: usdc_mint_cap + } ); } #[test(chain = @0x1)] - fun lbp_end_to_end(chain: signer,) acquires Config, CoinCapabilities, ModuleStore, Pool { + fun lbp_end_to_end(chain: signer) acquires Config, CoinCapabilities, ModuleStore, Pool { init_module(&chain); minitia_std::primary_fungible_store::init_module_for_test(); @@ -1938,12 +2019,12 @@ module minitia_std::dex { coin::mint_to( &initia_mint_cap, chain_addr, - 100000000, + 100000000 ); coin::mint_to( &usdc_mint_cap, chain_addr, - 100000000, + 100000000 ); set_block_info(10, 1000); @@ -1952,54 +2033,52 @@ module minitia_std::dex { &chain, std::string::utf8(b"name"), std::string::utf8(b"SYMBOL"), - decimal128::from_ratio(3, 1000), + bigdecimal::from_ratio_u64(3, 1000), 2000, - decimal128::from_ratio(99, 100), - decimal128::from_ratio(1, 100), + bigdecimal::from_ratio_u64(99, 100), + bigdecimal::from_ratio_u64(1, 100), 3000, - decimal128::from_ratio(61, 100), - decimal128::from_ratio(39, 100), + bigdecimal::from_ratio_u64(61, 100), + bigdecimal::from_ratio_u64(39, 100), init_metadata, usdc_metadata, 80000000, - 20000000, + 20000000 ); let lp_metadata = coin::metadata(chain_addr, string::utf8(b"SYMBOL")); let pair = object::convert(lp_metadata); assert!( - get_spot_price(pair, init_metadata) - == decimal128::from_string(&string::utf8(b"24.75")), - 0, + get_spot_price(pair, init_metadata) == bigdecimal::from_ratio_u64(2475, 100), + 0 ); // 0.8 : 0.2 set_block_info(11, 2500); assert!( - get_spot_price(pair, init_metadata) - == decimal128::from_string(&string::utf8(b"1")), - 1, + get_spot_price(pair, init_metadata) == bigdecimal::one(), + 1 ); // 0.61 : 0.39 set_block_info(12, 3500); assert!( get_spot_price(pair, init_metadata) - == decimal128::from_string(&string::utf8(b"0.391025641025641025")), - 2, + == bigdecimal::from_ratio_u64(391025641025641025, 1000000000000000000), + 2 ); assert!( coin::balance(chain_addr, init_metadata) == 20000000, - 0, + 0 ); assert!( coin::balance(chain_addr, usdc_metadata) == 80000000, - 1, + 1 ); assert!( coin::balance(chain_addr, lp_metadata) == 80000000, - 3, + 3 ); // swap test during LBP (0.8: 0.2) @@ -2011,15 +2090,15 @@ module minitia_std::dex { pair, init_metadata, 1000, - option::none(), + option::none() ); assert!( coin::balance(chain_addr, init_metadata) == 20000000 - 1000, - 4, + 4 ); assert!( coin::balance(chain_addr, usdc_metadata) == 80000000 + 996, - 5, + 5 ); // return 999 commission 3 // swap usdc to init @@ -2028,15 +2107,15 @@ module minitia_std::dex { pair, usdc_metadata, 1000, - option::none(), + option::none() ); assert!( coin::balance(chain_addr, init_metadata) == 20000000 - 1000 + 997, - 6, + 6 ); // return 1000 commission 3 assert!( coin::balance(chain_addr, usdc_metadata) == 80000000 + 996 - 1000, - 7, + 7 ); move_to( @@ -2044,8 +2123,8 @@ module minitia_std::dex { CoinCapsInit { burn_cap: initia_burn_cap, freeze_cap: initia_freeze_cap, - mint_cap: initia_mint_cap, - }, + mint_cap: initia_mint_cap + } ); move_to( @@ -2053,8 +2132,8 @@ module minitia_std::dex { CoinCapsUsdc { burn_cap: usdc_burn_cap, freeze_cap: usdc_freeze_cap, - mint_cap: usdc_mint_cap, - }, + mint_cap: usdc_mint_cap + } ); } @@ -2062,47 +2141,47 @@ module minitia_std::dex { fun get_weight_test() { let weights = Weights { weights_before: Weight { - coin_a_weight: decimal128::from_ratio(2, 10), - coin_b_weight: decimal128::from_ratio(8, 10), - timestamp: 1000, + coin_a_weight: bigdecimal::from_ratio_u64(2, 10), + coin_b_weight: bigdecimal::from_ratio_u64(8, 10), + timestamp: 1000 }, weights_after: Weight { - coin_a_weight: decimal128::from_ratio(8, 10), - coin_b_weight: decimal128::from_ratio(2, 10), - timestamp: 2000, - }, + coin_a_weight: bigdecimal::from_ratio_u64(8, 10), + coin_b_weight: bigdecimal::from_ratio_u64(2, 10), + timestamp: 2000 + } }; set_block_info(10, 1000); let (coin_a_weight, coin_b_weight) = get_weight(&weights); assert!( - coin_a_weight == decimal128::from_ratio(2, 10) - && coin_b_weight == decimal128::from_ratio(8, 10), - 0, + coin_a_weight == bigdecimal::from_ratio_u64(2, 10) + && coin_b_weight == bigdecimal::from_ratio_u64(8, 10), + 0 ); set_block_info(15, 1500); let (coin_a_weight, coin_b_weight) = get_weight(&weights); assert!( - coin_a_weight == decimal128::from_ratio(5, 10) - && coin_b_weight == decimal128::from_ratio(5, 10), - 1, + coin_a_weight == bigdecimal::from_ratio_u64(5, 10) + && coin_b_weight == bigdecimal::from_ratio_u64(5, 10), + 1 ); set_block_info(20, 2000); let (coin_a_weight, coin_b_weight) = get_weight(&weights); assert!( - coin_a_weight == decimal128::from_ratio(8, 10) - && coin_b_weight == decimal128::from_ratio(2, 10), - 2, + coin_a_weight == bigdecimal::from_ratio_u64(8, 10) + && coin_b_weight == bigdecimal::from_ratio_u64(2, 10), + 2 ); set_block_info(30, 3000); let (coin_a_weight, coin_b_weight) = get_weight(&weights); assert!( - coin_a_weight == decimal128::from_ratio(8, 10) - && coin_b_weight == decimal128::from_ratio(2, 10), - 3, + coin_a_weight == bigdecimal::from_ratio_u64(8, 10) + && coin_b_weight == bigdecimal::from_ratio_u64(2, 10), + 3 ); } @@ -2127,30 +2206,30 @@ module minitia_std::dex { coin::mint_to( &coin_a_mint_cap, chain_addr, - 100000000, + 100000000 ); coin::mint_to( &coin_b_mint_cap, chain_addr, - 100000000, + 100000000 ); coin::mint_to( &coin_c_mint_cap, chain_addr, - 100000000, + 100000000 ); create_pair_script( &chain, std::string::utf8(b"name"), std::string::utf8(b"SYMBOL1"), - decimal128::from_ratio(3, 1000), - decimal128::from_ratio(5, 10), - decimal128::from_ratio(5, 10), + bigdecimal::from_ratio_u64(3, 1000), + bigdecimal::from_ratio_u64(5, 10), + bigdecimal::from_ratio_u64(5, 10), a_metadata, b_metadata, 1, - 1, + 1 ); let lp_1_metadata = coin::metadata(chain_addr, string::utf8(b"SYMBOL1")); let pair_1 = object::convert(lp_1_metadata); @@ -2160,13 +2239,13 @@ module minitia_std::dex { &chain, std::string::utf8(b"name"), std::string::utf8(b"SYMBOL2"), - decimal128::from_ratio(3, 1000), - decimal128::from_ratio(5, 10), - decimal128::from_ratio(5, 10), + bigdecimal::from_ratio_u64(3, 1000), + bigdecimal::from_ratio_u64(5, 10), + bigdecimal::from_ratio_u64(5, 10), a_metadata, b_metadata, 1, - 1, + 1 ); let lp_2_metadata = coin::metadata(chain_addr, string::utf8(b"SYMBOL2")); let pair_2 = object::convert(lp_2_metadata); @@ -2176,13 +2255,13 @@ module minitia_std::dex { &chain, std::string::utf8(b"name"), std::string::utf8(b"SYMBOL3"), - decimal128::from_ratio(3, 1000), - decimal128::from_ratio(5, 10), - decimal128::from_ratio(5, 10), + bigdecimal::from_ratio_u64(3, 1000), + bigdecimal::from_ratio_u64(5, 10), + bigdecimal::from_ratio_u64(5, 10), a_metadata, c_metadata, 1, - 1, + 1 ); let lp_3_metadata = coin::metadata(chain_addr, string::utf8(b"SYMBOL3")); let pair_3 = object::convert(lp_3_metadata); @@ -2192,21 +2271,21 @@ module minitia_std::dex { &chain, std::string::utf8(b"name"), std::string::utf8(b"SYMBOL4"), - decimal128::from_ratio(3, 1000), - decimal128::from_ratio(5, 10), - decimal128::from_ratio(5, 10), + bigdecimal::from_ratio_u64(3, 1000), + bigdecimal::from_ratio_u64(5, 10), + bigdecimal::from_ratio_u64(5, 10), a_metadata, c_metadata, 1, - 1, + 1 ); let lp_4_metadata = coin::metadata(chain_addr, string::utf8(b"SYMBOL4")); let pair_4 = object::convert(lp_4_metadata); let pair_4_addr = object::object_address(&pair_4); let (_, timestamp) = get_block_info(); - let weight = decimal128::from_ratio(5, 10); - let swap_fee_rate = decimal128::from_ratio(3, 1000); + let weight = bigdecimal::from_ratio_u64(5, 10); + let swap_fee_rate = bigdecimal::from_ratio_u64(3, 1000); let weights = Weights { weights_before: Weight { coin_a_weight: weight, @@ -2224,7 +2303,7 @@ module minitia_std::dex { option::none(), option::none(), option::none(), - 10, + 10 ); assert!( res @@ -2234,30 +2313,31 @@ module minitia_std::dex { coin_b: b_addr, liquidity_token: pair_1_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: b_addr, liquidity_token: pair_2_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: c_addr, liquidity_token: pair_3_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: c_addr, liquidity_token: pair_4_addr, weights, - swap_fee_rate, - },], - 0, + swap_fee_rate + } + ], + 0 ); let res = @@ -2265,7 +2345,7 @@ module minitia_std::dex { option::some(a_addr), option::some(b_addr), option::some(pair_1_addr), - 10, + 10 ); assert!( res @@ -2275,23 +2355,24 @@ module minitia_std::dex { coin_b: b_addr, liquidity_token: pair_2_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: c_addr, liquidity_token: pair_3_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: c_addr, liquidity_token: pair_4_addr, weights, - swap_fee_rate, - },], - 1, + swap_fee_rate + } + ], + 1 ); let res = @@ -2299,7 +2380,7 @@ module minitia_std::dex { option::some(a_addr), option::some(a_addr), option::some(pair_1_addr), - 10, + 10 ); assert!( res @@ -2309,37 +2390,38 @@ module minitia_std::dex { coin_b: b_addr, liquidity_token: pair_1_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: b_addr, liquidity_token: pair_2_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: c_addr, liquidity_token: pair_3_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: c_addr, liquidity_token: pair_4_addr, weights, - swap_fee_rate, - },], - 2, + swap_fee_rate + } + ], + 2 ); let res = get_pairs( a_addr, b_addr, option::none(), - 10, + 10 ); assert!( res @@ -2349,23 +2431,24 @@ module minitia_std::dex { coin_b: b_addr, liquidity_token: pair_1_addr, weights, - swap_fee_rate, + swap_fee_rate }, PairResponse { coin_a: a_addr, coin_b: b_addr, liquidity_token: pair_2_addr, weights, - swap_fee_rate, - },], - 3, + swap_fee_rate + } + ], + 3 ); let res = get_pairs( a_addr, b_addr, option::some(pair_1_addr), - 10, + 10 ); assert!( res @@ -2375,9 +2458,10 @@ module minitia_std::dex { coin_b: b_addr, liquidity_token: pair_2_addr, weights, - swap_fee_rate, - },], - 3, + swap_fee_rate + } + ], + 3 ); } } diff --git a/minitia_stdlib/sources/event.move b/minitia_stdlib/sources/event.move index 3b2739d..dbc15f0 100644 --- a/minitia_stdlib/sources/event.move +++ b/minitia_stdlib/sources/event.move @@ -18,12 +18,12 @@ module minitia_std::event { #[test_only] struct TestEvent has copy, drop { - value: u64, + value: u64 } #[test_only] struct TestEvent2 has copy, drop { - value: u64, + value: u64 } #[test] diff --git a/minitia_stdlib/sources/fa/dispatchable_fungible_asset.move b/minitia_stdlib/sources/fa/dispatchable_fungible_asset.move index ea4955b..105529e 100644 --- a/minitia_stdlib/sources/fa/dispatchable_fungible_asset.move +++ b/minitia_stdlib/sources/fa/dispatchable_fungible_asset.move @@ -39,20 +39,20 @@ module minitia_std::dispatchable_fungible_asset { constructor_ref: &ConstructorRef, withdraw_function: Option, deposit_function: Option, - derived_balance_function: Option, + derived_balance_function: Option ) { fungible_asset::register_dispatch_functions( constructor_ref, withdraw_function, deposit_function, - derived_balance_function, + derived_balance_function ); let store_obj = &object::generate_signer(constructor_ref); move_to( store_obj, TransferRefStore { - transfer_ref: fungible_asset::generate_transfer_ref(constructor_ref), - }, + transfer_ref: fungible_asset::generate_transfer_ref(constructor_ref) + } ); } @@ -68,9 +68,7 @@ module minitia_std::dispatchable_fungible_asset { /// /// The semantics of deposit will be governed by the function specified in DispatchFunctionStore. public fun withdraw( - owner: &signer, - store: Object, - amount: u64, + owner: &signer, store: Object, amount: u64 ): FungibleAsset acquires TransferRefStore { fungible_asset::withdraw_sanity_check(owner, store, false); let func_opt = fungible_asset::withdraw_dispatch_function(store); @@ -82,12 +80,12 @@ module minitia_std::dispatchable_fungible_asset { store, amount, borrow_transfer_ref(store), - func, + func ); let end_balance = fungible_asset::balance(store); assert!( amount <= start_balance - end_balance, - error::aborted(EAMOUNT_MISMATCH), + error::aborted(EAMOUNT_MISMATCH) ); fa } else { @@ -108,7 +106,7 @@ module minitia_std::dispatchable_fungible_asset { store, fa, borrow_transfer_ref(store), - func, + func ) } else { fungible_asset::deposit_internal(object::object_address(&store), fa) @@ -121,7 +119,7 @@ module minitia_std::dispatchable_fungible_asset { sender: &signer, from: Object, to: Object, - amount: u64, + amount: u64 ) acquires TransferRefStore { let fa = withdraw(sender, from, amount); deposit(to, fa); @@ -174,28 +172,37 @@ module minitia_std::dispatchable_fungible_asset { } } - inline fun borrow_transfer_ref(metadata: Object): &TransferRef acquires TransferRefStore { + inline fun borrow_transfer_ref( + metadata: Object + ): &TransferRef acquires TransferRefStore { let metadata_addr = object::object_address(&fungible_asset::store_metadata(metadata)); assert!( exists(metadata_addr), - error::not_found(ESTORE_NOT_FOUND), + error::not_found(ESTORE_NOT_FOUND) ); &borrow_global(metadata_addr).transfer_ref } native fun dispatchable_withdraw( - store: Object, amount: u64, transfer_ref: &TransferRef, function: &FunctionInfo, + store: Object, + amount: u64, + transfer_ref: &TransferRef, + function: &FunctionInfo ): FungibleAsset; native fun dispatchable_deposit( store: Object, fa: FungibleAsset, transfer_ref: &TransferRef, - function: &FunctionInfo, + function: &FunctionInfo ); - native fun dispatchable_derived_balance(store: Object, function: &FunctionInfo,): u64; + native fun dispatchable_derived_balance( + store: Object, function: &FunctionInfo + ): u64; - native fun dispatchable_derived_supply(store: Object, function: &FunctionInfo,): Option; + native fun dispatchable_derived_supply( + store: Object, function: &FunctionInfo + ): Option; } diff --git a/minitia_stdlib/sources/fa/fungible_asset.move b/minitia_stdlib/sources/fa/fungible_asset.move index ad2b79b..f3f6bcc 100644 --- a/minitia_stdlib/sources/fa/fungible_asset.move +++ b/minitia_stdlib/sources/fa/fungible_asset.move @@ -97,7 +97,7 @@ module minitia_std::fungible_asset { struct Supply has key { current: u128, // option::none() means unlimited supply. - maximum: Option, + maximum: Option } /// Metadata of a Fungible asset @@ -115,7 +115,7 @@ module minitia_std::fungible_asset { /// asset. icon_uri: String, /// The Uniform Resource Identifier (uri) pointing to the website for the fungible asset. - project_uri: String, + project_uri: String } /// The store object that holds fungible assets of a specific type associated with an account. @@ -125,20 +125,20 @@ module minitia_std::fungible_asset { /// The balance of the fungible metadata. balance: u64, /// If true, owner transfer is disabled that only `TransferRef` can move in/out from this store. - frozen: bool, + frozen: bool } /// FungibleAsset can be passed into function for type safety and to guarantee a specific amount. /// FungibleAsset is ephemeral and cannot be stored directly. It must be deposited back into a store. struct FungibleAsset { metadata: Object, - amount: u64, + amount: u64 } struct DispatchFunctionStore has key { withdraw_function: Option, deposit_function: Option, - derived_balance_function: Option, + derived_balance_function: Option } struct DeriveSupply has key { @@ -171,7 +171,7 @@ module minitia_std::fungible_asset { struct DepositEvent has drop, store { store_addr: address, metadata_addr: address, - amount: u64, + amount: u64 } #[event] @@ -179,7 +179,7 @@ module minitia_std::fungible_asset { struct WithdrawEvent has drop, store { store_addr: address, metadata_addr: address, - amount: u64, + amount: u64 } #[event] @@ -187,21 +187,21 @@ module minitia_std::fungible_asset { struct FrozenEvent has drop, store { store_addr: address, metadata_addr: address, - frozen: bool, + frozen: bool } #[event] /// Emitted when fungible assets are burnt. struct BurnEvent has drop, store { metadata_addr: address, - amount: u64, + amount: u64 } #[event] /// Emitted when fungible assets are minted. struct MintEvent has drop, store { metadata_addr: address, - amount: u64, + amount: u64 } /// Make an existing object fungible by adding the Metadata resource. @@ -216,46 +216,46 @@ module minitia_std::fungible_asset { symbol: String, decimals: u8, icon_uri: String, - project_uri: String, + project_uri: String ): Object { assert!( !object::can_generate_delete_ref(constructor_ref), - error::invalid_argument(EOBJECT_IS_DELETABLE), + error::invalid_argument(EOBJECT_IS_DELETABLE) ); let metadata_object_signer = &object::generate_signer(constructor_ref); // metadata validations assert!( string::length(&name) <= MAX_NAME_LENGTH, - error::out_of_range(ENAME_TOO_LONG), + error::out_of_range(ENAME_TOO_LONG) ); assert!( string::length(&symbol) <= MAX_SYMBOL_LENGTH, - error::out_of_range(ESYMBOL_TOO_LONG), + error::out_of_range(ESYMBOL_TOO_LONG) ); assert!( decimals <= MAX_DECIMALS, - error::out_of_range(EDECIMALS_TOO_LARGE), + error::out_of_range(EDECIMALS_TOO_LARGE) ); assert!( string::length(&icon_uri) <= MAX_URI_LENGTH, - error::out_of_range(EURI_TOO_LONG), + error::out_of_range(EURI_TOO_LONG) ); assert!( string::length(&project_uri) <= MAX_URI_LENGTH, - error::out_of_range(EURI_TOO_LONG), + error::out_of_range(EURI_TOO_LONG) ); // store metadata move_to( metadata_object_signer, - Metadata { name, symbol, decimals, icon_uri, project_uri, }, + Metadata { name, symbol, decimals, icon_uri, project_uri } ); // store supply move_to( metadata_object_signer, - Supply { current: 0, maximum: maximum_supply }, + Supply { current: 0, maximum: maximum_supply } ); // return metadata object @@ -267,7 +267,7 @@ module minitia_std::fungible_asset { constructor_ref: &ConstructorRef, withdraw_function: Option, deposit_function: Option, - derived_balance_function: Option, + derived_balance_function: Option ) { // Verify that caller type matches callee type so wrongly typed function cannot be registered. option::for_each_ref( @@ -277,17 +277,17 @@ module minitia_std::fungible_asset { function_info::new_function_info_from_address( @minitia_std, string::utf8(b"dispatchable_fungible_asset"), - string::utf8(b"dispatchable_withdraw"), + string::utf8(b"dispatchable_withdraw") ); assert!( function_info::check_dispatch_type_compatibility( &dispatcher_withdraw_function_info, - withdraw_function, + withdraw_function ), - error::invalid_argument(EWITHDRAW_FUNCTION_SIGNATURE_MISMATCH), + error::invalid_argument(EWITHDRAW_FUNCTION_SIGNATURE_MISMATCH) ); - }, + } ); option::for_each_ref( @@ -297,17 +297,17 @@ module minitia_std::fungible_asset { function_info::new_function_info_from_address( @minitia_std, string::utf8(b"dispatchable_fungible_asset"), - string::utf8(b"dispatchable_deposit"), + string::utf8(b"dispatchable_deposit") ); // Verify that caller type matches callee type so wrongly typed function cannot be registered. assert!( function_info::check_dispatch_type_compatibility( &dispatcher_deposit_function_info, - deposit_function, + deposit_function ), - error::invalid_argument(EDEPOSIT_FUNCTION_SIGNATURE_MISMATCH), + error::invalid_argument(EDEPOSIT_FUNCTION_SIGNATURE_MISMATCH) ); - }, + } ); option::for_each_ref( @@ -317,26 +317,26 @@ module minitia_std::fungible_asset { function_info::new_function_info_from_address( @minitia_std, string::utf8(b"dispatchable_fungible_asset"), - string::utf8(b"dispatchable_derived_balance"), + string::utf8(b"dispatchable_derived_balance") ); // Verify that caller type matches callee type so wrongly typed function cannot be registered. assert!( function_info::check_dispatch_type_compatibility( &dispatcher_derived_balance_function_info, - balance_function, + balance_function ), error::invalid_argument( EDERIVED_BALANCE_FUNCTION_SIGNATURE_MISMATCH - ), + ) ); - }, + } ); register_dispatch_function_sanity_check(constructor_ref); assert!( !exists( object::address_from_constructor_ref(constructor_ref) ), - error::already_exists(EALREADY_REGISTERED), + error::already_exists(EALREADY_REGISTERED) ); let store_obj = &object::generate_signer(constructor_ref); @@ -347,8 +347,8 @@ module minitia_std::fungible_asset { DispatchFunctionStore { withdraw_function, deposit_function, - derived_balance_function, - }, + derived_balance_function + } ); } @@ -364,53 +364,50 @@ module minitia_std::fungible_asset { function_info::new_function_info_from_address( @minitia_std, string::utf8(b"dispatchable_fungible_asset"), - string::utf8(b"dispatchable_derived_supply"), + string::utf8(b"dispatchable_derived_supply") ); // Verify that caller type matches callee type so wrongly typed function cannot be registered. assert!( function_info::check_dispatch_type_compatibility( &function_info, - supply_function, + supply_function ), error::invalid_argument( EDERIVED_SUPPLY_FUNCTION_SIGNATURE_MISMATCH - ), + ) ); - }, + } ); register_dispatch_function_sanity_check(constructor_ref); assert!( !exists( object::address_from_constructor_ref(constructor_ref) ), - error::already_exists(EALREADY_REGISTERED), + error::already_exists(EALREADY_REGISTERED) ); let store_obj = &object::generate_signer(constructor_ref); // Store the overload function hook. - move_to( - store_obj, - DeriveSupply { dispatch_function }, - ); + move_to(store_obj, DeriveSupply { dispatch_function }); } /// Check the requirements for registering a dispatchable function. inline fun register_dispatch_function_sanity_check( - constructor_ref: &ConstructorRef, + constructor_ref: &ConstructorRef ) { // Cannot register hook for APT. assert!( object::address_from_constructor_ref(constructor_ref) != @minitia_std, - error::permission_denied(EAPT_NOT_DISPATCHABLE), + error::permission_denied(EAPT_NOT_DISPATCHABLE) ); assert!( !object::can_generate_delete_ref(constructor_ref), - error::invalid_argument(EOBJECT_IS_DELETABLE), + error::invalid_argument(EOBJECT_IS_DELETABLE) ); assert!( exists(object::address_from_constructor_ref(constructor_ref)), - error::not_found(EFUNGIBLE_METADATA_EXISTENCE), + error::not_found(EFUNGIBLE_METADATA_EXISTENCE) ); } @@ -547,7 +544,8 @@ module minitia_std::fungible_asset { /// /// If the store has not been created, we default to returning false so deposits can be sent to it. public fun is_frozen(store: Object): bool acquires FungibleStore { - store_exists(object::object_address(&store)) && borrow_store_resource(&store).frozen + store_exists(object::object_address(&store)) + && borrow_store_resource(&store).frozen } #[view] @@ -558,7 +556,9 @@ module minitia_std::fungible_asset { exists(metadata_addr) } - public fun deposit_dispatch_function(store: Object): Option acquires FungibleStore, DispatchFunctionStore { + public fun deposit_dispatch_function( + store: Object + ): Option acquires FungibleStore, DispatchFunctionStore { let fa_store = borrow_store_resource(&store); let metadata_addr = object::object_address(&fa_store.metadata); if (exists(metadata_addr)) { @@ -568,17 +568,22 @@ module minitia_std::fungible_asset { } } - fun has_deposit_dispatch_function(metadata: Object): bool acquires DispatchFunctionStore { + fun has_deposit_dispatch_function( + metadata: Object + ): bool acquires DispatchFunctionStore { let metadata_addr = object::object_address(&metadata); // Short circuit on APT for better perf - if (metadata_addr != @minitia_std && exists(metadata_addr)) { + if (metadata_addr != @minitia_std + && exists(metadata_addr)) { option::is_some( &borrow_global(metadata_addr).deposit_function ) } else { false } } - public fun withdraw_dispatch_function(store: Object): Option acquires FungibleStore, DispatchFunctionStore { + public fun withdraw_dispatch_function( + store: Object + ): Option acquires FungibleStore, DispatchFunctionStore { let fa_store = borrow_store_resource(&store); let metadata_addr = object::object_address(&fa_store.metadata); if (exists(metadata_addr)) { @@ -588,10 +593,13 @@ module minitia_std::fungible_asset { } } - fun has_withdraw_dispatch_function(metadata: Object): bool acquires DispatchFunctionStore { + fun has_withdraw_dispatch_function( + metadata: Object + ): bool acquires DispatchFunctionStore { let metadata_addr = object::object_address(&metadata); // Short circuit on APT for better perf - if (metadata_addr != @minitia_std && exists(metadata_addr)) { + if (metadata_addr != @minitia_std + && exists(metadata_addr)) { option::is_some( &borrow_global(metadata_addr).withdraw_function ) @@ -651,7 +659,7 @@ module minitia_std::fungible_asset { sender: &signer, from: Object, to: Object, - amount: u64, + amount: u64 ) acquires FungibleStore, DispatchFunctionStore { let fa = withdraw(sender, from, amount); deposit(to, fa); @@ -660,16 +668,12 @@ module minitia_std::fungible_asset { /// Allow an object to hold a store for fungible assets. /// Applications can use this to create multiple stores for isolating fungible assets for different purposes. public fun create_store( - constructor_ref: &ConstructorRef, metadata: Object, + constructor_ref: &ConstructorRef, metadata: Object ): Object { let store_obj = &object::generate_signer(constructor_ref); move_to( store_obj, - FungibleStore { - metadata: object::convert(metadata), - balance: 0, - frozen: false, - }, + FungibleStore { metadata: object::convert(metadata), balance: 0, frozen: false } ); object::object_from_constructor_ref(constructor_ref) @@ -678,16 +682,12 @@ module minitia_std::fungible_asset { /// Allow an object to hold a store for fungible assets. /// Applications can use this to create multiple stores for isolating fungible assets for different purposes. public fun create_store_with_extend_ref( - extend_ref: &ExtendRef, metadata: Object, + extend_ref: &ExtendRef, metadata: Object ): Object { let store_obj = &object::generate_signer_for_extending(extend_ref); move_to( store_obj, - FungibleStore { - metadata: object::convert(metadata), - balance: 0, - frozen: false, - }, + FungibleStore { metadata: object::convert(metadata), balance: 0, frozen: false } ); let obj_addr = object::address_from_extend_ref(extend_ref); @@ -702,24 +702,22 @@ module minitia_std::fungible_asset { move_from(addr); assert!( balance == 0, - error::permission_denied(EBALANCE_IS_NOT_ZERO), + error::permission_denied(EBALANCE_IS_NOT_ZERO) ); } /// Check the permission for withdraw operation. public(friend) fun withdraw_sanity_check( - owner: &signer, - store: Object, - abort_on_dispatch: bool, + owner: &signer, store: Object, abort_on_dispatch: bool ) acquires FungibleStore, DispatchFunctionStore { assert!( object::owns(store, signer::address_of(owner)), - error::permission_denied(ENOT_STORE_OWNER), + error::permission_denied(ENOT_STORE_OWNER) ); let fa_store = borrow_store_resource(&store); assert!( !abort_on_dispatch || !has_withdraw_dispatch_function(fa_store.metadata), - error::invalid_argument(EINVALID_DISPATCHABLE_OPERATIONS), + error::invalid_argument(EINVALID_DISPATCHABLE_OPERATIONS) ); assert!(!fa_store.frozen, error::permission_denied(ESTORE_IS_FROZEN)); } @@ -731,7 +729,7 @@ module minitia_std::fungible_asset { let fa_store = borrow_store_resource(&store); assert!( !abort_on_dispatch || !has_deposit_dispatch_function(fa_store.metadata), - error::invalid_argument(EINVALID_DISPATCHABLE_OPERATIONS), + error::invalid_argument(EINVALID_DISPATCHABLE_OPERATIONS) ); assert!(!fa_store.frozen, error::permission_denied(ESTORE_IS_FROZEN)); @@ -740,22 +738,22 @@ module minitia_std::fungible_asset { let store_addr = object::object_address(&store); assert!( !is_blocked_store_addr(store_addr), - error::invalid_argument(ECANNOT_DEPOSIT_TO_BLOCKED_ACCOUNT), + error::invalid_argument(ECANNOT_DEPOSIT_TO_BLOCKED_ACCOUNT) ); } /// Withdraw `amount` of the fungible asset from `store` by the owner. public fun withdraw( - owner: &signer, - store: Object, - amount: u64, + owner: &signer, store: Object, amount: u64 ): FungibleAsset acquires FungibleStore, DispatchFunctionStore { withdraw_sanity_check(owner, store, true); withdraw_internal(object::object_address(&store), amount) } /// Deposit `amount` of the fungible asset to `store`. - public fun deposit(store: Object, fa: FungibleAsset) acquires FungibleStore, DispatchFunctionStore { + public fun deposit( + store: Object, fa: FungibleAsset + ) acquires FungibleStore, DispatchFunctionStore { deposit_sanity_check(store, true); deposit_internal(object::object_address(&store), fa); } @@ -784,13 +782,11 @@ module minitia_std::fungible_asset { /// Enable/disable a store's ability to do direct transfers of the fungible asset. public fun set_frozen_flag( - ref: &TransferRef, - store: Object, - frozen: bool, + ref: &TransferRef, store: Object, frozen: bool ) acquires FungibleStore { assert!( ref.metadata == store_metadata(store), - error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH), + error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH) ); let metadata_addr = object::object_address(&ref.metadata); @@ -799,7 +795,7 @@ module minitia_std::fungible_asset { // cannot freeze module account store assert!( !is_module_account_store_addr(store_addr), - error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE), + error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE) ); borrow_global_mut(store_addr).frozen = frozen; @@ -810,10 +806,10 @@ module minitia_std::fungible_asset { /// Burns a fungible asset public fun burn(ref: &BurnRef, fa: FungibleAsset) acquires Supply { - let FungibleAsset { metadata, amount, } = fa; + let FungibleAsset { metadata, amount } = fa; assert!( ref.metadata == metadata, - error::invalid_argument(EBURN_REF_AND_FUNGIBLE_ASSET_MISMATCH), + error::invalid_argument(EBURN_REF_AND_FUNGIBLE_ASSET_MISMATCH) ); decrease_supply(metadata, amount); @@ -829,7 +825,7 @@ module minitia_std::fungible_asset { let metadata = ref.metadata; assert!( metadata == store_metadata(store), - error::invalid_argument(EBURN_REF_AND_STORE_MISMATCH), + error::invalid_argument(EBURN_REF_AND_STORE_MISMATCH) ); let store_addr = object::object_address(&store); @@ -837,7 +833,7 @@ module minitia_std::fungible_asset { // cannot burn module account funds assert!( !is_module_account_store_addr(store_addr), - error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE), + error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE) ); burn(ref, withdraw_internal(store_addr, amount)); @@ -849,14 +845,14 @@ module minitia_std::fungible_asset { ): FungibleAsset acquires FungibleStore { assert!( ref.metadata == store_metadata(store), - error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH), + error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH) ); // cannot withdraw module account funds let store_addr = object::object_address(&store); assert!( !is_module_account_store_addr(store_addr), - error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE), + error::invalid_argument(ECONNOT_MANIPULATE_MODULE_ACCOUNT_STORE) ); withdraw_internal(object::object_address(&store), amount) @@ -868,14 +864,14 @@ module minitia_std::fungible_asset { ) acquires FungibleStore { assert!( ref.metadata == fa.metadata, - error::invalid_argument(ETRANSFER_REF_AND_FUNGIBLE_ASSET_MISMATCH), + error::invalid_argument(ETRANSFER_REF_AND_FUNGIBLE_ASSET_MISMATCH) ); // cannot deposit to blocked account let store_addr = object::object_address(&store); assert!( !is_blocked_store_addr(store_addr), - error::invalid_argument(ECANNOT_DEPOSIT_TO_BLOCKED_ACCOUNT), + error::invalid_argument(ECANNOT_DEPOSIT_TO_BLOCKED_ACCOUNT) ); deposit_internal(object::object_address(&store), fa); @@ -886,7 +882,7 @@ module minitia_std::fungible_asset { transfer_ref: &TransferRef, from: Object, to: Object, - amount: u64, + amount: u64 ) acquires FungibleStore { let fa = withdraw_with_ref(transfer_ref, from, amount); deposit_with_ref(transfer_ref, to, fa); @@ -899,7 +895,7 @@ module minitia_std::fungible_asset { symbol: Option, decimals: Option, icon_uri: Option, - project_uri: Option, + project_uri: Option ) acquires Metadata { let metadata_address = object::object_address(&metadata_ref.metadata); let mutable_metadata = borrow_global_mut(metadata_address); @@ -929,7 +925,7 @@ module minitia_std::fungible_asset { sender: &signer, from: Object, to: Object, - amount: u64, + amount: u64 ) acquires FungibleStore, DispatchFunctionStore { let fa = withdraw(sender, from, amount); sudo_deposit(to, fa); @@ -943,7 +939,7 @@ module minitia_std::fungible_asset { ) acquires FungibleStore { assert!( !is_frozen(store), - error::invalid_argument(ESTORE_IS_FROZEN), + error::invalid_argument(ESTORE_IS_FROZEN) ); deposit_internal(object::object_address(&store), fa); @@ -952,17 +948,17 @@ module minitia_std::fungible_asset { /// Create a fungible asset with zero amount. /// This can be useful when starting a series of computations where the initial value is 0. public fun zero(metadata: Object): FungibleAsset { - FungibleAsset { metadata: object::convert(metadata), amount: 0, } + FungibleAsset { metadata: object::convert(metadata), amount: 0 } } /// Extract a given amount from the given fungible asset and return a new one. public fun extract(fungible_asset: &mut FungibleAsset, amount: u64): FungibleAsset { assert!( fungible_asset.amount >= amount, - error::invalid_argument(EINSUFFICIENT_BALANCE), + error::invalid_argument(EINSUFFICIENT_BALANCE) ); fungible_asset.amount = fungible_asset.amount - amount; - FungibleAsset { metadata: fungible_asset.metadata, amount, } + FungibleAsset { metadata: fungible_asset.metadata, amount } } /// "Merges" the two given fungible assets. The fungible asset passed in as `dst_fungible_asset` will have a value @@ -973,7 +969,7 @@ module minitia_std::fungible_asset { let FungibleAsset { metadata, amount } = src_fungible_asset; assert!( metadata == dst_fungible_asset.metadata, - error::invalid_argument(EFUNGIBLE_ASSET_MISMATCH), + error::invalid_argument(EFUNGIBLE_ASSET_MISMATCH) ); dst_fungible_asset.amount = dst_fungible_asset.amount + amount; } @@ -983,7 +979,7 @@ module minitia_std::fungible_asset { let FungibleAsset { amount, metadata: _ } = fungible_asset; assert!( amount == 0, - error::invalid_argument(EAMOUNT_IS_NOT_ZERO), + error::invalid_argument(EAMOUNT_IS_NOT_ZERO) ); } @@ -993,12 +989,12 @@ module minitia_std::fungible_asset { let FungibleAsset { metadata, amount } = fa; assert!( exists(store_addr), - error::not_found(EFUNGIBLE_STORE_EXISTENCE), + error::not_found(EFUNGIBLE_STORE_EXISTENCE) ); let store = borrow_global_mut(store_addr); assert!( metadata == store.metadata, - error::invalid_argument(EFUNGIBLE_ASSET_AND_STORE_MISMATCH), + error::invalid_argument(EFUNGIBLE_ASSET_AND_STORE_MISMATCH) ); if (amount == 0) return; @@ -1012,7 +1008,7 @@ module minitia_std::fungible_asset { /// Extract `amount` of the fungible asset from `store`. public(friend) fun withdraw_internal( - store_addr: address, amount: u64, + store_addr: address, amount: u64 ): FungibleAsset acquires FungibleStore { let store = borrow_global_mut(store_addr); let metadata = store.metadata; @@ -1020,7 +1016,7 @@ module minitia_std::fungible_asset { assert!( store.balance >= amount, - error::invalid_argument(EINSUFFICIENT_BALANCE), + error::invalid_argument(EINSUFFICIENT_BALANCE) ); store.balance = store.balance - amount; @@ -1038,14 +1034,14 @@ module minitia_std::fungible_asset { let metadata_address = object::object_address(&metadata); assert!( exists(metadata_address), - error::not_found(ESUPPLY_NOT_FOUND), + error::not_found(ESUPPLY_NOT_FOUND) ); let supply = borrow_global_mut(metadata_address); if (option::is_some(&supply.maximum)) { let max = *option::borrow_mut(&mut supply.maximum); assert!( max - supply.current >= (amount as u128), - error::out_of_range(EMAX_SUPPLY_EXCEEDED), + error::out_of_range(EMAX_SUPPLY_EXCEEDED) ) }; supply.current = supply.current + (amount as u128); @@ -1058,12 +1054,12 @@ module minitia_std::fungible_asset { let metadata_address = object::object_address(&metadata); assert!( exists(metadata_address), - error::not_found(ESUPPLY_NOT_FOUND), + error::not_found(ESUPPLY_NOT_FOUND) ); let supply = borrow_global_mut(metadata_address); assert!( supply.current >= (amount as u128), - error::invalid_state(ESUPPLY_UNDERFLOW), + error::invalid_state(ESUPPLY_UNDERFLOW) ); supply.current = supply.current - (amount as u128); } @@ -1087,12 +1083,16 @@ module minitia_std::fungible_asset { borrow_global(addr) } - inline fun borrow_fungible_metadata_mut(metadata: &Object): &mut Metadata acquires Metadata { + inline fun borrow_fungible_metadata_mut( + metadata: &Object + ): &mut Metadata acquires Metadata { let addr = object::object_address(metadata); borrow_global_mut(addr) } - inline fun borrow_store_resource(store: &Object): &FungibleStore acquires FungibleStore { + inline fun borrow_store_resource( + store: &Object + ): &FungibleStore acquires FungibleStore { borrow_global(object::object_address(store)) } @@ -1110,10 +1110,9 @@ module minitia_std::fungible_asset { } #[test_only] - public fun init_test_metadata(constructor_ref: &ConstructorRef) - : ( - MintRef, TransferRef, BurnRef, MutateMetadataRef - ) { + public fun init_test_metadata( + constructor_ref: &ConstructorRef + ): (MintRef, TransferRef, BurnRef, MutateMetadataRef) { add_fungibility( constructor_ref, option::some(100) /* max supply */, @@ -1123,7 +1122,7 @@ module minitia_std::fungible_asset { string::utf8( b"http://www.example.com/favicon.ico" ), - string::utf8(b"http://www.example.com"), + string::utf8(b"http://www.example.com") ); let mint_ref = generate_mint_ref(constructor_ref); let burn_ref = generate_burn_ref(constructor_ref); @@ -1133,10 +1132,9 @@ module minitia_std::fungible_asset { } #[test_only] - public fun create_fungible_asset(creator: &signer) - : ( - MintRef, TransferRef, BurnRef, MutateMetadataRef, Object - ) { + public fun create_fungible_asset( + creator: &signer + ): (MintRef, TransferRef, BurnRef, MutateMetadataRef, Object) { let (creator_ref, token_object) = create_test_token(creator); let (mint, transfer, burn, mutate_metadata) = init_test_metadata(&creator_ref); (mint, transfer, burn, mutate_metadata, object::convert(token_object)) @@ -1149,7 +1147,7 @@ module minitia_std::fungible_asset { let owner_addr = signer::address_of(owner); create_store( &object::create_object(owner_addr, true), - metadata, + metadata ) } @@ -1187,7 +1185,9 @@ module minitia_std::fungible_asset { } #[test(creator = @0xcafe, aaron = @0xface)] - fun test_e2e_basic_flow(creator: &signer, aaron: &signer,) acquires FungibleStore, Supply, DispatchFunctionStore, Metadata { + fun test_e2e_basic_flow( + creator: &signer, aaron: &signer + ) acquires FungibleStore, Supply, DispatchFunctionStore, Metadata { let (mint_ref, transfer_ref, burn_ref, mutate_metadata_ref, test_token) = create_fungible_asset(creator); let metadata = mint_ref.metadata; @@ -1212,7 +1212,7 @@ module minitia_std::fungible_asset { creator, creator_store, aaron_store, - 10, + 10 ); assert!(balance(creator_store) == 10, 5); assert!(balance(aaron_store) == 60, 6); @@ -1227,14 +1227,14 @@ module minitia_std::fungible_asset { option::some(string::utf8(b"mutated_symbol")), option::none(), option::none(), - option::none(), + option::none() ); assert!(name(metadata) == string::utf8(b"mutated_name"), 8); assert!(symbol(metadata) == string::utf8(b"mutated_symbol"), 9); assert!(decimals(metadata) == 0, 10); assert!( icon_uri(metadata) == string::utf8(b"http://www.example.com/favicon.ico"), - 11, + 11 ); assert!(project_uri(metadata) == string::utf8(b"http://www.example.com"), 12); } @@ -1252,7 +1252,7 @@ module minitia_std::fungible_asset { } #[test(creator = @0xcafe, aaron = @0xface)] - fun test_transfer_with_ref(creator: &signer, aaron: &signer,) acquires FungibleStore, Supply { + fun test_transfer_with_ref(creator: &signer, aaron: &signer) acquires FungibleStore, Supply { let (mint_ref, transfer_ref, _burn_ref, _mutate_metadata_ref, _) = create_fungible_asset(creator); let metadata = mint_ref.metadata; @@ -1267,7 +1267,7 @@ module minitia_std::fungible_asset { &transfer_ref, creator_store, aaron_store, - 80, + 80 ); assert!(balance(creator_store) == 20, 1); assert!(balance(aaron_store) == 80, 2); @@ -1304,7 +1304,7 @@ module minitia_std::fungible_asset { ) { let (_, _, _, _, metadata1) = create_fungible_asset(creator); let (_, _, _, _, metadata2) = create_fungible_asset(aaron); - let base = FungibleAsset { metadata: metadata1, amount: 1, }; + let base = FungibleAsset { metadata: metadata1, amount: 1 }; let addon = FungibleAsset { metadata: metadata2, amount: 1 }; merge(&mut base, addon); let FungibleAsset { metadata: _, amount: _ } = base; @@ -1325,13 +1325,13 @@ module minitia_std::fungible_asset { 10, 0, 3, - false, + false ); set_frozen_flag( &transfer_ref, module_acc_store, - true, + true ); } @@ -1350,7 +1350,7 @@ module minitia_std::fungible_asset { 10, 0, 3, - false, + false ); let fa = mint(&mint_ref, 100); @@ -1373,7 +1373,7 @@ module minitia_std::fungible_asset { 10, 0, 3, - false, + false ); let fa = mint(&mint_ref, 100); @@ -1397,7 +1397,7 @@ module minitia_std::fungible_asset { 10, 0, 3, - true, + true ); let fa = mint(&mint_ref, 100); @@ -1419,7 +1419,7 @@ module minitia_std::fungible_asset { 10, 0, 3, - true, + true ); let fa = mint(&mint_ref, 100); diff --git a/minitia_stdlib/sources/fa/primary_fungible_store.move b/minitia_stdlib/sources/fa/primary_fungible_store.move index 7e779cf..ce227d7 100644 --- a/minitia_stdlib/sources/fa/primary_fungible_store.move +++ b/minitia_stdlib/sources/fa/primary_fungible_store.move @@ -38,25 +38,28 @@ module minitia_std::primary_fungible_store { /// stores for users with deterministic addresses so that users can easily deposit/withdraw/transfer fungible /// assets. struct DeriveRefPod has key { - metadata_derive_ref: DeriveRef, + metadata_derive_ref: DeriveRef } struct ModuleStore has key { issuers: Table
, - user_stores: Table
>, + user_stores: Table
> } #[event] struct PrimaryStoreCreatedEvent has drop, store { owner_addr: address, store_addr: address, - metadata_addr: address, + metadata_addr: address } fun init_module(chain: &signer) { move_to( chain, - ModuleStore { issuers: table::new(), user_stores: table::new(), }, + ModuleStore { + issuers: table::new(), + user_stores: table::new() + } ) } @@ -70,7 +73,7 @@ module minitia_std::primary_fungible_store { symbol: String, decimals: u8, icon_uri: String, - project_uri: String, + project_uri: String ) acquires ModuleStore { fungible_asset::add_fungibility( constructor_ref, @@ -79,7 +82,7 @@ module minitia_std::primary_fungible_store { symbol, decimals, icon_uri, - project_uri, + project_uri ); let metadata = object::object_from_constructor_ref(constructor_ref); @@ -87,8 +90,8 @@ module minitia_std::primary_fungible_store { move_to( metadata_signer, DeriveRefPod { - metadata_derive_ref: object::generate_derive_ref(constructor_ref), - }, + metadata_derive_ref: object::generate_derive_ref(constructor_ref) + } ); // record issuers for cosmos side query @@ -97,14 +100,14 @@ module minitia_std::primary_fungible_store { table::add( &mut module_store.issuers, object::object_address(&metadata), - object::owner(metadata), + object::owner(metadata) ); } } /// Ensure that the primary store object for the given address exists. If it doesn't, create it. public fun ensure_primary_store_exists( - owner: address, metadata: Object, + owner: address, metadata: Object ): Object acquires DeriveRefPod, ModuleStore { if (!primary_store_exists(owner, metadata)) { create_primary_store(owner, metadata) @@ -115,7 +118,7 @@ module minitia_std::primary_fungible_store { /// Create a primary store object to hold fungible asset for the given address. public fun create_primary_store( - owner_addr: address, metadata: Object, + owner_addr: address, metadata: Object ): Object acquires DeriveRefPod, ModuleStore { let metadata_addr = object::object_address(&metadata); object::address_to_object(metadata_addr); @@ -135,13 +138,13 @@ module minitia_std::primary_fungible_store { if (exists(@minitia_std)) { let module_store = borrow_global_mut(@minitia_std); if (!table::contains( - &module_store.user_stores, - owner_addr, - )) { + &module_store.user_stores, + owner_addr + )) { table::add( &mut module_store.user_stores, owner_addr, - table::new(), + table::new() ); }; @@ -149,14 +152,12 @@ module minitia_std::primary_fungible_store { table::add( user_stores, metadata_addr, - store_addr, + store_addr ); }; // emit store created event - event::emit( - PrimaryStoreCreatedEvent { owner_addr, store_addr, metadata_addr, }, - ); + event::emit(PrimaryStoreCreatedEvent { owner_addr, store_addr, metadata_addr }); store } @@ -166,7 +167,7 @@ module minitia_std::primary_fungible_store { let module_store = borrow_global(@minitia_std); *table::borrow( &module_store.issuers, - object::object_address(&metadata), + object::object_address(&metadata) ) } @@ -181,8 +182,8 @@ module minitia_std::primary_fungible_store { #[view] /// Get the primary store object for the given account. - public fun primary_store(owner: address, metadata: Object) - : Object { + public fun primary_store(owner: address, metadata: Object): + Object { let store = primary_store_address(owner, metadata); object::address_to_object(store) } @@ -214,9 +215,7 @@ module minitia_std::primary_fungible_store { #[view] /// Get the balances of `account`'s primary store for all fungible assets. public fun balances( - account: address, - start_after: Option
, - limit: u8, + account: address, start_after: Option
, limit: u8 ): (vector>, vector) acquires ModuleStore { let module_store = borrow_global(@minitia_std); let account_stores = table::borrow(&module_store.user_stores, account); @@ -224,14 +223,14 @@ module minitia_std::primary_fungible_store { account_stores, option::none(), start_after, - 2, + 2 ); let metadata_vec: vector> = vector[]; let balance_vec: vector = vector[]; while (table::prepare(iter) - && vector::length(&balance_vec) < (limit as u64)) { + && vector::length(&balance_vec) < (limit as u64)) { let (metadata_addr, store_addr) = table::next(iter); let metadata = object::address_to_object(metadata_addr); let store = object::address_to_object(*store_addr); @@ -239,7 +238,7 @@ module minitia_std::primary_fungible_store { vector::push_back(&mut metadata_vec, metadata); vector::push_back( &mut balance_vec, - fungible_asset::balance(store), + fungible_asset::balance(store) ); }; @@ -249,7 +248,9 @@ module minitia_std::primary_fungible_store { /// Deposit fungible asset `fa` to the given account's primary store. /// /// This function is only callable by the chain. - public(friend) fun sudo_deposit(owner: address, fa: FungibleAsset) acquires DeriveRefPod, ModuleStore { + public(friend) fun sudo_deposit( + owner: address, fa: FungibleAsset + ) acquires DeriveRefPod, ModuleStore { let metadata = fungible_asset::asset_metadata(&fa); let store = ensure_primary_store_exists(owner, metadata); fungible_asset::sudo_deposit(store, fa); @@ -267,7 +268,7 @@ module minitia_std::primary_fungible_store { sender: &signer, metadata: Object, recipient: address, - amount: u64, + amount: u64 ) acquires DeriveRefPod, ModuleStore { let sender_store = ensure_primary_store_exists(signer::address_of(sender), metadata); @@ -276,7 +277,7 @@ module minitia_std::primary_fungible_store { sender, sender_store, recipient_store, - amount, + amount ); } @@ -309,7 +310,7 @@ module minitia_std::primary_fungible_store { sender: &signer, metadata: Object, recipient: address, - amount: u64, + amount: u64 ) acquires DeriveRefPod, ModuleStore { let sender_store = ensure_primary_store_exists(signer::address_of(sender), metadata); @@ -331,7 +332,7 @@ module minitia_std::primary_fungible_store { metadata: Object, recipient: address, amount: u64, - expected: u64, + expected: u64 ) acquires DeriveRefPod, ModuleStore { let sender_store = ensure_primary_store_exists(signer::address_of(sender), metadata); @@ -341,7 +342,7 @@ module minitia_std::primary_fungible_store { sender_store, recipient_store, amount, - expected, + expected ); } @@ -350,7 +351,7 @@ module minitia_std::primary_fungible_store { let primary_store = ensure_primary_store_exists( owner, - fungible_asset::mint_ref_metadata(mint_ref), + fungible_asset::mint_ref_metadata(mint_ref) ); fungible_asset::mint_to(mint_ref, primary_store, amount); @@ -366,7 +367,7 @@ module minitia_std::primary_fungible_store { let primary_store = primary_store( owner, - fungible_asset::burn_ref_metadata(burn_ref), + fungible_asset::burn_ref_metadata(burn_ref) ); fungible_asset::burn_from(burn_ref, primary_store, amount); } @@ -378,7 +379,7 @@ module minitia_std::primary_fungible_store { let primary_store = ensure_primary_store_exists( owner, - fungible_asset::transfer_ref_metadata(transfer_ref), + fungible_asset::transfer_ref_metadata(transfer_ref) ); fungible_asset::set_frozen_flag(transfer_ref, primary_store, frozen); } @@ -390,12 +391,12 @@ module minitia_std::primary_fungible_store { let from_primary_store = primary_store( owner, - fungible_asset::transfer_ref_metadata(transfer_ref), + fungible_asset::transfer_ref_metadata(transfer_ref) ); fungible_asset::withdraw_with_ref( transfer_ref, from_primary_store, - amount, + amount ) } @@ -406,7 +407,7 @@ module minitia_std::primary_fungible_store { let from_primary_store = ensure_primary_store_exists( owner, - fungible_asset::transfer_ref_metadata(transfer_ref), + fungible_asset::transfer_ref_metadata(transfer_ref) ); fungible_asset::deposit_with_ref(transfer_ref, from_primary_store, fa); @@ -426,18 +427,18 @@ module minitia_std::primary_fungible_store { let from_primary_store = primary_store( from, - fungible_asset::transfer_ref_metadata(transfer_ref), + fungible_asset::transfer_ref_metadata(transfer_ref) ); let to_primary_store = ensure_primary_store_exists( to, - fungible_asset::transfer_ref_metadata(transfer_ref), + fungible_asset::transfer_ref_metadata(transfer_ref) ); fungible_asset::transfer_with_ref( transfer_ref, from_primary_store, to_primary_store, - amount, + amount ); // create cosmos side account @@ -475,7 +476,7 @@ module minitia_std::primary_fungible_store { string::utf8(b"@T"), 0, string::utf8(b"http://example.com/icon"), - string::utf8(b"http://example.com"), + string::utf8(b"http://example.com") ); let mint_ref = generate_mint_ref(constructor_ref); let burn_ref = generate_burn_ref(constructor_ref); @@ -491,11 +492,11 @@ module minitia_std::primary_fungible_store { let aaron_address = signer::address_of(aaron); assert!( !primary_store_exists(creator_address, metadata), - 1, + 1 ); assert!( !primary_store_exists(aaron_address, metadata), - 2, + 2 ); assert!(balance(creator_address, metadata) == 0, 3); assert!(balance(aaron_address, metadata) == 0, 4); @@ -505,16 +506,16 @@ module minitia_std::primary_fungible_store { ensure_primary_store_exists(aaron_address, metadata); assert!( primary_store_exists(creator_address, metadata), - 7, + 7 ); assert!( primary_store_exists(aaron_address, metadata), - 8, + 8 ); } #[test(creator = @0xcafe, aaron = @0xface)] - fun test_basic_flow(creator: &signer, aaron: &signer,) acquires DeriveRefPod, ModuleStore { + fun test_basic_flow(creator: &signer, aaron: &signer) acquires DeriveRefPod, ModuleStore { let (creator_ref, metadata) = create_test_token(creator); let (mint_ref, transfer_ref, burn_ref) = init_test_metadata_with_primary_store_enabled(&creator_ref); @@ -536,7 +537,7 @@ module minitia_std::primary_fungible_store { &transfer_ref, aaron_address, creator_address, - 20, + 20 ); set_frozen_flag(&transfer_ref, aaron_address, false); assert!(!is_frozen(aaron_address, metadata), 6); diff --git a/minitia_stdlib/sources/fixed_point64.move b/minitia_stdlib/sources/fixed_point64.move index 3c310b9..af2e0bf 100644 --- a/minitia_stdlib/sources/fixed_point64.move +++ b/minitia_stdlib/sources/fixed_point64.move @@ -17,6 +17,7 @@ module minitia_std::fixed_point64 { } const MAX_U128: u256 = 340282366920938463463374607431768211455; + const MAX_U64: u128 = 18446744073709551615; /// The denominator provided was zero const EDENOMINATOR: u64 = 0x10001; @@ -28,6 +29,86 @@ module minitia_std::fixed_point64 { const EDIVISION_BY_ZERO: u64 = 0x10004; /// The computed ratio when converting to a `FixedPoint64` would be unrepresentable const ERATIO_OUT_OF_RANGE: u64 = 0x20005; + /// Abort code on calculation result is negative. + const ENEGATIVE_RESULT: u64 = 0x10006; + + public fun one(): FixedPoint64 { + create_from_raw_value(1 << 64) + } + + public fun zero(): FixedPoint64 { + create_from_raw_value(0) + } + + public fun rev(self: FixedPoint64): FixedPoint64 { + create_from_raw_value(((1u256 << 128) / (get_raw_value(self) as u256) as u128)) + } + + /// Returns self - y. self must be not less than y. + public fun sub(self: FixedPoint64, y: FixedPoint64): FixedPoint64 { + let x_raw = get_raw_value(self); + let y_raw = get_raw_value(y); + assert!(x_raw >= y_raw, ENEGATIVE_RESULT); + create_from_raw_value(x_raw - y_raw) + } + + public fun sub_u64(self: FixedPoint64, y: u64): FixedPoint64 { + sub_u128(self, (y as u128)) + } + + public fun sub_u128(self: FixedPoint64, y: u128): FixedPoint64 { + let x_raw = (get_raw_value(self) as u256); + let y_raw = (y as u256) << 64; + assert!(x_raw >= y_raw, ENEGATIVE_RESULT); + create_from_raw_value(((x_raw - y_raw) as u128)) + } + + spec sub { + pragma opaque; + aborts_if self.value < y.value with ENEGATIVE_RESULT; + ensures result.value == self.value - y.value; + } + + /// Returns self + y. The result cannot be greater than MAX_U128. + public fun add(self: FixedPoint64, y: FixedPoint64): FixedPoint64 { + let x_raw = get_raw_value(self); + let y_raw = get_raw_value(y); + let result = (x_raw as u256) + (y_raw as u256); + assert!(result <= MAX_U128, ERATIO_OUT_OF_RANGE); + create_from_raw_value((result as u128)) + } + + public fun add_u64(self: FixedPoint64, y: u64): FixedPoint64 { + add_u128(self, (y as u128)) + } + + public fun add_u128(self: FixedPoint64, y: u128): FixedPoint64 { + let x_raw = (get_raw_value(self) as u256); + let y_raw = (y as u256) << 64; + let result = x_raw + y_raw; + assert!(result <= MAX_U128, ERATIO_OUT_OF_RANGE); + create_from_raw_value((result as u128)) + } + + spec add { + pragma opaque; + aborts_if (self.value as u256) + (y.value as u256) > MAX_U128 with ERATIO_OUT_OF_RANGE; + ensures result.value == self.value + y.value; + } + + public fun multiply(self: FixedPoint64, y: FixedPoint64): FixedPoint64 { + let x_raw = get_raw_value(self); + let y_raw = get_raw_value(y); + let result = ((x_raw as u256) * (y_raw as u256)) >> 64; + assert!(result <= MAX_U128, EMULTIPLICATION); + create_from_raw_value((result as u128)) + } + + public fun multiply_u64(val: u64, multiplier: FixedPoint64): u64 { + let res = multiply_u128((val as u128), multiplier); + assert!(res <= MAX_U64, EMULTIPLICATION); + (res as u64) + } /// Multiply a u128 integer by a fixed-point number, truncating any /// fractional part of the product. This will abort if the product @@ -61,6 +142,29 @@ module minitia_std::fixed_point64 { (val * multiplier.value) >> 64 } + public fun divide(self: FixedPoint64, divisor: FixedPoint64): FixedPoint64 { + // Check for division by zero. + assert!(divisor.value != 0, EDIVISION_BY_ZERO); + // Perform the division with 256 bits to avoid losing accuracy. + let result = ((self.value as u256) << 64) / (divisor.value as u256); + assert!(result <= MAX_U128, EDIVISION); + create_from_raw_value((result as u128)) + } + + /// Divide a u64 integer by a fixed-point number, truncating any + /// fractional part of the quotient. This will abort if the divisor + /// is zero or if the quotient overflows. + public fun divide_u64(val: u64, divisor: FixedPoint64): u64 { + let res = divide_u128((val as u128), divisor); + assert!(res <= MAX_U64, EDIVISION); + (res as u64) + } + + /// Divide a fixed-point number by a u64 integer. + public fun divide_by_u64(val: FixedPoint64, divisor: u64): FixedPoint64 { + divide_by_u128(val, (divisor as u128)) + } + /// Divide a u128 integer by a fixed-point number, truncating any /// fractional part of the quotient. This will abort if the divisor /// is zero or if the quotient overflows. @@ -78,6 +182,13 @@ module minitia_std::fixed_point64 { (quotient as u128) } + /// Divide a fixed-point number by a u128 integer. + public fun divide_by_u128(val: FixedPoint64, divisor: u128): FixedPoint64 { + // Check for division by zero. + assert!(divisor != 0, EDIVISION_BY_ZERO); + create_from_raw_value(get_raw_value(val) / divisor) + } + spec divide_u128 { pragma opaque; include DivideAbortsIf; @@ -112,10 +223,7 @@ module minitia_std::fixed_point64 { let scaled_numerator = (numerator as u256) << 64; assert!(denominator != 0, EDENOMINATOR); let quotient = scaled_numerator / (denominator as u256); - assert!( - quotient != 0 || numerator == 0, - ERATIO_OUT_OF_RANGE, - ); + assert!(quotient != 0 || numerator == 0, ERATIO_OUT_OF_RANGE); // Return the quotient as a fixed-point number. We first need to check whether the cast // can succeed. assert!(quotient <= MAX_U128, ERATIO_OUT_OF_RANGE); @@ -124,7 +232,7 @@ module minitia_std::fixed_point64 { spec create_from_rational { pragma opaque; - pragma verify = false; // TODO: set to false because of timeout (property proved). + pragma verify_duration_estimate = 1000; // TODO: set because of timeout (property proved). include CreateFromRationalAbortsIf; ensures result == spec_create_from_rational(numerator, denominator); } @@ -141,7 +249,9 @@ module minitia_std::fixed_point64 { } spec fun spec_create_from_rational(numerator: num, denominator: num): FixedPoint64 { - FixedPoint64 { value: (numerator << 128) / (denominator << 64) } + FixedPoint64 { + value: (numerator << 128) / (denominator << 64) + } } /// Create a fixedpoint value from a raw value. @@ -158,13 +268,13 @@ module minitia_std::fixed_point64 { /// Accessor for the raw u128 value. Other less common operations, such as /// adding or subtracting FixedPoint64 values, can be done using the raw /// values directly. - public fun get_raw_value(num: FixedPoint64): u128 { - num.value + public fun get_raw_value(self: FixedPoint64): u128 { + self.value } /// Returns true if the ratio is zero. - public fun is_zero(num: FixedPoint64): bool { - num.value == 0 + public fun is_zero(self: FixedPoint64): bool { + self.value == 0 } /// Returns the smaller of the two FixedPoint64 numbers. @@ -201,6 +311,106 @@ module minitia_std::fixed_point64 { else { num2 } } + /// Returns true if self <= num2 + public fun less_or_equal(self: FixedPoint64, num2: FixedPoint64): bool { + self.value <= num2.value + } + + spec less_or_equal { + pragma opaque; + aborts_if false; + ensures result == spec_less_or_equal(self, num2); + } + + spec fun spec_less_or_equal(self: FixedPoint64, num2: FixedPoint64): bool { + self.value <= num2.value + } + + /// Returns true if self < num2 + public fun less(self: FixedPoint64, num2: FixedPoint64): bool { + self.value < num2.value + } + + spec less { + pragma opaque; + aborts_if false; + ensures result == spec_less(self, num2); + } + + spec fun spec_less(self: FixedPoint64, num2: FixedPoint64): bool { + self.value < num2.value + } + + /// Returns true if self >= num2 + public fun greater_or_equal(self: FixedPoint64, num2: FixedPoint64): bool { + self.value >= num2.value + } + + spec greater_or_equal { + pragma opaque; + aborts_if false; + ensures result == spec_greater_or_equal(self, num2); + } + + spec fun spec_greater_or_equal(self: FixedPoint64, num2: FixedPoint64): bool { + self.value >= num2.value + } + + /// Returns true if self > num2 + public fun greater(self: FixedPoint64, num2: FixedPoint64): bool { + self.value > num2.value + } + + spec greater { + pragma opaque; + aborts_if false; + ensures result == spec_greater(self, num2); + } + + spec fun spec_greater(self: FixedPoint64, num2: FixedPoint64): bool { + self.value > num2.value + } + + /// Returns true if self = num2 + public fun equal(self: FixedPoint64, num2: FixedPoint64): bool { + self.value == num2.value + } + + spec equal { + pragma opaque; + aborts_if false; + ensures result == spec_equal(self, num2); + } + + spec fun spec_equal(self: FixedPoint64, num2: FixedPoint64): bool { + self.value == num2.value + } + + /// Returns true if self almost equals to num2, which means abs(num1-num2) <= precision + public fun almost_equal( + self: FixedPoint64, num2: FixedPoint64, precision: FixedPoint64 + ): bool { + if (self.value > num2.value) { + (self.value - num2.value <= precision.value) + } else { + (num2.value - self.value <= precision.value) + } + } + + spec almost_equal { + pragma opaque; + aborts_if false; + ensures result == spec_almost_equal(self, num2, precision); + } + + spec fun spec_almost_equal(self: FixedPoint64, num2: FixedPoint64, precision: FixedPoint64): bool { + if (self.value > num2.value) { + (self.value - num2.value <= precision.value) + } else { + (num2.value - self.value <= precision.value) + } + } + /// Create a fixedpoint value from a u128 value. public fun create_from_u128(val: u128): FixedPoint64 { let value = (val as u256) << 64; @@ -225,29 +435,29 @@ module minitia_std::fixed_point64 { } /// Returns the largest integer less than or equal to a given number. - public fun floor(num: FixedPoint64): u128 { - num.value >> 64 + public fun floor(self: FixedPoint64): u128 { + self.value >> 64 } spec floor { pragma opaque; aborts_if false; - ensures result == spec_floor(num); + ensures result == spec_floor(self); } - spec fun spec_floor(val: FixedPoint64): u128 { - let fractional = val.value % (1 << 64); + spec fun spec_floor(self: FixedPoint64): u128 { + let fractional = self.value % (1 << 64); if (fractional == 0) { - val.value >> 64 + self.value >> 64 } else { - (val.value - fractional) >> 64 + (self.value - fractional) >> 64 } } /// Rounds up the given FixedPoint64 to the next largest integer. - public fun ceil(num: FixedPoint64): u128 { - let floored_num = floor(num) << 64; - if (num.value == floored_num) { + public fun ceil(self: FixedPoint64): u128 { + let floored_num = floor(self) << 64; + if (self.value == floored_num) { return floored_num >> 64 }; let val = ((floored_num as u256) + (1 << 64)); @@ -255,48 +465,48 @@ module minitia_std::fixed_point64 { } spec ceil { - /// TODO: worked in the past but started to time out since last z3 update - pragma verify = false; + // TODO: set because of timeout (property proved). + pragma verify_duration_estimate = 1000; pragma opaque; aborts_if false; - ensures result == spec_ceil(num); + ensures result == spec_ceil(self); } - spec fun spec_ceil(val: FixedPoint64): u128 { - let fractional = val.value % (1 << 64); + spec fun spec_ceil(self: FixedPoint64): u128 { + let fractional = self.value % (1 << 64); let one = 1 << 64; if (fractional == 0) { - val.value >> 64 + self.value >> 64 } else { - (val.value - fractional + one) >> 64 + (self.value - fractional + one) >> 64 } } /// Returns the value of a FixedPoint64 to the nearest integer. - public fun round(num: FixedPoint64): u128 { - let floored_num = floor(num) << 64; + public fun round(self: FixedPoint64): u128 { + let floored_num = floor(self) << 64; let boundary = floored_num + ((1 << 64) / 2); - if (num.value < boundary) { + if (self.value < boundary) { floored_num >> 64 } else { - ceil(num) + ceil(self) } } spec round { pragma opaque; aborts_if false; - ensures result == spec_round(num); + ensures result == spec_round(self); } - spec fun spec_round(val: FixedPoint64): u128 { - let fractional = val.value % (1 << 64); + spec fun spec_round(self: FixedPoint64): u128 { + let fractional = self.value % (1 << 64); let boundary = (1 << 64) / 2; let one = 1 << 64; if (fractional < boundary) { - (val.value - fractional) >> 64 + (self.value - fractional) >> 64 } else { - (val.value - fractional + one) >> 64 + (self.value - fractional + one) >> 64 } } @@ -307,4 +517,172 @@ module minitia_std::fixed_point64 { spec module { pragma aborts_if_is_strict; } + + #[test] + public entry fun test_sub() { + let x = create_from_rational(9, 7); + let y = create_from_rational(1, 3); + let result = sub(x, y); + // 9/7 - 1/3 = 20/21 + let expected_result = create_from_rational(20, 21); + assert_approx_the_same( + (get_raw_value(result) as u256), + (get_raw_value(expected_result) as u256), + 16 + ); + } + + #[test] + #[expected_failure(abort_code = 0x10006, location = Self)] + public entry fun test_sub_should_abort() { + let x = create_from_rational(1, 3); + let y = create_from_rational(9, 7); + let _ = sub(x, y); + } + + #[test_only] + /// For functions that approximate a value it's useful to test a value is close + /// to the most correct value up to last digit + fun assert_approx_the_same(x: u256, y: u256, precission: u128) { + if (x < y) { + let tmp = x; + x = y; + y = tmp; + }; + let mult = 1u256; + let n = 10u256; + while (precission > 0) { + if (precission % 2 == 1) { + mult = mult * n; + }; + precission = precission / 2; + n = n * n; + }; + assert!((x - y) * mult < x, 0); + } + + #[test] + public entry fun test_div() { + let x = create_from_rational(9, 7); + let y = create_from_rational(1, 3); + let result = divide(x, y); + // 9/7 / 1/3 = 27/7 + let expected_result = create_from_rational(27, 7); + assert_approx_the_same( + (get_raw_value(result) as u256), + (get_raw_value(expected_result) as u256), + 16 + ); + } + + #[test] + public entry fun test_div_u64() { + let x = create_from_rational(9, 7); + let y = 3u64; + let result = divide_u64(y, x); + // 3 / 9/7 = 21/9 + let expected_result = create_from_rational(21, 9); + assert_approx_the_same( + (result as u256), + (get_raw_value(expected_result) as u256) >> 64, + 16 + ); + } + + #[test] + public entry fun test_div_u128() { + let x = create_from_rational(9, 7); + let y = 3u128; + let result = divide_u128(y, x); + // 3 / 9/7 = 21/9 + let expected_result = create_from_rational(21, 9); + assert_approx_the_same( + (result as u256), + (get_raw_value(expected_result) as u256) >> 64, + 16 + ); + } + + #[test] + public entry fun test_multiply() { + let x = create_from_rational(9, 7); + let y = create_from_rational(1, 3); + let result = multiply(x, y); + // 9/7 * 1/3 = 3/7 + let expected_result = create_from_rational(3, 7); + assert_approx_the_same( + (get_raw_value(result) as u256), + (get_raw_value(expected_result) as u256), + 16 + ); + } + + #[test] + public entry fun test_multiply_u64() { + let x = create_from_rational(9, 7); + let y = 3u64; + let result = multiply_u64(y, x); + // 3 * 9/7 = 27/7 + let expected_result = create_from_rational(27, 7); + assert_approx_the_same( + (result as u256), + (get_raw_value(expected_result) as u256) >> 64, + 16 + ); + } + + #[test] + public entry fun test_multiply_u128() { + let x = create_from_rational(9, 7); + let y = 3u128; + let result = multiply_u128(y, x); + // 3 * 9/7 = 27/7 + let expected_result = create_from_rational(27, 7); + assert_approx_the_same( + (result as u256), + (get_raw_value(expected_result) as u256) >> 64, + 16 + ); + } + + #[test] + public entry fun test_rev() { + let x = create_from_rational(9, 7); + let result = rev(x); + // 1 / 9/7 = 7/9 + let expected_result = create_from_rational(7, 9); + assert_approx_the_same( + (get_raw_value(result) as u256), + (get_raw_value(expected_result) as u256), + 16 + ); + } + + #[test] + public entry fun test_divide_by_u64() { + let x = create_from_rational(9, 7); + let y = 3u64; + let result = divide_by_u64(x, y); + // 9/7 / 3 = 3/7 + let expected_result = create_from_rational(3, 7); + assert_approx_the_same( + (get_raw_value(result) as u256), + (get_raw_value(expected_result) as u256), + 16 + ); + } + + #[test] + public entry fun test_divide_by_u128() { + let x = create_from_rational(9, 7); + let y = 3u128; + let result = divide_by_u128(x, y); + // 9/7 / 3 = 3/7 + let expected_result = create_from_rational(3, 7); + assert_approx_the_same( + (get_raw_value(result) as u256), + (get_raw_value(expected_result) as u256), + 16 + ); + } } diff --git a/minitia_stdlib/sources/from_bcs.move b/minitia_stdlib/sources/from_bcs.move index 7aa72b9..e357746 100644 --- a/minitia_stdlib/sources/from_bcs.move +++ b/minitia_stdlib/sources/from_bcs.move @@ -64,9 +64,9 @@ module minitia_std::from_bcs { |s| { assert!( string::internal_check_utf8(string::bytes(s)), - EINVALID_UTF8, + EINVALID_UTF8 ); - }, + } ); vec_string } @@ -76,7 +76,7 @@ module minitia_std::from_bcs { let s = from_bytes(v); assert!( string::internal_check_utf8(string::bytes(&s)), - EINVALID_UTF8, + EINVALID_UTF8 ); s } diff --git a/minitia_stdlib/sources/function_info.move b/minitia_stdlib/sources/function_info.move index dc3d65d..780e10b 100644 --- a/minitia_stdlib/sources/function_info.move +++ b/minitia_stdlib/sources/function_info.move @@ -17,36 +17,32 @@ module minitia_std::function_info { struct FunctionInfo has copy, drop, store { module_address: address, module_name: String, - function_name: String, + function_name: String } /// Creates a new function info from names. public fun new_function_info( - module_signer: &signer, - module_name: String, - function_name: String, + module_signer: &signer, module_name: String, function_name: String ): FunctionInfo { new_function_info_from_address( signer::address_of(module_signer), module_name, - function_name, + function_name ) } public(friend) fun new_function_info_from_address( - module_address: address, - module_name: String, - function_name: String, + module_address: address, module_name: String, function_name: String ): FunctionInfo { assert!( is_identifier(string::bytes(&module_name)), - EINVALID_IDENTIFIER, + EINVALID_IDENTIFIER ); assert!( is_identifier(string::bytes(&function_name)), - EINVALID_IDENTIFIER, + EINVALID_IDENTIFIER ); - FunctionInfo { module_address, module_name, function_name, } + FunctionInfo { module_address, module_name, function_name } } /// Check if the dispatch target function meets the type requirements of the disptach entry point. @@ -60,7 +56,7 @@ module minitia_std::function_info { /// /// dispatch_target also needs to be public so the type signature will remain unchanged. public(friend) fun check_dispatch_type_compatibility( - framework_function: &FunctionInfo, dispatch_target: &FunctionInfo, + framework_function: &FunctionInfo, dispatch_target: &FunctionInfo ): bool { load_function_impl(dispatch_target); check_dispatch_type_compatibility_impl(framework_function, dispatch_target) @@ -79,7 +75,9 @@ module minitia_std::function_info { load_function_impl(f) } - native fun check_dispatch_type_compatibility_impl(lhs: &FunctionInfo, r: &FunctionInfo): bool; + native fun check_dispatch_type_compatibility_impl( + lhs: &FunctionInfo, r: &FunctionInfo + ): bool; native fun is_identifier(s: &vector): bool; native fun load_function_impl(f: &FunctionInfo); diff --git a/minitia_stdlib/sources/hex.move b/minitia_stdlib/sources/hex.move index 9385367..0742265 100644 --- a/minitia_stdlib/sources/hex.move +++ b/minitia_stdlib/sources/hex.move @@ -36,11 +36,11 @@ module minitia_std::hex { let val = *vector::borrow(bz, index); vector::push_back( &mut vec, - encode_to_char_with_option(val / 0x10, is_upper), + encode_to_char_with_option(val / 0x10, is_upper) ); vector::push_back( &mut vec, - encode_to_char_with_option(val % 0x10, is_upper), + encode_to_char_with_option(val % 0x10, is_upper) ); index = index + 1; }; @@ -52,7 +52,7 @@ module minitia_std::hex { public fun decode_string(str: &String): vector { assert!( is_hex_string(str), - error::invalid_argument(ENOT_HEXSTRING), + error::invalid_argument(ENOT_HEXSTRING) ); let vec: vector = vector[]; @@ -128,12 +128,13 @@ module minitia_std::hex { } fun is_hex_char(char: u8): bool { - if ((char >= ZERO + if ( + (char >= ZERO && char <= ZERO + 9) // 0 - 9 - || (char >= UPPERA - && char <= UPPERA + 5) // A - F - || (char >= LOWERA - && char <= LOWERA + 5)) { // a - f + || (char >= UPPERA + && char <= UPPERA + 5) // A - F + || (char >= LOWERA + && char <= LOWERA + 5)) { // a - f return true }; false @@ -145,7 +146,7 @@ module minitia_std::hex { let hex_string = encode_to_string(&raw_bytes); assert!( *string::bytes(&hex_string) == b"68656c6c6f20776f726c6421", - 0, + 0 ); // test odd bytes diff --git a/minitia_stdlib/sources/json.move b/minitia_stdlib/sources/json.move index 3ec8d28..e8166eb 100644 --- a/minitia_stdlib/sources/json.move +++ b/minitia_stdlib/sources/json.move @@ -1,5 +1,76 @@ module minitia_std::json { - use std::string::String; + use std::vector; + use std::string::{Self, String}; + use std::option::{Self, Option}; + + /// JSONValue is a struct to hold any JSON value which is unknown at compile time. + struct JSONValue has copy, drop { + value: vector + } + + /// JSONObject is a struct to hold any json object which is unknown at compile time. + struct JSONObject has copy, drop { + elems: vector + } + + /// Element is a struct to hold key-value pair in JSON object. + struct Element has copy, drop { + key: vector, + value: vector + } + + /// Unmarshal JSON value to the given type. + public fun unmarshal_json_value(json_value: JSONValue): T { + unmarshal(json_value.value) + } + + /// Get the list of keys from the JSON object. + public fun keys(obj: &JSONObject): vector { + vector::map_ref(&obj.elems, |elem| { + use_elem(elem); + string::utf8(elem.key) + }) + } + + /// Get the value of the given key from the JSON object. + public fun get_elem(obj: &JSONObject, key: String): Option { + let key_bytes = string::bytes(&key); + let (found, idx) = vector::find(&obj.elems, |elem| { + use_elem(elem); + elem.key == *key_bytes + }); + + if (!found) { + return option::none() + }; + + let elem = vector::borrow(&obj.elems, idx); + option::some(unmarshal(elem.value)) + } + + /// Set or overwrite the element in the JSON object. + public fun set_elem(obj: &mut JSONObject, key: String, value: &T) { + let key_bytes = string::bytes(&key); + let (found, idx) = vector::find(&obj.elems, |elem| { + use_elem(elem); + elem.key == *key_bytes + }); + + if (!found) { + vector::push_back(&mut obj.elems, Element { + key: *key_bytes, + value: marshal(value) + }); + } else { + let elem = vector::borrow_mut(&mut obj.elems, idx); + elem.value = marshal(value); + } + } + + // + // (only on compiler v1) for preventing compile error; because of inferring type issue + // + inline fun use_elem(_elem: &Element) {} /// Marshal data to JSON bytes. /// @@ -20,16 +91,10 @@ module minitia_std::json { native public fun unmarshal(json: vector): T; #[test_only] - use std::string; - - #[test_only] - use std::option::{Self, Option}; + use std::biguint::{Self, BigUint}; #[test_only] - use std::decimal128::{Self, Decimal128}; - - #[test_only] - use std::decimal256::{Self, Decimal256}; + use std::bigdecimal::{Self, BigDecimal}; #[test_only] struct TestObject has copy, drop { @@ -41,15 +106,27 @@ module minitia_std::json { f: Option, _type_: String, _move_: String, - decimal128: Decimal128, - decimal256: Decimal256, + biguint: BigUint, + bigdecimal: BigDecimal } #[test_only] struct TestObject2 has copy, drop { a: u64, b: bool, - c: vector, + c: vector + } + + #[test_only] + struct EmptyObject has copy, drop {} + + #[test] + fun test_empty_marshal_unmarshal_empty() { + let json = marshal(&EmptyObject {}); + assert!(json == b"{}", 1); + + let val = unmarshal(json); + assert!(val == EmptyObject {}, 2); } #[test] @@ -78,28 +155,47 @@ module minitia_std::json { c: vector[1, 2, 3], d: @0x1, e: option::some( - TestObject2 { a: 42, b: true, c: vector[1, 2, 3], }, + TestObject2 { a: 42, b: true, c: vector[1, 2, 3] } ), f: option::none(), _type_: string::utf8(b"/cosmos.gov.v1.MsgVote"), _move_: string::utf8(b"move"), - decimal128: decimal128::from_ratio(1, 100), - decimal256: decimal256::from_ratio(123, 10000), + biguint: biguint::from_u64(42), + bigdecimal: bigdecimal::from_ratio_u64(123, 10000) }; let json = marshal(&obj); assert!( json - == b"{\"@type\":\"/cosmos.gov.v1.MsgVote\",\"a\":\"42\",\"b\":true,\"c\":\"010203\",\"d\":\"0x1\",\"decimal128\":\"0.01\",\"decimal256\":\"0.0123\",\"e\":{\"a\":\"42\",\"b\":true,\"c\":\"010203\"},\"f\":null,\"move\":\"move\"}", - 1, + == b"{\"@type\":\"/cosmos.gov.v1.MsgVote\",\"a\":\"42\",\"b\":true,\"bigdecimal\":\"0.0123\",\"biguint\":\"42\",\"c\":\"010203\",\"d\":\"0x1\",\"e\":{\"a\":\"42\",\"b\":true,\"c\":\"010203\"},\"f\":null,\"move\":\"move\"}", + 1 ); let obj2 = unmarshal(json); let json2 = marshal(&obj2); - assert!( - json2 - == b"{\"@type\":\"/cosmos.gov.v1.MsgVote\",\"a\":\"42\",\"b\":true,\"c\":\"010203\",\"d\":\"0x1\",\"decimal128\":\"0.01\",\"decimal256\":\"0.0123\",\"e\":{\"a\":\"42\",\"b\":true,\"c\":\"010203\"},\"f\":null,\"move\":\"move\"}", - 1, - ); + assert!(json2 == json, 1); + + let json_val = unmarshal(json); + let json3 = marshal(&json_val); + assert!(json3 == json, 2); + + let obj3 = unmarshal_json_value(json_val); + let json4 = marshal(&obj3); + assert!(json4 == json, 3); + + let json_obj = unmarshal(json); + let json5 = marshal(&json_obj); + assert!(json5 == json, 4); + + assert!(option::extract(&mut get_elem(&json_obj, string::utf8(b"a"))) == 42, 4); + assert!(option::extract(&mut get_elem(&json_obj, string::utf8(b"b"))) == true, 5); + assert!(option::extract(&mut get_elem>(&json_obj, string::utf8(b"c"))) == vector[1, 2, 3], 6); + assert!(option::extract(&mut get_elem
(&json_obj, string::utf8(b"d"))) == @0x1, 7); + + set_elem(&mut json_obj, string::utf8(b"c"), &string::utf8(b"hello")); + assert!(option::extract(&mut get_elem(&json_obj, string::utf8(b"c"))) == string::utf8(b"hello"), 8); + + let json5 = marshal(&json_obj); + assert!(json5 == b"{\"@type\":\"/cosmos.gov.v1.MsgVote\",\"a\":\"42\",\"b\":true,\"bigdecimal\":\"0.0123\",\"biguint\":\"42\",\"c\":\"hello\",\"d\":\"0x1\",\"e\":{\"a\":\"42\",\"b\":true,\"c\":\"010203\"},\"f\":null,\"move\":\"move\"}", 9); } } diff --git a/minitia_stdlib/sources/keccak.move b/minitia_stdlib/sources/keccak.move index 2f07947..9c382ce 100644 --- a/minitia_stdlib/sources/keccak.move +++ b/minitia_stdlib/sources/keccak.move @@ -12,11 +12,12 @@ module minitia_std::keccak { #[test] fun keccak256_test() { - let inputs = vector[b"testing", b"",]; + let inputs = vector[b"testing", b""]; let outputs = vector[ x"5f16f4c7f149ac4f9510d9cf8cf384038ad348b3bcdc01915f95de12df9d1b02", - x"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",]; + x"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" + ]; let i = 0; while (i < std::vector::length(&inputs)) { diff --git a/minitia_stdlib/sources/managed_coin.move b/minitia_stdlib/sources/managed_coin.move index 8a3fa07..f3c86c8 100644 --- a/minitia_stdlib/sources/managed_coin.move +++ b/minitia_stdlib/sources/managed_coin.move @@ -30,7 +30,7 @@ module minitia_std::managed_coin { struct Capabilities has key { mint_cap: MintCapability, burn_cap: BurnCapability, - freeze_cap: FreezeCapability, + freeze_cap: FreezeCapability } // @@ -40,7 +40,7 @@ module minitia_std::managed_coin { fun check_sudo(account: &signer) { assert!( signer::address_of(account) == @minitia_std, - error::permission_denied(EUNAUTHORIZED), + error::permission_denied(EUNAUTHORIZED) ); } @@ -49,20 +49,20 @@ module minitia_std::managed_coin { account: &signer, dst_addr: address, metadata: Object, - amount: u64, + amount: u64 ) acquires Capabilities { check_sudo(account); let account_addr = signer::address_of(account); assert!( object::is_owner(metadata, account_addr), - error::not_found(EUNAUTHORIZED), + error::not_found(EUNAUTHORIZED) ); let object_addr = object::object_address(&metadata); assert!( exists(object_addr), - error::not_found(ENO_CAPABILITIES), + error::not_found(ENO_CAPABILITIES) ); let capabilities = borrow_global(object_addr); @@ -83,7 +83,7 @@ module minitia_std::managed_coin { symbol: String, decimals: u8, icon_uri: String, - project_uri: String, + project_uri: String ) { let (mint_cap, burn_cap, freeze_cap, extend_ref) = coin::initialize_and_generate_extend_ref( @@ -93,33 +93,31 @@ module minitia_std::managed_coin { symbol, decimals, icon_uri, - project_uri, + project_uri ); let metadata_signer = object::generate_signer_for_extending(&extend_ref); move_to( &metadata_signer, - Capabilities { mint_cap, burn_cap, freeze_cap, }, + Capabilities { mint_cap, burn_cap, freeze_cap } ); } /// Withdraw an `amount` of metadata coin from `account` and burn it. public entry fun burn( - account: &signer, - metadata: Object, - amount: u64, + account: &signer, metadata: Object, amount: u64 ) acquires Capabilities { let account_addr = signer::address_of(account); assert!( object::is_owner(metadata, account_addr), - error::not_found(EUNAUTHORIZED), + error::not_found(EUNAUTHORIZED) ); let object_addr = object::object_address(&metadata); assert!( exists(object_addr), - error::not_found(ENO_CAPABILITIES), + error::not_found(ENO_CAPABILITIES) ); let capabilities = borrow_global(object_addr); @@ -130,21 +128,19 @@ module minitia_std::managed_coin { /// Create new metadata coins. public fun mint( - account: &signer, - metadata: Object, - amount: u64, + account: &signer, metadata: Object, amount: u64 ): FungibleAsset acquires Capabilities { let account_addr = signer::address_of(account); assert!( object::is_owner(metadata, account_addr), - error::not_found(EUNAUTHORIZED), + error::not_found(EUNAUTHORIZED) ); let object_addr = object::object_address(&metadata); assert!( exists(object_addr), - error::not_found(ENO_CAPABILITIES), + error::not_found(ENO_CAPABILITIES) ); let capabilities = borrow_global(object_addr); @@ -156,7 +152,7 @@ module minitia_std::managed_coin { account: &signer, dst_addr: address, metadata: Object, - amount: u64, + amount: u64 ) acquires Capabilities { let fa = mint(account, metadata, amount); @@ -200,7 +196,7 @@ module minitia_std::managed_coin { string::utf8(TEST_SYMBOL), 10, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); let metadata = test_metadata(); @@ -210,18 +206,18 @@ module minitia_std::managed_coin { &mod_account, source_addr, metadata, - 50, + 50 ); mint_to( &mod_account, destination_addr, metadata, - 10, + 10 ); assert!(coin::balance(source_addr, metadata) == 50, 1); assert!( coin::balance(destination_addr, metadata) == 10, - 2, + 2 ); let supply = coin::supply(metadata); @@ -231,19 +227,19 @@ module minitia_std::managed_coin { &source, destination_addr, metadata, - 10, + 10 ); assert!(coin::balance(source_addr, metadata) == 40, 3); assert!( coin::balance(destination_addr, metadata) == 20, - 4, + 4 ); coin::transfer( &source, signer::address_of(&mod_account), metadata, - 40, + 40 ); burn(&mod_account, metadata, 40); @@ -256,9 +252,7 @@ module minitia_std::managed_coin { #[test(source = @0xa11ce, destination = @0xb0b, mod_account = @0x1)] #[expected_failure(abort_code = 0x60002, location = Self)] public entry fun fail_mint( - source: signer, - destination: signer, - mod_account: signer, + source: signer, destination: signer, mod_account: signer ) acquires Capabilities { primary_fungible_store::init_module_for_test(); @@ -271,7 +265,7 @@ module minitia_std::managed_coin { string::utf8(TEST_SYMBOL), 10, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); let metadata = test_metadata(); @@ -279,16 +273,14 @@ module minitia_std::managed_coin { &destination, source_addr, metadata, - 100, + 100 ); } #[test(source = @0xa11ce, destination = @0xb0b, mod_account = @0x1)] #[expected_failure(abort_code = 0x60002, location = Self)] public entry fun fail_burn( - source: signer, - destination: signer, - mod_account: signer, + source: signer, destination: signer, mod_account: signer ) acquires Capabilities { primary_fungible_store::init_module_for_test(); @@ -301,7 +293,7 @@ module minitia_std::managed_coin { string::utf8(TEST_SYMBOL), 10, string::utf8(b""), - string::utf8(b""), + string::utf8(b"") ); let metadata = test_metadata(); @@ -309,7 +301,7 @@ module minitia_std::managed_coin { &mod_account, source_addr, metadata, - 100, + 100 ); burn(&destination, metadata, 10); } diff --git a/minitia_stdlib/sources/math128.move b/minitia_stdlib/sources/math128.move index 07fe9ff..40ca3b6 100644 --- a/minitia_stdlib/sources/math128.move +++ b/minitia_stdlib/sources/math128.move @@ -60,7 +60,7 @@ module minitia_std::math128 { let res = 0; assert!( x != 0, - std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2), + std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2) ); // Effectively the position of the most significant set bit let n = 64; @@ -167,9 +167,9 @@ module minitia_std::math128 { assert!( ceil_div( (((1u256 << 128) - 9) as u128), - 11, + 11 ) == 30934760629176223951215873402888019223, - 0, + 0 ); } @@ -232,10 +232,8 @@ module minitia_std::math128 { idx = 1; while (idx <= 128) { assert!( - floor_log2( - (((1u256 << idx) - 1) as u128) - ) == idx - 1, - 0, + floor_log2((((1u256 << idx) - 1) as u128)) == idx - 1, + 0 ); idx = idx + 1; }; @@ -248,7 +246,7 @@ module minitia_std::math128 { let res = log2(1 << idx); assert!( fixed_point32::get_raw_value(res) == (idx as u64) << 32, - 0, + 0 ); idx = idx + 1; }; @@ -267,7 +265,7 @@ module minitia_std::math128 { assert_approx_the_same( (fixed_point32::get_raw_value(res) as u128), expected, - 8, + 8 ); idx = idx + 1; }; @@ -280,15 +278,13 @@ module minitia_std::math128 { let res = log2_64(1 << idx); assert!( fixed_point64::get_raw_value(res) == (idx as u128) << 64, - 0, + 0 ); idx = idx + 1; }; idx = 10; while (idx <= 128) { - let res = log2_64( - (((1u256 << idx) - 1) as u128) - ); + let res = log2_64((((1u256 << idx) - 1) as u128)); // idx + log2 (1 - 1/2^idx) = idx + ln (1-1/2^idx)/ln2 // Use 3rd order taylor to approximate expected result let expected = (idx as u256) << 64; @@ -304,7 +300,7 @@ module minitia_std::math128 { assert_approx_the_same( fixed_point64::get_raw_value(res), (expected as u128), - 14, + 14 ); idx = idx + 1; }; diff --git a/minitia_stdlib/sources/math64.move b/minitia_stdlib/sources/math64.move index 2f6df2f..f0e8eb9 100644 --- a/minitia_stdlib/sources/math64.move +++ b/minitia_stdlib/sources/math64.move @@ -58,7 +58,7 @@ module minitia_std::math64 { let res = 0; assert!( x != 0, - std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2), + std::error::invalid_argument(EINVALID_ARG_FLOOR_LOG2) ); // Effectively the position of the most significant set bit let n = 32; @@ -140,9 +140,9 @@ module minitia_std::math64 { assert!( ceil_div( (((1u128 << 64) - 9) as u64), - 11, + 11 ) == 1676976733973595601, - 0, + 0 ); } @@ -211,10 +211,8 @@ module minitia_std::math64 { idx = 1; while (idx <= 64) { assert!( - floor_log2( - (((1u128 << idx) - 1) as u64) - ) == idx - 1, - 0, + floor_log2((((1u128 << idx) - 1) as u64)) == idx - 1, + 0 ); idx = idx + 1; }; @@ -227,7 +225,7 @@ module minitia_std::math64 { let res = log2(1 << idx); assert!( fixed_point32::get_raw_value(res) == (idx as u64) << 32, - 0, + 0 ); idx = idx + 1; }; @@ -246,7 +244,7 @@ module minitia_std::math64 { assert_approx_the_same( (fixed_point32::get_raw_value(res) as u128), expected, - 8, + 8 ); idx = idx + 1; }; diff --git a/minitia_stdlib/sources/multisig.move b/minitia_stdlib/sources/multisig.move index d65dd38..e1919c3 100644 --- a/minitia_stdlib/sources/multisig.move +++ b/minitia_stdlib/sources/multisig.move @@ -34,7 +34,7 @@ module minitia_std::multisig { // constants - const STATUS: vector> = vector[b"in voting preiod", b"executed", b"expired",]; + const STATUS: vector> = vector[b"in voting preiod", b"executed", b"expired"]; const MAX_LIMIT: u8 = 30; @@ -45,7 +45,7 @@ module minitia_std::multisig { /// If both `height` and `timestamp` are set, and only one of them has expired, the period is considered expired. struct Period has copy, drop, store { height: Option, - timestamp: Option, + timestamp: Option } struct MultisigWallet has key { @@ -54,7 +54,7 @@ module minitia_std::multisig { members: vector
, // members of multisig account threshold: u64, // require votes to pass max_voting_period: Period, // max voting period - proposals: Table, + proposals: Table } struct Proposal has store { @@ -69,7 +69,7 @@ module minitia_std::multisig { votes: SimpleMap, status: u8, is_json: bool, - json_args: vector, + json_args: vector } // events @@ -91,7 +91,7 @@ module minitia_std::multisig { function_name: String, type_args: vector, args: vector>, - config_version: u64, + config_version: u64 } #[event] @@ -99,14 +99,14 @@ module minitia_std::multisig { multisig_addr: address, proposal_id: u64, voter: address, - vote_yes: bool, + vote_yes: bool } #[event] struct ExecuteProposalEvent has drop, store { multisig_addr: address, proposal_id: u64, - executor: address, + executor: address } #[event] @@ -133,7 +133,7 @@ module minitia_std::multisig { yes_vote_count: u64, status: String, is_json: bool, - json_args: vector, + json_args: vector } struct ConfigResponse has drop { @@ -141,19 +141,21 @@ module minitia_std::multisig { config_version: u64, members: vector
, threshold: u64, - max_voting_period: Period, + max_voting_period: Period } // view functions #[view] - public fun get_proposal(multisig_addr: address, proposal_id: u64): ProposalResponse acquires MultisigWallet { + public fun get_proposal( + multisig_addr: address, proposal_id: u64 + ): ProposalResponse acquires MultisigWallet { let multisig_wallet = borrow_global(multisig_addr); let proposal = table::borrow(&multisig_wallet.proposals, proposal_id); proposal_to_proposal_response( multisig_wallet, multisig_addr, proposal_id, - proposal, + proposal ) } @@ -170,12 +172,11 @@ module minitia_std::multisig { &multisig_wallet.proposals, option::none(), start_after, - 2, + 2 ); - while (vector::length(&res) < (limit as u64) && table::prepare( - iter - )) { + while (vector::length(&res) < (limit as u64) + && table::prepare(iter)) { let (proposal_id, proposal) = table::next(iter); vector::push_back( &mut res, @@ -183,8 +184,8 @@ module minitia_std::multisig { multisig_wallet, multisig_addr, proposal_id, - proposal, - ), + proposal + ) ); }; @@ -200,7 +201,7 @@ module minitia_std::multisig { config_version: multisig_wallet.config_version, members: multisig_wallet.members, threshold: multisig_wallet.threshold, - max_voting_period: multisig_wallet.max_voting_period, + max_voting_period: multisig_wallet.max_voting_period } } @@ -213,12 +214,12 @@ module minitia_std::multisig { members: vector
, threshold: u64, max_voting_period_height: Option, - max_voting_period_timestamp: Option, + max_voting_period_timestamp: Option ) { assert_member(&members, &signer::address_of(account)); assert!( vector::length(&members) >= threshold, - error::invalid_argument(EINVALID_THRESHOLD), + error::invalid_argument(EINVALID_THRESHOLD) ); let constructor_ref = object::create_named_object( account, *string::bytes(&name) @@ -228,12 +229,12 @@ module minitia_std::multisig { let multisig_addr = signer::address_of(&multisig_signer); let max_voting_period = Period { height: max_voting_period_height, - timestamp: max_voting_period_timestamp, + timestamp: max_voting_period_timestamp }; let members_map = simple_map::create(); vector::for_each( members, - |member| simple_map::add(&mut members_map, member, true), + |member| simple_map::add(&mut members_map, member, true) ); // just for check uniqueness move_to( @@ -244,8 +245,8 @@ module minitia_std::multisig { members, threshold, max_voting_period, - proposals: table::new(), - }, + proposals: table::new() + } ); event::emit( @@ -253,8 +254,8 @@ module minitia_std::multisig { multisig_addr, members, threshold, - max_voting_period, - }, + max_voting_period + } ) } @@ -266,7 +267,7 @@ module minitia_std::multisig { module_name: String, function_name: String, type_args: vector, - args: vector>, + args: vector> ) acquires MultisigWallet { create_proposal_internal( account, @@ -277,7 +278,7 @@ module minitia_std::multisig { type_args, args, false, - vector[], + vector[] ) } @@ -289,7 +290,7 @@ module minitia_std::multisig { module_name: String, function_name: String, type_args: vector, - args: vector, + args: vector ) acquires MultisigWallet { create_proposal_internal( account, @@ -300,7 +301,7 @@ module minitia_std::multisig { type_args, vector[], true, - args, + args ) } @@ -309,7 +310,7 @@ module minitia_std::multisig { account: &signer, multisig_addr: address, proposal_id: u64, - vote_yes: bool, + vote_yes: bool ) acquires MultisigWallet { let voter = signer::address_of(account); let multisig_wallet = borrow_global_mut(multisig_addr); @@ -318,9 +319,9 @@ module minitia_std::multisig { assert!( table::contains( &multisig_wallet.proposals, - proposal_id, + proposal_id ), - error::invalid_argument(EPROPOSAL_NOT_FOUND), + error::invalid_argument(EPROPOSAL_NOT_FOUND) ); let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id); @@ -330,15 +331,13 @@ module minitia_std::multisig { vote(&mut proposal.votes, voter, vote_yes); event::emit( - VoteProposalEvent { multisig_addr, proposal_id, voter, vote_yes, }, + VoteProposalEvent { multisig_addr, proposal_id, voter, vote_yes } ) } /// Execute proposal public entry fun execute_proposal( - account: &signer, - multisig_addr: address, - proposal_id: u64, + account: &signer, multisig_addr: address, proposal_id: u64 ) acquires MultisigWallet { let executor = signer::address_of(account); let multisig_wallet = borrow_global_mut(multisig_addr); @@ -347,9 +346,9 @@ module minitia_std::multisig { assert!( table::contains( &multisig_wallet.proposals, - proposal_id, + proposal_id ), - error::invalid_argument(EPROPOSAL_NOT_FOUND), + error::invalid_argument(EPROPOSAL_NOT_FOUND) ); let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id); @@ -360,9 +359,9 @@ module minitia_std::multisig { assert!( yes_vote_count( &proposal.votes, - &multisig_wallet.members, + &multisig_wallet.members ) >= multisig_wallet.threshold, - error::invalid_state(ENOT_PASS), + error::invalid_state(ENOT_PASS) ); let multisig_signer = @@ -375,7 +374,7 @@ module minitia_std::multisig { proposal.module_name, proposal.function_name, proposal.type_args, - proposal.args, + proposal.args ) } else { move_execute_with_json( @@ -384,14 +383,14 @@ module minitia_std::multisig { proposal.module_name, proposal.function_name, proposal.type_args, - proposal.json_args, + proposal.json_args ) }; proposal.status = 1; // executed event::emit( - ExecuteProposalEvent { multisig_addr, proposal_id, executor, }, + ExecuteProposalEvent { multisig_addr, proposal_id, executor } ) } @@ -401,23 +400,23 @@ module minitia_std::multisig { new_members: vector
, new_threshold: u64, new_max_voting_period_height: Option, - new_max_voting_period_timestamp: Option, + new_max_voting_period_timestamp: Option ) acquires MultisigWallet { let multisig_addr = signer::address_of(account); let multisig_wallet = borrow_global_mut(multisig_addr); assert!( vector::length(&new_members) >= new_threshold, - error::invalid_argument(EINVALID_THRESHOLD), + error::invalid_argument(EINVALID_THRESHOLD) ); let new_members_map = simple_map::create(); vector::for_each( new_members, - |member| simple_map::add(&mut new_members_map, member, true), + |member| simple_map::add(&mut new_members_map, member, true) ); // just for check uniqueness let new_max_voting_period = Period { height: new_max_voting_period_height, - timestamp: new_max_voting_period_timestamp, + timestamp: new_max_voting_period_timestamp }; multisig_wallet.config_version = multisig_wallet.config_version + 1; @@ -430,8 +429,8 @@ module minitia_std::multisig { multisig_addr, members: new_members, threshold: new_threshold, - max_voting_period: new_max_voting_period, - }, + max_voting_period: new_max_voting_period + } ) } @@ -444,7 +443,7 @@ module minitia_std::multisig { type_args: vector, args: vector>, is_json: bool, - json_args: vector, + json_args: vector ) acquires MultisigWallet { let addr = signer::address_of(account); let multisig_wallet = borrow_global_mut(multisig_addr); @@ -465,14 +464,14 @@ module minitia_std::multisig { votes: simple_map::create(), status: 0, // in voting period is_json, - json_args, + json_args }; let proposal_id = table::length(&multisig_wallet.proposals) + 1; table::add( &mut multisig_wallet.proposals, proposal_id, - proposal, + proposal ); event::emit( @@ -484,8 +483,8 @@ module minitia_std::multisig { function_name, type_args, args, - config_version, - }, + config_version + } ) } @@ -529,10 +528,10 @@ module minitia_std::multisig { members, |member| { if (simple_map::contains_key(votes, member) - && *simple_map::borrow(votes, member)) { + && *simple_map::borrow(votes, member)) { yes_count = yes_count + 1; } - }, + } ); yes_count @@ -542,14 +541,14 @@ module minitia_std::multisig { multisig_wallet: &MultisigWallet, multisig_addr: address, proposal_id: u64, - proposal: &Proposal, + proposal: &Proposal ): ProposalResponse { let status_index = proposal.status; let is_expired = is_proposal_expired( &multisig_wallet.max_voting_period, proposal.proposal_height, - proposal.proposal_timestamp, + proposal.proposal_timestamp ); let yes_vote_count = yes_vote_count(&proposal.votes, &multisig_wallet.members); if (status_index == 0 && is_expired) { @@ -570,14 +569,14 @@ module minitia_std::multisig { yes_vote_count, status: string::utf8(*vector::borrow(&STATUS, (status_index as u64))), is_json: proposal.is_json, - json_args: proposal.json_args, + json_args: proposal.json_args } } inline fun assert_member(members: &vector
, member: &address) { assert!( vector::contains(members, member), - error::permission_denied(ENOT_MEMBER), + error::permission_denied(ENOT_MEMBER) ) } @@ -586,7 +585,7 @@ module minitia_std::multisig { ) { assert!( multisig_wallet_config_version == execute_proposal.config_version, - error::invalid_state(EOLD_CONFIG_VERSION), + error::invalid_state(EOLD_CONFIG_VERSION) ) } @@ -595,28 +594,30 @@ module minitia_std::multisig { ) { assert!( proposal.status == 0, - error::invalid_state(EINVALID_PROPOSAL_STATUS), + error::invalid_state(EINVALID_PROPOSAL_STATUS) ); assert!( !is_proposal_expired( max_voting_period, proposal.proposal_height, - proposal.proposal_timestamp, + proposal.proposal_timestamp ), - error::invalid_state(EPROPOSAL_EXPIRED), + error::invalid_state(EPROPOSAL_EXPIRED) ); } #[test_only] use minitia_std::block::set_block_info; - #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104)] + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] #[expected_failure(abort_code = 0x50002, location = Self)] fun create_wallet_by_other( account1: signer, account2: signer, account3: signer, - account4: signer, + account4: signer ) { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -629,16 +630,14 @@ module minitia_std::multisig { vector[addr1, addr2, addr3], 2, option::none(), - option::none(), + option::none() ); } #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] #[expected_failure(abort_code = 0x10001, location = Self)] fun invalid_threshold( - account1: signer, - account2: signer, - account3: signer, + account1: signer, account2: signer, account3: signer ) { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -651,16 +650,14 @@ module minitia_std::multisig { vector[addr1, addr2, addr3], 4, option::none(), - option::none(), + option::none() ); } #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] - #[expected_failure(abort_code = 0x10000, location = simple_map)] + #[expected_failure(abort_code = 0x10001, location = simple_map)] fun duplicated_member( - account1: signer, - account2: signer, - account3: signer, + account1: signer, account2: signer, account3: signer ) { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -673,17 +670,19 @@ module minitia_std::multisig { vector[addr1, addr1, addr2, addr3], 3, option::none(), - option::none(), + option::none() ); } - #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104)] + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] #[expected_failure(abort_code = 0x50002, location = Self)] fun create_proposal_by_other( account1: signer, account2: signer, account3: signer, - account4: signer, + account4: signer ) acquires MultisigWallet { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -697,7 +696,7 @@ module minitia_std::multisig { vector[addr1, addr2, addr3], 2, option::none(), - option::none(), + option::none() ); let multisig_addr = object::create_object_address(&addr1, b"multisig wallet"); @@ -712,17 +711,20 @@ module minitia_std::multisig { std::bcs::to_bytes(&vector[addr1, addr2, addr4]), std::bcs::to_bytes(&3u64), std::bcs::to_bytes(&option::none()), - std::bcs::to_bytes(&option::none()),], + std::bcs::to_bytes(&option::none()) + ] ); } - #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104)] + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] #[expected_failure(abort_code = 0x50002, location = Self)] fun vote_by_other( account1: signer, account2: signer, account3: signer, - account4: signer, + account4: signer ) acquires MultisigWallet { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -736,7 +738,7 @@ module minitia_std::multisig { vector[addr1, addr2, addr3], 2, option::none(), - option::none(), + option::none() ); let multisig_addr = object::create_object_address(&addr1, b"multisig wallet"); @@ -751,19 +753,22 @@ module minitia_std::multisig { std::bcs::to_bytes(&vector[addr1, addr2, addr4]), std::bcs::to_bytes(&3u64), std::bcs::to_bytes(&option::none()), - std::bcs::to_bytes(&option::none()),], + std::bcs::to_bytes(&option::none()) + ] ); vote_proposal(&account4, multisig_addr, 1, true); } - #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104)] + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] #[expected_failure(abort_code = 0x30005, location = Self)] fun vote_after_height_expired( account1: signer, account2: signer, account3: signer, - account4: signer, + account4: signer ) acquires MultisigWallet { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -777,7 +782,7 @@ module minitia_std::multisig { vector[addr1, addr2, addr3], 2, option::some(10), - option::some(10), + option::some(10) ); let multisig_addr = object::create_object_address(&addr1, b"multisig wallet"); @@ -793,20 +798,23 @@ module minitia_std::multisig { std::bcs::to_bytes(&vector[addr1, addr2, addr4]), std::bcs::to_bytes(&3u64), std::bcs::to_bytes(&option::none()), - std::bcs::to_bytes(&option::none()),], + std::bcs::to_bytes(&option::none()) + ] ); set_block_info(111, 100); vote_proposal(&account1, multisig_addr, 1, true); } - #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104)] + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] #[expected_failure(abort_code = 0x30005, location = Self)] fun vote_after_timestamp_expired( account1: signer, account2: signer, account3: signer, - account4: signer, + account4: signer ) acquires MultisigWallet { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -820,7 +828,7 @@ module minitia_std::multisig { vector[addr1, addr2, addr3], 2, option::some(10), - option::some(10), + option::some(10) ); let multisig_addr = object::create_object_address(&addr1, b"multisig wallet"); @@ -836,20 +844,23 @@ module minitia_std::multisig { std::bcs::to_bytes(&vector[addr1, addr2, addr4]), std::bcs::to_bytes(&3u64), std::bcs::to_bytes(&option::none()), - std::bcs::to_bytes(&option::none()),], + std::bcs::to_bytes(&option::none()) + ] ); set_block_info(100, 111); vote_proposal(&account1, multisig_addr, 1, true); } - #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104)] + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] #[expected_failure(abort_code = 0x30008, location = Self)] fun execute_not_pass( account1: signer, account2: signer, account3: signer, - account4: signer, + account4: signer ) acquires MultisigWallet { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -863,7 +874,7 @@ module minitia_std::multisig { vector[addr1, addr2, addr3], 2, option::none(), - option::none(), + option::none() ); let multisig_addr = object::create_object_address(&addr1, b"multisig wallet"); @@ -878,7 +889,8 @@ module minitia_std::multisig { std::bcs::to_bytes(&vector[addr1, addr2, addr4]), std::bcs::to_bytes(&3u64), std::bcs::to_bytes(&option::none()), - std::bcs::to_bytes(&option::none()),], + std::bcs::to_bytes(&option::none()) + ] ); vote_proposal(&account1, multisig_addr, 1, true); @@ -888,13 +900,15 @@ module minitia_std::multisig { execute_proposal(&account1, multisig_addr, 1); } - #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104)] + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] #[expected_failure(abort_code = 0x30003, location = Self)] fun execute_after_config_update( account1: signer, account2: signer, account3: signer, - account4: signer, + account4: signer ) acquires MultisigWallet { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -908,7 +922,7 @@ module minitia_std::multisig { vector[addr1, addr2, addr3], 2, option::none(), - option::none(), + option::none() ); let multisig_addr = object::create_object_address(&addr1, b"multisig wallet"); @@ -923,7 +937,8 @@ module minitia_std::multisig { std::bcs::to_bytes(&vector[addr1, addr2, addr4]), std::bcs::to_bytes(&3u64), std::bcs::to_bytes(&option::none()), - std::bcs::to_bytes(&option::none()),], + std::bcs::to_bytes(&option::none()) + ] ); vote_proposal(&account1, multisig_addr, 1, true); @@ -938,7 +953,7 @@ module minitia_std::multisig { vector[addr1, addr2, addr4], 2, option::none(), - option::none(), + option::none() ); execute_proposal(&account1, multisig_addr, 1); @@ -946,9 +961,7 @@ module minitia_std::multisig { #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] fun proposal_with_json( - account1: signer, - account2: signer, - account3: signer, + account1: signer, account2: signer, account3: signer ) acquires MultisigWallet { // create multisig wallet let addr1 = signer::address_of(&account1); @@ -961,7 +974,7 @@ module minitia_std::multisig { vector[addr1, addr2, addr3], 2, option::none(), - option::none(), + option::none() ); let multisig_addr = object::create_object_address(&addr1, b"multisig wallet"); @@ -976,18 +989,19 @@ module minitia_std::multisig { string::utf8(b"[\"0x101\", \"0x102\", \"0x104\"]"), string::utf8(b"\"3\""), string::utf8(b""), - string::utf8(b""),], + string::utf8(b"") + ] ); let proposal = get_proposal(multisig_addr, 1); assert!(proposal.module_address == @minitia_std, 0); assert!( proposal.module_name == string::utf8(b"multisig"), - 1, + 1 ); assert!( proposal.function_name == string::utf8(b"update_config"), - 2, + 2 ); assert!(proposal.type_args == vector[], 3); assert!( @@ -996,8 +1010,9 @@ module minitia_std::multisig { string::utf8(b"[\"0x101\", \"0x102\", \"0x104\"]"), string::utf8(b"\"3\""), string::utf8(b""), - string::utf8(b""),], - 4, + string::utf8(b"") + ], + 4 ); assert!(proposal.args == vector[], 5); } diff --git a/minitia_stdlib/sources/object.move b/minitia_stdlib/sources/object.move index cc708a4..8e90c06 100644 --- a/minitia_stdlib/sources/object.move +++ b/minitia_stdlib/sources/object.move @@ -28,6 +28,7 @@ module minitia_std::object { use minitia_std::event; friend minitia_std::primary_fungible_store; + friend minitia_std::nft; /// An object already exists at this address const EOBJECT_EXISTS: u64 = 1; @@ -82,7 +83,7 @@ module minitia_std::object { /// Tombstone is version store for deleted objects with version struct Tombstone has key { - version: u64, + version: u64 } /// The core of the object model that defines ownership, transferability, and events. @@ -93,7 +94,7 @@ module minitia_std::object { /// transfers bypassing the use of a TransferRef. allow_ungated_transfer: bool, /// The version is to invalidate the refs, which are generated for previously burnt object. - version: u64, + version: u64 } /// A pointer to an object -- these can only provide guarantees based upon the underlying data @@ -101,7 +102,7 @@ module minitia_std::object { /// by any other module than the module that defined T. Similarly, the module that defines T /// can remove it from storage at any point in time. struct Object has copy, drop, store { - inner: address, + inner: address } /// This is a one time ability given to the creator to configure the object as necessary @@ -109,25 +110,25 @@ module minitia_std::object { self: address, /// True if the object can be deleted. can_delete: bool, - version: u64, + version: u64 } /// Used to remove an object from storage. struct DeleteRef has drop, store { self: address, - version: u64, + version: u64 } /// Used to create events or move additional resources into object storage. struct ExtendRef has drop, store { self: address, - version: u64, + version: u64 } /// Used to create LinearTransferRef, hence ownership transfer. struct TransferRef has drop, store { self: address, - version: u64, + version: u64 } /// Used to perform transfers. This locks transferring ability to a single time use bound to @@ -135,13 +136,13 @@ module minitia_std::object { struct LinearTransferRef has drop { self: address, owner: address, - version: u64, + version: u64 } /// Used to create derived objects from a given objects. struct DeriveRef has drop, store { self: address, - version: u64, + version: u64 } #[event] @@ -149,7 +150,7 @@ module minitia_std::object { struct CreateEvent has drop, store { object: address, owner: address, - version: u64, + version: u64 } #[event] @@ -157,18 +158,18 @@ module minitia_std::object { struct TransferEvent has drop, store { object: address, from: address, - to: address, + to: address } /// Produces an ObjectId from the given address. This is not verified. public fun address_to_object(object: address): Object { assert!( exists(object), - error::not_found(EOBJECT_DOES_NOT_EXIST), + error::not_found(EOBJECT_DOES_NOT_EXIST) ); assert!( exists_at(object), - error::not_found(ERESOURCE_DOES_NOT_EXIST), + error::not_found(ERESOURCE_DOES_NOT_EXIST) ); Object { inner: object } } @@ -178,6 +179,11 @@ module minitia_std::object { exists(object) } + /// Returns true if there exists an object with resource T. + public fun object_exists(object: address): bool { + exists(object) && exists_at(object) + } + /// Derives an object address from source material: sha3_256([creator address | seed | 0xFE]). public fun create_object_address(source: &address, seed: vector): address { let bytes = bcs::to_bytes(source); @@ -220,7 +226,9 @@ module minitia_std::object { /// Create a new named object and return the ConstructorRef. /// Named objects can be queried globally by knowing the user generated seed used to create them. - public fun create_named_object(creator: &signer, seed: vector): ConstructorRef acquires Tombstone { + public fun create_named_object( + creator: &signer, seed: vector + ): ConstructorRef acquires Tombstone { let creator_address = signer::address_of(creator); let obj_addr = create_object_address(&creator_address, seed); create_object_internal(creator_address, obj_addr, false) @@ -236,6 +244,16 @@ module minitia_std::object { create_object_internal(creator_address, obj_addr, true) } + /// Create a new object to represent an NFT and return the ConstructorRef. + /// Nft objects can be queried globally by knowing the user generated seed used to create them + /// and the creator's address. NFT objects can be deleted. + public(friend) fun create_nft_object( + owner: address, creator: address, seed: vector + ): ConstructorRef acquires Tombstone { + let obj_addr = create_object_address(&creator, seed); + create_object_internal(owner, obj_addr, true) + } + /// Create a new object whose address is derived based on the creator account address and another object. /// Derivde objects, similar to named objects, cannot be deleted. public(friend) fun create_user_derived_object( @@ -246,32 +264,32 @@ module minitia_std::object { create_object_internal( creator_address, obj_addr, - can_delete, + can_delete ) } /// Create a new object by generating a random unique address based on transaction hash. /// The unique address is computed sha3_256([transaction hash | auid counter | 0xFB]). - public fun create_object(owner_address: address, can_delete: bool): ConstructorRef acquires Tombstone { + public fun create_object( + owner_address: address, can_delete: bool + ): ConstructorRef acquires Tombstone { let unique_address = transaction_context::generate_unique_address(); create_object_internal( owner_address, unique_address, - can_delete, + can_delete ) } fun create_object_internal( - creator_address: address, - object: address, - can_delete: bool, + creator_address: address, object: address, can_delete: bool ): ConstructorRef acquires Tombstone { // create resource account to prevent address overapping. account::create_object_account(object); assert!( !exists(object), - error::already_exists(EOBJECT_EXISTS), + error::already_exists(EOBJECT_EXISTS) ); let object_signer = account::create_signer(object); let version = @@ -282,12 +300,10 @@ module minitia_std::object { move_to( &object_signer, - ObjectCore { owner: creator_address, allow_ungated_transfer: true, version, }, + ObjectCore { owner: creator_address, allow_ungated_transfer: true, version } ); - event::emit( - CreateEvent { owner: creator_address, object, version, } - ); + event::emit(CreateEvent { owner: creator_address, object, version }); ConstructorRef { self: object, version, can_delete } } @@ -298,7 +314,7 @@ module minitia_std::object { public fun generate_delete_ref(ref: &ConstructorRef): DeleteRef { assert!( ref.can_delete, - error::permission_denied(ECANNOT_DELETE), + error::permission_denied(ECANNOT_DELETE) ); DeleteRef { self: ref.self, version: ref.version } } @@ -355,15 +371,15 @@ module minitia_std::object { let object_core = move_from(ref.self); assert!( ref.version == object_core.version, - error::permission_denied(EVERSION_MISMATCH), + error::permission_denied(EVERSION_MISMATCH) ); - let ObjectCore { owner: _, allow_ungated_transfer: _, version, } = object_core; + let ObjectCore { owner: _, allow_ungated_transfer: _, version } = object_core; // set tombstone move_to( &account::create_signer(ref.self), - Tombstone { version, }, + Tombstone { version } ); } @@ -374,7 +390,7 @@ module minitia_std::object { let object_core = borrow_global(ref.self); assert!( ref.version == object_core.version, - error::permission_denied(EVERSION_MISMATCH), + error::permission_denied(EVERSION_MISMATCH) ); account::create_signer(ref.self) @@ -392,7 +408,7 @@ module minitia_std::object { let object_core = borrow_global_mut(ref.self); assert!( ref.version == object_core.version, - error::permission_denied(EVERSION_MISMATCH), + error::permission_denied(EVERSION_MISMATCH) ); object_core.allow_ungated_transfer = false; @@ -403,7 +419,7 @@ module minitia_std::object { let object_core = borrow_global_mut(ref.self); assert!( ref.version == object_core.version, - error::permission_denied(EVERSION_MISMATCH), + error::permission_denied(EVERSION_MISMATCH) ); object_core.allow_ungated_transfer = true; @@ -411,17 +427,19 @@ module minitia_std::object { /// Create a LinearTransferRef for a one-time transfer. This requires that the owner at the /// time of generation is the owner at the time of transferring. - public fun generate_linear_transfer_ref(ref: &TransferRef): LinearTransferRef acquires ObjectCore { + public fun generate_linear_transfer_ref( + ref: &TransferRef + ): LinearTransferRef acquires ObjectCore { let object_core = borrow_global(ref.self); assert!( ref.version == object_core.version, - error::permission_denied(EVERSION_MISMATCH), + error::permission_denied(EVERSION_MISMATCH) ); LinearTransferRef { self: ref.self, owner: object_core.owner, - version: object_core.version, + version: object_core.version } } @@ -430,25 +448,21 @@ module minitia_std::object { let object_core = borrow_global_mut(ref.self); assert!( ref.version == object_core.version, - error::permission_denied(EVERSION_MISMATCH), + error::permission_denied(EVERSION_MISMATCH) ); assert!( object_core.owner == ref.owner, - error::permission_denied(ENOT_OBJECT_OWNER), + error::permission_denied(ENOT_OBJECT_OWNER) ); - event::emit( - TransferEvent { object: ref.self, from: object_core.owner, to, }, - ); + event::emit(TransferEvent { object: ref.self, from: object_core.owner, to }); object_core.owner = to; } /// Entry function that can be used to transfer, if allow_ungated_transfer is set true. public entry fun transfer_call( - owner: &signer, - object: address, - to: address, + owner: &signer, object: address, to: address ) acquires ObjectCore { transfer_raw(owner, object, to) } @@ -456,9 +470,7 @@ module minitia_std::object { /// Transfers ownership of the object (and all associated resources) at the specified address /// for Object to the "to" address. public entry fun transfer( - owner: &signer, - object: Object, - to: address, + owner: &signer, object: Object, to: address ) acquires ObjectCore { transfer_raw(owner, object.inner, to) } @@ -467,28 +479,20 @@ module minitia_std::object { /// allow_ungated_transfer is set true. Note, that this allows the owner of a nested object to /// transfer that object, so long as allow_ungated_transfer is enabled at each stage in the /// hierarchy. - public fun transfer_raw( - owner: &signer, - object: address, - to: address, - ) acquires ObjectCore { + public fun transfer_raw(owner: &signer, object: address, to: address) acquires ObjectCore { let owner_address = signer::address_of(owner); verify_ungated_and_descendant(owner_address, object); let object_core = borrow_global_mut(object); if (object_core.owner == to) { return }; - event::emit( - TransferEvent { object: object, from: object_core.owner, to, }, - ); + event::emit(TransferEvent { object: object, from: object_core.owner, to }); object_core.owner = to; } /// Transfer the given object to another object. See `transfer` for more information. public entry fun transfer_to_object( - owner: &signer, - object: Object, - to: Object, + owner: &signer, object: Object, to: Object ) acquires ObjectCore { transfer(owner, object, to.inner) } @@ -502,13 +506,13 @@ module minitia_std::object { let current_address = destination; assert!( exists(current_address), - error::not_found(EOBJECT_DOES_NOT_EXIST), + error::not_found(EOBJECT_DOES_NOT_EXIST) ); let object = borrow_global(current_address); assert!( object.allow_ungated_transfer, - error::permission_denied(ENO_UNGATED_TRANSFERS), + error::permission_denied(ENO_UNGATED_TRANSFERS) ); let current_address = object.owner; @@ -518,19 +522,19 @@ module minitia_std::object { count = count + 1; assert!( count < MAXIMUM_OBJECT_NESTING, - error::out_of_range(EMAXIMUM_NESTING), + error::out_of_range(EMAXIMUM_NESTING) ); // At this point, the first object exists and so the more likely case is that the // object's owner is not an object. So we return a more sensible error. assert!( exists(current_address), - error::permission_denied(ENOT_OBJECT_OWNER), + error::permission_denied(ENOT_OBJECT_OWNER) ); let object = borrow_global(current_address); assert!( object.allow_ungated_transfer, - error::permission_denied(ENO_UNGATED_TRANSFERS), + error::permission_denied(ENO_UNGATED_TRANSFERS) ); current_address = object.owner; @@ -544,7 +548,7 @@ module minitia_std::object { public fun ungated_transfer_allowed(object: Object): bool acquires ObjectCore { assert!( exists(object.inner), - error::not_found(EOBJECT_DOES_NOT_EXIST), + error::not_found(EOBJECT_DOES_NOT_EXIST) ); borrow_global(object.inner).allow_ungated_transfer } @@ -554,7 +558,7 @@ module minitia_std::object { public fun owner(object: Object): address acquires ObjectCore { assert!( exists(object.inner), - error::not_found(EOBJECT_DOES_NOT_EXIST), + error::not_found(EOBJECT_DOES_NOT_EXIST) ); borrow_global(object.inner).owner } @@ -575,7 +579,7 @@ module minitia_std::object { assert!( exists(current_address), - error::not_found(EOBJECT_DOES_NOT_EXIST), + error::not_found(EOBJECT_DOES_NOT_EXIST) ); let object = borrow_global(current_address); @@ -586,7 +590,7 @@ module minitia_std::object { count = count + 1; assert!( count < MAXIMUM_OBJECT_NESTING, - error::out_of_range(EMAXIMUM_NESTING), + error::out_of_range(EMAXIMUM_NESTING) ); if (!exists(current_address)) { return false @@ -609,12 +613,12 @@ module minitia_std::object { #[event] #[test_only] struct HeroEquipEvent has drop, store { - weapon_id: Option>, + weapon_id: Option> } #[test_only] struct Hero has key { - weapon: Option>, + weapon: Option> } #[test_only] @@ -624,7 +628,7 @@ module minitia_std::object { public fun create_hero(creator: &signer): (ConstructorRef, Object) acquires Tombstone { let hero_constructor_ref = create_deletable_named_object(creator, b"hero"); let hero_signer = generate_signer(&hero_constructor_ref); - move_to(&hero_signer, Hero { weapon: option::none(), }); + move_to(&hero_signer, Hero { weapon: option::none() }); let hero = object_from_constructor_ref(&hero_constructor_ref); (hero_constructor_ref, hero) @@ -647,9 +651,7 @@ module minitia_std::object { #[test_only] public fun hero_equip( - owner: &signer, - hero: Object, - weapon: Object, + owner: &signer, hero: Object, weapon: Object ) acquires Hero, ObjectCore { transfer_to_object(owner, weapon, hero); let hero_obj = borrow_global_mut(object_address(&hero)); @@ -659,14 +661,12 @@ module minitia_std::object { #[test_only] public fun hero_unequip( - owner: &signer, - hero: Object, - weapon: Object, + owner: &signer, hero: Object, weapon: Object ) acquires Hero, ObjectCore { transfer( owner, weapon, - signer::address_of(owner), + signer::address_of(owner) ); let hero = borrow_global_mut(object_address(&hero)); option::extract(&mut hero.weapon); @@ -734,7 +734,9 @@ module minitia_std::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 0x50009, location = Self)] - fun test_cannot_use_transfer_ref_with_old_version(creator: &signer) acquires Tombstone, ObjectCore, Hero { + fun test_cannot_use_transfer_ref_with_old_version( + creator: &signer + ) acquires Tombstone, ObjectCore, Hero { let (hero_constructor, _) = create_hero(creator); let delete_ref = generate_delete_ref(&hero_constructor); let transfer_ref = generate_transfer_ref(&hero_constructor); @@ -747,7 +749,9 @@ module minitia_std::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 0x50009, location = Self)] - fun test_cannot_use_transfer_ref_with_old_version2(creator: &signer) acquires Tombstone, ObjectCore, Hero { + fun test_cannot_use_transfer_ref_with_old_version2( + creator: &signer + ) acquires Tombstone, ObjectCore, Hero { let (hero_constructor, _) = create_hero(creator); let delete_ref = generate_delete_ref(&hero_constructor); let transfer_ref = generate_transfer_ref(&hero_constructor); @@ -760,7 +764,9 @@ module minitia_std::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 0x50009, location = Self)] - fun test_cannot_use_transfer_ref_with_old_version3(creator: &signer) acquires Tombstone, ObjectCore, Hero { + fun test_cannot_use_transfer_ref_with_old_version3( + creator: &signer + ) acquires Tombstone, ObjectCore, Hero { let (hero_constructor, _) = create_hero(creator); let delete_ref = generate_delete_ref(&hero_constructor); let transfer_ref = generate_transfer_ref(&hero_constructor); @@ -773,7 +779,9 @@ module minitia_std::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 0x50009, location = Self)] - fun test_cannot_use_delete_ref_with_old_version(creator: &signer) acquires Tombstone, ObjectCore, Hero { + fun test_cannot_use_delete_ref_with_old_version( + creator: &signer + ) acquires Tombstone, ObjectCore, Hero { let (hero_constructor, _) = create_hero(creator); let delete_ref = generate_delete_ref(&hero_constructor); let delete_ref2 = generate_delete_ref(&hero_constructor); @@ -786,7 +794,9 @@ module minitia_std::object { #[test(creator = @0x123)] #[expected_failure(abort_code = 0x50009, location = Self)] - fun test_cannot_use_extend_ref_with_old_version(creator: &signer) acquires Tombstone, ObjectCore, Hero { + fun test_cannot_use_extend_ref_with_old_version( + creator: &signer + ) acquires Tombstone, ObjectCore, Hero { let (hero_constructor, _) = create_hero(creator); let delete_ref = generate_delete_ref(&hero_constructor); let extend_ref = generate_extend_ref(&hero_constructor); diff --git a/minitia_stdlib/sources/object_code_deployment.move b/minitia_stdlib/sources/object_code_deployment.move new file mode 100644 index 0000000..d34b2e5 --- /dev/null +++ b/minitia_stdlib/sources/object_code_deployment.move @@ -0,0 +1,146 @@ +/// This module allows users to deploy, upgrade and freeze modules deployed to objects on-chain. +/// This enables users to deploy modules to an object with a unique address each time they are published. +/// This modules provides an alternative method to publish code on-chain, where code is deployed to objects rather than accounts. +/// This is encouraged as it abstracts the necessary resources needed for deploying modules, +/// along with the required authorization to upgrade and freeze modules. +/// +/// The functionalities of this module are as follows. +/// +/// Publishing modules flow: +/// 1. Create a new object with the address derived from the publisher address and the object seed. +/// 2. Publish the module passed in the function via `metadata_serialized` and `code` to the newly created object. +/// 3. Emits 'Publish' event with the address of the newly created object. +/// 4. Create a `ManagingRefs` which stores the extend ref of the newly created object. +/// Note: This is needed to upgrade the code as the signer must be generated to upgrade the existing code in an object. +/// +/// Upgrading modules flow: +/// 1. Assert the `code_object` passed in the function is owned by the `publisher`. +/// 2. Assert the `code_object` passed in the function exists in global storage. +/// 2. Retrieve the `ExtendRef` from the `code_object` and generate the signer from this. +/// 3. Upgrade the module with the `metadata_serialized` and `code` passed in the function. +/// 4. Emits 'Upgrade' event with the address of the object with the upgraded code. +/// Note: If the modules were deployed as immutable when calling `publish`, the upgrade will fail. +/// +/// Freezing modules flow: +/// 1. Assert the `code_object` passed in the function exists in global storage. +/// 2. Assert the `code_object` passed in the function is owned by the `publisher`. +/// 3. Mark all the modules in the `code_object` as immutable. +/// 4. Emits 'Freeze' event with the address of the object with the frozen code. +/// Note: There is no unfreeze function as this gives no benefit if the user can freeze/unfreeze modules at will. +/// Once modules are marked as immutable, they cannot be made mutable again. +module minitia_std::object_code_deployment { + use std::bcs; + use std::error; + use std::signer; + use std::vector; + use minitia_std::account; + use minitia_std::code::{Self, MetadataStore}; + use minitia_std::event; + use minitia_std::object; + use minitia_std::object::{ExtendRef, Object}; + use minitia_std::string::String; + + /// Object code deployment feature not supported. + const EOBJECT_CODE_DEPLOYMENT_NOT_SUPPORTED: u64 = 1; + /// Not the owner of the `code_object` + const ENOT_CODE_OBJECT_OWNER: u64 = 2; + /// `code_object` does not exist. + const ECODE_OBJECT_DOES_NOT_EXIST: u64 = 3; + + const OBJECT_CODE_DEPLOYMENT_DOMAIN_SEPARATOR: vector = b"minitia_std::object_code_deployment"; + + /// Internal struct, attached to the object, that holds Refs we need to manage the code deployment (i.e. upgrades). + struct ManagingRefs has key { + /// We need to keep the extend ref to be able to generate the signer to upgrade existing code. + extend_ref: ExtendRef + } + + #[event] + /// Event emitted when code is published to an object. + struct Publish has drop, store { + object_address: address + } + + #[event] + /// Event emitted when code in an existing object is upgraded. + struct Upgrade has drop, store { + object_address: address + } + + #[event] + /// Event emitted when code in an existing object is made immutable. + struct Freeze has drop, store { + object_address: address + } + + /// Creates a new object with a unique address derived from the publisher address and the object seed. + /// Publishes the code passed in the function to the newly created object. + /// The caller must provide package metadata describing the package via `metadata_serialized` and + /// the code to be published via `code`. This contains a vector of modules to be deployed on-chain. + public entry fun publish( + publisher: &signer, module_ids: vector, code: vector> + ) { + let publisher_address = signer::address_of(publisher); + let object_seed = object_seed(publisher_address); + let constructor_ref = &object::create_named_object(publisher, object_seed); + let code_signer = &object::generate_signer(constructor_ref); + code::publish(code_signer, module_ids, code, 1); + + event::emit(Publish { object_address: signer::address_of(code_signer) }); + + move_to( + code_signer, + ManagingRefs { extend_ref: object::generate_extend_ref(constructor_ref) } + ); + } + + inline fun object_seed(publisher: address): vector { + let sequence_number = account::get_sequence_number(publisher) + 1; + let seeds = vector[]; + vector::append( + &mut seeds, bcs::to_bytes(&OBJECT_CODE_DEPLOYMENT_DOMAIN_SEPARATOR) + ); + vector::append(&mut seeds, bcs::to_bytes(&sequence_number)); + seeds + } + + /// Upgrades the existing modules at the `code_object` address with the new modules passed in `code`, + /// along with the metadata `metadata_serialized`. + /// Note: If the modules were deployed as immutable when calling `publish`, the upgrade will fail. + /// Requires the publisher to be the owner of the `code_object`. + public entry fun upgrade( + publisher: &signer, + module_ids: vector, + code: vector>, + code_object: Object + ) acquires ManagingRefs { + let publisher_address = signer::address_of(publisher); + assert!( + object::is_owner(code_object, publisher_address), + error::permission_denied(ENOT_CODE_OBJECT_OWNER) + ); + + let code_object_address = object::object_address(&code_object); + assert!( + exists(code_object_address), + error::not_found(ECODE_OBJECT_DOES_NOT_EXIST) + ); + + let extend_ref = &borrow_global(code_object_address).extend_ref; + let code_signer = &object::generate_signer_for_extending(extend_ref); + code::publish(code_signer, module_ids, code, 1); + + event::emit(Upgrade { object_address: signer::address_of(code_signer) }); + } + + /// Make an existing upgradable package immutable. Once this is called, the package cannot be made upgradable again. + /// Each `code_object` should only have one package, as one package is deployed per object in this module. + /// Requires the `publisher` to be the owner of the `code_object`. + public entry fun freeze_code_object( + publisher: &signer, code_object: Object + ) { + code::freeze_code_object(publisher, code_object); + + event::emit(Freeze { object_address: object::object_address(&code_object) }); + } +} diff --git a/minitia_stdlib/sources/oracle.move b/minitia_stdlib/sources/oracle.move index 64432df..aeddb8a 100644 --- a/minitia_stdlib/sources/oracle.move +++ b/minitia_stdlib/sources/oracle.move @@ -19,13 +19,16 @@ module minitia_std::oracle { *string::bytes(pair_id), price, updated_at, - decimals, + decimals ) } #[test_only] native fun set_price_internal( - pair_id: vector, price: u256, updated_at: u64, decimals: u64 + pair_id: vector, + price: u256, + updated_at: u64, + decimals: u64 ); #[test] @@ -46,13 +49,13 @@ module minitia_std::oracle { &btc_usd_pair_id, btc_price, btc_updated_at, - btc_decimals, + btc_decimals ); set_price( ð_usd_pair_id, eth_price, eth_updated_at, - eth_decimals, + eth_decimals ); let (price, updated_at, decimals) = get_price(btc_usd_pair_id); diff --git a/minitia_stdlib/sources/query.move b/minitia_stdlib/sources/query.move index 74cd022..a4ae5e5 100644 --- a/minitia_stdlib/sources/query.move +++ b/minitia_stdlib/sources/query.move @@ -36,7 +36,7 @@ module minitia_std::query { */ struct ProposalRequest has copy, drop { - proposal_id: u64, + proposal_id: u64 } struct ProposalResponse has copy, drop { @@ -45,7 +45,7 @@ module minitia_std::query { summary: String, status: String, submit_time: String, - emergency: bool, + emergency: bool } #[view] @@ -53,7 +53,7 @@ module minitia_std::query { let response = query_stargate( b"/initia.gov.v1.Query/Proposal", - json::marshal(&ProposalRequest { proposal_id, }), + json::marshal(&ProposalRequest { proposal_id }) ); let res = json::unmarshal(response); (res.id, res.title, res.summary, string::utf8(response)) @@ -64,7 +64,7 @@ module minitia_std::query { let response = query_stargate( b"/initia.gov.v1.Query/Proposal", - json::marshal(&ProposalRequest { proposal_id, }), + json::marshal(&ProposalRequest { proposal_id }) ); let res = json::unmarshal(response); (res.id, res.status, res.submit_time, res.emergency) @@ -79,6 +79,11 @@ module minitia_std::query { path_or_name: vector, data: vector, response: vector ); + #[test_only] + native public fun unset_query_response( + path_or_name: vector, data: vector + ); + #[test] fun test_query_custom() { set_query_response(b"path", b"data123", b"output"); @@ -94,4 +99,14 @@ module minitia_std::query { let res = query_stargate(b"path", b"data123"); assert!(res == b"output", 0); } + + #[test] + #[expected_failure(abort_code = 0x1006E, location = Self)] + fun test_query_unsset() { + set_query_response(b"path", b"data123", b"output"); + unset_query_response(b"path", b"data123"); + + let res = query_custom(b"path", b"data123"); + assert!(res == b"", 0); + } } diff --git a/minitia_stdlib/sources/simple_map.move b/minitia_stdlib/sources/simple_map.move index 5ba9040..4db63b9 100644 --- a/minitia_stdlib/sources/simple_map.move +++ b/minitia_stdlib/sources/simple_map.move @@ -1,151 +1,216 @@ -/// This module provides a solution for sorted maps, that is it has the properties that +/// This module provides a solution for unsorted maps, that is it has the properties that /// 1) Keys point to Values /// 2) Each Key must be unique -/// 3) A Key can be found within O(Log N) time -/// 4) The data is stored as a sorted by Key +/// 3) A Key can be found within O(N) time +/// 4) The keys are unsorted. /// 5) Adds and removals take O(N) time module minitia_std::simple_map { use std::error; use std::option; use std::vector; - use minitia_std::comparator; - const EKEY_ALREADY_EXISTS: u64 = 0; - const EKEY_NOT_FOUND: u64 = 1; + /// Map key already exists + const EKEY_ALREADY_EXISTS: u64 = 1; + /// Map key is not found + const EKEY_NOT_FOUND: u64 = 2; struct SimpleMap has copy, drop, store { - data: vector>, + data: vector> } struct Element has copy, drop, store { key: Key, - value: Value, + value: Value } - public fun length(map: &SimpleMap): u64 { - vector::length(&map.data) + public fun length(self: &SimpleMap): u64 { + vector::length(&self.data) } + /// Create an empty SimpleMap. + public fun new(): SimpleMap { + SimpleMap { data: vector::empty() } + } + + /// Create a SimpleMap from a vector of keys and values. The keys must be unique. + public fun new_from( + keys: vector, values: vector + ): SimpleMap { + let map = new(); + add_all(&mut map, keys, values); + map + } + + #[deprecated] + /// Create an empty SimpleMap. + /// This function is deprecated, use `new` instead. public fun create(): SimpleMap { - SimpleMap { data: vector::empty(), } + new() } public fun borrow( - map: &SimpleMap, key: &Key, + self: &SimpleMap, key: &Key ): &Value { - let (maybe_idx, _) = find(map, key); - assert!( - option::is_some(&maybe_idx), - error::invalid_argument(EKEY_NOT_FOUND), - ); + let maybe_idx = find(self, key); + assert!(option::is_some(&maybe_idx), error::invalid_argument(EKEY_NOT_FOUND)); let idx = option::extract(&mut maybe_idx); - &vector::borrow(&map.data, idx).value + &vector::borrow(&self.data, idx).value } public fun borrow_mut( - map: &mut SimpleMap, key: &Key, + self: &mut SimpleMap, key: &Key ): &mut Value { - let (maybe_idx, _) = find(map, key); - assert!( - option::is_some(&maybe_idx), - error::invalid_argument(EKEY_NOT_FOUND), - ); + let maybe_idx = find(self, key); + assert!(option::is_some(&maybe_idx), error::invalid_argument(EKEY_NOT_FOUND)); let idx = option::extract(&mut maybe_idx); - &mut vector::borrow_mut(&mut map.data, idx).value + &mut vector::borrow_mut(&mut self.data, idx).value } public fun contains_key( - map: &SimpleMap, key: &Key, + self: &SimpleMap, key: &Key ): bool { - let (maybe_idx, _) = find(map, key); + let maybe_idx = find(self, key); option::is_some(&maybe_idx) } public fun destroy_empty( - map: SimpleMap + self: SimpleMap ) { - let SimpleMap { data } = map; + let SimpleMap { data } = self; vector::destroy_empty(data); } + /// Add a key/value pair to the map. The key must not already exist. public fun add( - map: &mut SimpleMap, + self: &mut SimpleMap, key: Key, - value: Value, + value: Value ) { - let (maybe_idx, maybe_placement) = find(map, &key); - assert!( - option::is_none(&maybe_idx), - error::invalid_argument(EKEY_ALREADY_EXISTS), - ); + let maybe_idx = find(self, &key); + assert!(option::is_none(&maybe_idx), error::invalid_argument(EKEY_ALREADY_EXISTS)); - // Append to the end and then swap elements until the list is ordered again - vector::push_back(&mut map.data, Element { key, value }); - - let placement = option::extract(&mut maybe_placement); - let end = vector::length(&map.data) - 1; - while (placement < end) { - vector::swap(&mut map.data, placement, end); - placement = placement + 1; - }; + vector::push_back(&mut self.data, Element { key, value }); } - public fun remove( - map: &mut SimpleMap, key: &Key, - ): (Key, Value) { - let (maybe_idx, _) = find(map, key); - assert!( - option::is_some(&maybe_idx), - error::invalid_argument(EKEY_NOT_FOUND), + /// Add multiple key/value pairs to the map. The keys must not already exist. + public fun add_all( + self: &mut SimpleMap, + keys: vector, + values: vector + ) { + vector::zip( + keys, + values, + |key, value| { + add(self, key, value); + } ); + } - let placement = option::extract(&mut maybe_idx); - let end = vector::length(&map.data) - 1; - - while (placement < end) { - vector::swap( - &mut map.data, - placement, - placement + 1, - ); - placement = placement + 1; + /// Insert key/value pair or update an existing key to a new value + public fun upsert( + self: &mut SimpleMap, + key: Key, + value: Value + ): (std::option::Option, std::option::Option) { + let data = &mut self.data; + let len = vector::length(data); + let i = 0; + while (i < len) { + let element = vector::borrow(data, i); + if (&element.key == &key) { + vector::push_back(data, Element { key, value }); + vector::swap(data, i, len); + let Element { key, value } = vector::pop_back(data); + return (std::option::some(key), std::option::some(value)) + }; + i = i + 1; }; + vector::push_back(&mut self.data, Element { key, value }); + (std::option::none(), std::option::none()) + } - let Element { key, value } = vector::pop_back(&mut map.data); - (key, value) + /// Return all keys in the map. This requires keys to be copyable. + public fun keys(self: &SimpleMap): vector { + vector::map_ref( + &self.data, + |e| { + let e: &Element = e; + e.key + } + ) } - fun find( - map: &SimpleMap, key: &Key, - ): (option::Option, option::Option) { - let length = vector::length(&map.data); + /// Return all values in the map. This requires values to be copyable. + public fun values(self: &SimpleMap): vector { + vector::map_ref( + &self.data, + |e| { + let e: &Element = e; + e.value + } + ) + } - if (length == 0) { - return (option::none(), option::some(0)) - }; + /// Transform the map into two vectors with the keys and values respectively + /// Primarily used to destroy a map + public fun to_vec_pair( + self: SimpleMap + ): (vector, vector) { + let keys: vector = vector::empty(); + let values: vector = vector::empty(); + let SimpleMap { data } = self; + vector::for_each( + data, + |e| { + let Element { key, value } = e; + vector::push_back(&mut keys, key); + vector::push_back(&mut values, value); + } + ); + (keys, values) + } - let left = 0; - let right = length; + /// For maps that cannot be dropped this is a utility to destroy them + /// using lambdas to destroy the individual keys and values. + public inline fun destroy( + self: SimpleMap, + dk: |Key|, + dv: |Value| + ) { + let (keys, values) = to_vec_pair(self); + vector::destroy(keys, |_k| dk(_k)); + vector::destroy(values, |_v| dv(_v)); + } - while (left != right) { - let mid = (left + right) / 2; - let potential_key = &vector::borrow(&map.data, mid).key; - if (comparator::is_smaller_than(&comparator::compare(potential_key, key))) { - left = mid + 1; - } else { - right = mid; + /// Remove a key/value pair from the map. The key must exist. + public fun remove( + self: &mut SimpleMap, key: &Key + ): (Key, Value) { + let maybe_idx = find(self, key); + assert!(option::is_some(&maybe_idx), error::invalid_argument(EKEY_NOT_FOUND)); + let placement = option::extract(&mut maybe_idx); + let Element { key, value } = vector::swap_remove(&mut self.data, placement); + (key, value) + } + + fun find( + self: &SimpleMap, key: &Key + ): option::Option { + let leng = vector::length(&self.data); + let i = 0; + while (i < leng) { + let element = vector::borrow(&self.data, i); + if (&element.key == key) { + return option::some(i) }; + i = i + 1; }; - - if (left != length && key == &vector::borrow(&map.data, left).key) { - (option::some(left), option::none()) - } else { - (option::none(), option::some(left)) - } + option::none() } #[test] - public fun add_remove_many() { + public fun test_add_remove_many() { let map = create(); assert!(length(&map) == 0, 0); @@ -178,41 +243,45 @@ module minitia_std::simple_map { } #[test] - public fun test_several() { + public fun test_add_all() { let map = create(); - add(&mut map, 6, 6); - add(&mut map, 1, 1); - add(&mut map, 5, 5); - add(&mut map, 2, 2); - add(&mut map, 3, 3); - add(&mut map, 0, 0); - add(&mut map, 7, 7); - add(&mut map, 4, 4); - - let idx = 0; - while (idx < vector::length(&map.data)) { - assert!( - idx == vector::borrow(&map.data, idx).key, - idx, - ); - idx = idx + 1; - }; - remove(&mut map, &0); + assert!(length(&map) == 0, 0); + add_all(&mut map, vector[1, 2, 3], vector[10, 20, 30]); + assert!(length(&map) == 3, 1); + assert!(borrow(&map, &1) == &10, 2); + assert!(borrow(&map, &2) == &20, 3); + assert!(borrow(&map, &3) == &30, 4); + remove(&mut map, &1); remove(&mut map, &2); remove(&mut map, &3); - remove(&mut map, &4); - remove(&mut map, &5); - remove(&mut map, &6); - remove(&mut map, &7); - destroy_empty(map); } + #[test] + public fun test_keys() { + let map = create(); + assert!(keys(&map) == vector[], 0); + add(&mut map, 2, 1); + add(&mut map, 3, 1); + + assert!(keys(&map) == vector[2, 3], 0); + } + + #[test] + public fun test_values() { + let map = create(); + assert!(values(&map) == vector[], 0); + add(&mut map, 2, 1); + add(&mut map, 3, 2); + + assert!(values(&map) == vector[1, 2], 0); + } + #[test] #[expected_failure] - public fun add_twice() { + public fun test_add_twice() { let map = create(); add(&mut map, 3, 1); add(&mut map, 3, 1); @@ -223,7 +292,7 @@ module minitia_std::simple_map { #[test] #[expected_failure] - public fun remove_twice() { + public fun test_remove_twice() { let map = create(); add(&mut map, 3, 1); remove(&mut map, &3); @@ -231,4 +300,28 @@ module minitia_std::simple_map { destroy_empty(map); } + + #[test] + public fun test_upsert_test() { + let map = create(); + // test adding 3 elements using upsert + upsert(&mut map, 1, 1); + upsert(&mut map, 2, 2); + upsert(&mut map, 3, 3); + + assert!(length(&map) == 3, 0); + assert!(contains_key(&map, &1), 1); + assert!(contains_key(&map, &2), 2); + assert!(contains_key(&map, &3), 3); + assert!(borrow(&map, &1) == &1, 4); + assert!(borrow(&map, &2) == &2, 5); + assert!(borrow(&map, &3) == &3, 6); + + // change mapping 1->1 to 1->4 + upsert(&mut map, 1, 4); + + assert!(length(&map) == 3, 7); + assert!(contains_key(&map, &1), 8); + assert!(borrow(&map, &1) == &4, 9); + } } diff --git a/minitia_stdlib/sources/string_utils.move b/minitia_stdlib/sources/string_utils.move index 8069895..cbeb25c 100644 --- a/minitia_stdlib/sources/string_utils.move +++ b/minitia_stdlib/sources/string_utils.move @@ -63,7 +63,7 @@ module minitia_std::string_utils { // Helper struct to allow passing a generic heterogeneous list of values to native_format_list. struct Cons has copy, drop, store { car: T, - cdr: N, + cdr: N } struct NIL has copy, drop, store {} @@ -81,15 +81,18 @@ module minitia_std::string_utils { // Create a list of values. inline fun list1(a: T0): Cons { cons(a, nil()) - } inline fun list2(a: T0, b: T1): Cons> { + } + inline fun list2(a: T0, b: T1): Cons> { cons(a, list1(b)) - } inline fun list3(a: T0, b: T1, c: T2): Cons>> { + } + inline fun list3(a: T0, b: T1, c: T2): Cons>> { cons(a, list2(b, c)) - } inline fun list4(a: T0, b: T1, c: T2, d: T3) + } - : Cons>>> { + inline fun list4(a: T0, b: T1, c: T2, d: T3): + Cons>>> { cons(a, list3(b, c, d)) } @@ -107,32 +110,32 @@ module minitia_std::string_utils { fun test_format() { assert!( to_string(&1u64) == std::string::utf8(b"1"), - 1, + 1 ); assert!( to_string(&false) == std::string::utf8(b"false"), - 2, + 2 ); assert!( to_string(&1u256) == std::string::utf8(b"1"), - 3, + 3 ); assert!( to_string(&vector[1, 2, 3]) == std::string::utf8(b"[ 1, 2, 3 ]"), - 4, + 4 ); assert!( to_string(&cons(std::string::utf8(b"My string"), 2)) == std::string::utf8(b"Cons { car: \"My string\", cdr: 2 }"), - 5, + 5 ); assert!( to_string(&std::option::none()) == std::string::utf8(b"None"), - 6, + 6 ); assert!( to_string(&std::option::some(1)) == std::string::utf8(b"Some(1)"), - 7, + 7 ); } @@ -142,11 +145,11 @@ module minitia_std::string_utils { &b"a = {} b = {} c = {}", 1, 2, - std::string::utf8(b"My string"), + std::string::utf8(b"My string") ); assert!( s == std::string::utf8(b"a = 1 b = 2 c = \"My string\""), - 1, + 1 ); } @@ -172,7 +175,7 @@ module minitia_std::string_utils { /// #[test_only] struct FakeCons has copy, drop, store { car: T, - cdr: N, + cdr: N } #[test] @@ -205,7 +208,7 @@ module minitia_std::string_utils { let s = format3(&b"{{a = {} b = {} c = {}}}", 1, 2, 3); assert!( s == std::string::utf8(b"{a = 1 b = 2 c = 3}"), - 1, + 1 ); } } diff --git a/minitia_stdlib/sources/table.move b/minitia_stdlib/sources/table.move index e4cad90..32f1df9 100644 --- a/minitia_stdlib/sources/table.move +++ b/minitia_stdlib/sources/table.move @@ -15,26 +15,26 @@ module minitia_std::table { /// Type of tables struct Table has store { handle: address, - length: u64, + length: u64 } /// Type of table iterators struct TableIter has drop { - iterator_id: u64, + iterator_id: u64 } /// Create a new Table. public fun new(): Table { let handle = new_table_handle(); account::create_table_account(handle); - Table { handle, length: 0, } + Table { handle, length: 0 } } /// Destroy a table. The table must be empty to succeed. public fun destroy_empty(table: Table) { assert!( table.length == 0, - error::invalid_state(ENOT_EMPTY), + error::invalid_state(ENOT_EMPTY) ); destroy_empty_box>(&table); drop_unchecked_box>(table) @@ -155,7 +155,7 @@ module minitia_std::table { table: &Table, start: Option, /* inclusive */ end: Option, /* exclusive */ - order: u8 /* 1: Ascending, 2: Descending */, + order: u8 /* 1: Ascending, 2: Descending */ ): &TableIter { let start_bytes: vector = if (option::is_some(&start)) { @@ -186,13 +186,13 @@ module minitia_std::table { /// Create mutable iterator for `table`. /// A user has to check `prepare` before calling `next` to prevent abort. /// - /// let iter = table::iter_mut(&t, start, end, order); + /// let iter = table::iter_mut(&mut t, start, end, order); /// loop { - /// if (!table::prepare_mut(&mut iter)) { + /// if (!table::prepare_mut(iter)) { /// break; /// } /// - /// let (key, value) = table::next_mut(&mut iter); + /// let (key, value) = table::next_mut(iter); /// } /// /// NOTE: The default BCS number encoding follows the Little Endian method. @@ -204,7 +204,7 @@ module minitia_std::table { table: &mut Table, start: Option, /* inclusive */ end: Option, /* exclusive */ - order: u8 /* 1: Ascending, 2: Descending */, + order: u8 /* 1: Ascending, 2: Descending */ ): &mut TableIter { let start_bytes: vector = if (option::is_some(&start)) { @@ -246,35 +246,51 @@ module minitia_std::table { // can use this to determine serialization layout. native fun new_table_handle(): address; - native fun add_box(table: &mut Table, key: K, val: Box); + native fun add_box( + table: &mut Table, key: K, val: Box + ); native fun borrow_box(table: &Table, key: K): &Box; - native fun borrow_box_mut(table: &mut Table, key: K): &mut Box; + native fun borrow_box_mut( + table: &mut Table, key: K + ): &mut Box; native fun contains_box(table: &Table, key: K): bool; - native fun remove_box(table: &mut Table, key: K): Box; + native fun remove_box( + table: &mut Table, key: K + ): Box; native fun destroy_empty_box(table: &Table); native fun drop_unchecked_box(table: Table); native fun new_table_iter( - table: &Table, start: vector, end: vector, order: u8 + table: &Table, + start: vector, + end: vector, + order: u8 ): &TableIter; native fun new_table_iter_mut( - table: &mut Table, start: vector, end: vector, order: u8 + table: &mut Table, + start: vector, + end: vector, + order: u8 ): &mut TableIter; native fun next_box(table_iter: &TableIter): (K, &Box); native fun prepare_box(table_iter: &TableIter): bool; - native fun next_box_mut(table_iter: &mut TableIter): (K, &mut Box); + native fun next_box_mut( + table_iter: &mut TableIter + ): (K, &mut Box); - native fun prepare_box_mut(table_iter: &mut TableIter): bool; + native fun prepare_box_mut( + table_iter: &mut TableIter + ): bool; // ====================================================================================================== // Tests @@ -306,12 +322,12 @@ module minitia_std::table { assert!(!contains(&t, key), error_code); assert!( *borrow_with_default(&t, key, &12) == 12, - error_code, + error_code ); add(&mut t, key, 1); assert!( *borrow_with_default(&t, key, &12) == 1, - error_code, + error_code ); move_to(&account, TableHolder { t }); @@ -333,4 +349,14 @@ module minitia_std::table { move_to(account, TableHolder { t }); } + + #[test(account = @0x1, account2 = @0x2)] + fun test_address_uniqueness(account: &signer, account2: &signer) { + let t1 = new(); + let t2 = new(); + assert!(handle(&t1) != handle(&t2), 1); + + move_to(account, TableHolder { t: t1 }); + move_to(account2, TableHolder { t: t2 }); + } } diff --git a/minitia_stdlib/sources/token/collection.move b/minitia_stdlib/sources/token/collection.move index 10abc71..e151d53 100644 --- a/minitia_stdlib/sources/token/collection.move +++ b/minitia_stdlib/sources/token/collection.move @@ -62,12 +62,12 @@ module minitia_std::collection { /// storage; the URL length will likely need a maximum any suggestions? uri: String, /// index to object map. - nfts: Table, + nfts: Table } /// This enables mutating description and URI by higher level services. struct MutatorRef has drop, store { - self: address, + self: address } #[event] @@ -86,39 +86,39 @@ module minitia_std::collection { /// Total minted - total burned current_supply: u64, max_supply: u64, - total_minted: u64, + total_minted: u64 } /// Unlimited supply tracker, this is useful for adding events and supply tracking to a collection. struct UnlimitedSupply has key { current_supply: u64, - total_minted: u64, + total_minted: u64 } struct NftResponse has drop { token_id: String, - nft: address, + nft: address } #[event] struct CreateCollectionEvent has drop, store { collection: address, creator: address, - name: String, + name: String } #[event] struct BurnEvent has drop, store { collection: address, token_id: String, - nft: address, + nft: address } #[event] struct MintEvent has drop, store { collection: address, token_id: String, - nft: address, + nft: address } /// Creates a fixed-sized collection, or a collection that supports a fixed amount of nfts. @@ -132,16 +132,16 @@ module minitia_std::collection { max_supply: u64, name: String, royalty: Option, - uri: String, + uri: String ): ConstructorRef { assert!( max_supply != 0, - error::invalid_argument(EMAX_SUPPLY_CANNOT_BE_ZERO), + error::invalid_argument(EMAX_SUPPLY_CANNOT_BE_ZERO) ); let collection_seed = create_collection_seed(&name); let constructor_ref = object::create_named_object(creator, collection_seed); - let supply = FixedSupply { current_supply: 0, max_supply, total_minted: 0, }; + let supply = FixedSupply { current_supply: 0, max_supply, total_minted: 0 }; create_collection_internal( creator, @@ -150,7 +150,7 @@ module minitia_std::collection { name, royalty, uri, - option::some(supply), + option::some(supply) ) } @@ -161,12 +161,12 @@ module minitia_std::collection { description: String, name: String, royalty: Option, - uri: String, + uri: String ): ConstructorRef { let collection_seed = create_collection_seed(&name); let constructor_ref = object::create_named_object(creator, collection_seed); - let supply = UnlimitedSupply { current_supply: 0, total_minted: 0, }; + let supply = UnlimitedSupply { current_supply: 0, total_minted: 0 }; create_collection_internal( creator, @@ -175,7 +175,7 @@ module minitia_std::collection { name, royalty, uri, - option::some(supply), + option::some(supply) ) } @@ -187,7 +187,7 @@ module minitia_std::collection { description: String, name: String, royalty: Option, - uri: String, + uri: String ): ConstructorRef { let collection_seed = create_collection_seed(&name); let constructor_ref = object::create_named_object(creator, collection_seed); @@ -199,7 +199,7 @@ module minitia_std::collection { name, royalty, uri, - option::none(), + option::none() ) } @@ -207,11 +207,11 @@ module minitia_std::collection { let len = string::length(name); assert!( len <= MAX_COLLECTION_NAME_LENGTH, - error::out_of_range(ECOLLECTION_NAME_TOO_LONG), + error::out_of_range(ECOLLECTION_NAME_TOO_LONG) ); assert!( - string::index_of(name, &string::utf8(b"::")) == len, - error::invalid_argument(EINVALID_COLLECTION_NAME), + string::index_of(name, &string::utf8(b":")) == len, + error::invalid_argument(EINVALID_COLLECTION_NAME) ); } @@ -222,17 +222,17 @@ module minitia_std::collection { name: String, royalty: Option, uri: String, - supply: Option, + supply: Option ): ConstructorRef { assert_collection_name(&name); assert!( string::length(&uri) <= MAX_URI_LENGTH, - error::out_of_range(EURI_TOO_LONG), + error::out_of_range(EURI_TOO_LONG) ); assert!( string::length(&description) <= MAX_DESCRIPTION_LENGTH, - error::out_of_range(EDESCRIPTION_TOO_LONG), + error::out_of_range(EDESCRIPTION_TOO_LONG) ); let object_signer = &object::generate_signer(&constructor_ref); @@ -243,14 +243,14 @@ module minitia_std::collection { description, name, uri, - nfts: table::new(), + nfts: table::new() }; move_to(object_signer, collection); if (option::is_some(&supply)) { move_to( object_signer, - option::destroy_some(supply), + option::destroy_some(supply) ); let collection_addr = signer::address_of(object_signer); event::emit( @@ -258,7 +258,7 @@ module minitia_std::collection { collection: collection_addr, creator: creator_addr, name - }, + } ); } else { option::destroy_none(supply) @@ -267,13 +267,10 @@ module minitia_std::collection { if (option::is_some(&royalty)) { royalty::init( &constructor_ref, - option::extract(&mut royalty), + option::extract(&mut royalty) ) }; - let transfer_ref = object::generate_transfer_ref(&constructor_ref); - object::disable_ungated_transfer(&transfer_ref); - constructor_ref } @@ -286,16 +283,14 @@ module minitia_std::collection { public fun create_collection_seed(name: &String): vector { assert!( string::length(name) <= MAX_COLLECTION_NAME_LENGTH, - error::out_of_range(ECOLLECTION_NAME_TOO_LONG), + error::out_of_range(ECOLLECTION_NAME_TOO_LONG) ); *string::bytes(name) } /// Called by nft on mint to increment supply if there's an appropriate Supply struct. public(friend) fun increment_supply( - collection: Object, - token_id: String, - nft: address, + collection: Object, token_id: String, nft: address ) acquires Collection, FixedSupply, UnlimitedSupply { let collection_addr = object::object_address(&collection); let collection = borrow_global_mut(collection_addr); @@ -305,28 +300,22 @@ module minitia_std::collection { supply.total_minted = supply.total_minted + 1; assert!( supply.current_supply <= supply.max_supply, - error::out_of_range(ECOLLECTION_SUPPLY_EXCEEDED), + error::out_of_range(ECOLLECTION_SUPPLY_EXCEEDED) ); table::add(&mut collection.nfts, token_id, nft); - event::emit( - MintEvent { collection: collection_addr, token_id, nft }, - ); + event::emit(MintEvent { collection: collection_addr, token_id, nft }); } else if (exists(collection_addr)) { let supply = borrow_global_mut(collection_addr); supply.current_supply = supply.current_supply + 1; supply.total_minted = supply.total_minted + 1; table::add(&mut collection.nfts, token_id, nft); - event::emit( - MintEvent { collection: collection_addr, token_id, nft }, - ); + event::emit(MintEvent { collection: collection_addr, token_id, nft }); } } /// Called by nft on burn to decrement supply if there's an appropriate Supply struct. public(friend) fun decrement_supply( - collection: Object, - token_id: String, - nft: address, + collection: Object, token_id: String, nft: address ) acquires Collection, FixedSupply, UnlimitedSupply { let collection_addr = object::object_address(&collection); let collection = borrow_global_mut(collection_addr); @@ -334,16 +323,12 @@ module minitia_std::collection { let supply = borrow_global_mut(collection_addr); supply.current_supply = supply.current_supply - 1; table::remove(&mut collection.nfts, token_id); - event::emit( - BurnEvent { collection: collection_addr, token_id, nft }, - ); + event::emit(BurnEvent { collection: collection_addr, token_id, nft }); } else if (exists(collection_addr)) { let supply = borrow_global_mut(collection_addr); supply.current_supply = supply.current_supply - 1; table::remove(&mut collection.nfts, token_id); - event::emit( - BurnEvent { collection: collection_addr, token_id, nft }, - ); + event::emit(BurnEvent { collection: collection_addr, token_id, nft }); } } @@ -358,7 +343,7 @@ module minitia_std::collection { inline fun check_collection_exists(addr: address) { assert!( exists(addr), - error::not_found(ECOLLECTION_DOES_NOT_EXIST), + error::not_found(ECOLLECTION_DOES_NOT_EXIST) ); } @@ -409,9 +394,7 @@ module minitia_std::collection { /// get nft list from collection /// if `start_after` is not none, seach nfts in range (start_after, ...] public fun nfts( - collection: Object, - start_after: Option, - limit: u64, + collection: Object, start_after: Option, limit: u64 ): vector acquires Collection { let collection = borrow(collection); @@ -423,18 +406,18 @@ module minitia_std::collection { &collection.nfts, option::none(), start_after, - 2, + 2 ); let res: vector = vector[]; while (table::prepare(nfts_iter) - && vector::length(&res) < (limit as u64)) { + && vector::length(&res) < (limit as u64)) { let (token_id, nft) = table::next(nfts_iter); vector::push_back( &mut res, - NftResponse { token_id, nft: *nft, }, + NftResponse { token_id, nft: *nft } ); }; @@ -457,7 +440,7 @@ module minitia_std::collection { ) acquires Collection { assert!( string::length(&description) <= MAX_DESCRIPTION_LENGTH, - error::out_of_range(EDESCRIPTION_TOO_LONG), + error::out_of_range(EDESCRIPTION_TOO_LONG) ); let collection = borrow_mut(mutator_ref); event::emit( @@ -466,7 +449,7 @@ module minitia_std::collection { mutated_field_name: string::utf8(b"description"), old_value: collection.description, new_value: description - }, + } ); collection.description = description; } @@ -474,7 +457,7 @@ module minitia_std::collection { public fun set_uri(mutator_ref: &MutatorRef, uri: String) acquires Collection { assert!( string::length(&uri) <= MAX_URI_LENGTH, - error::out_of_range(EURI_TOO_LONG), + error::out_of_range(EURI_TOO_LONG) ); let collection = borrow_mut(mutator_ref); event::emit( @@ -483,7 +466,7 @@ module minitia_std::collection { mutated_field_name: string::utf8(b"uri"), old_value: collection.uri, new_value: uri - }, + } ); collection.uri = uri; } @@ -491,7 +474,9 @@ module minitia_std::collection { // Tests #[test(creator = @0x123)] - fun test_create_mint_burn_for_unlimited(creator: &signer) acquires Collection, FixedSupply, UnlimitedSupply { + fun test_create_mint_burn_for_unlimited( + creator: &signer + ) acquires Collection, FixedSupply, UnlimitedSupply { let creator_address = signer::address_of(creator); let name = string::utf8(b"collection name"); create_unlimited_collection( @@ -499,7 +484,7 @@ module minitia_std::collection { string::utf8(b""), name, option::none(), - string::utf8(b""), + string::utf8(b"") ); let collection_address = create_collection_address(creator_address, &name); let collection = object::address_to_object(collection_address); @@ -507,19 +492,21 @@ module minitia_std::collection { increment_supply( collection, string::utf8(b"token_id"), - @0x11111, + @0x11111 ); assert!(count(collection) == option::some(1), 0); decrement_supply( collection, string::utf8(b"token_id"), - @0x11112, + @0x11112 ); assert!(count(collection) == option::some(0), 0); } #[test(creator = @0x123)] - fun test_create_mint_burn_for_fixed(creator: &signer) acquires Collection, FixedSupply, UnlimitedSupply { + fun test_create_mint_burn_for_fixed( + creator: &signer + ) acquires Collection, FixedSupply, UnlimitedSupply { let creator_address = signer::address_of(creator); let name = string::utf8(b"collection name"); create_fixed_collection( @@ -528,7 +515,7 @@ module minitia_std::collection { 1, name, option::none(), - string::utf8(b""), + string::utf8(b"") ); let collection_address = create_collection_address(creator_address, &name); let collection = object::address_to_object(collection_address); @@ -536,26 +523,19 @@ module minitia_std::collection { increment_supply( collection, string::utf8(b"token_id"), - @0x11111, + @0x11111 ); assert!(count(collection) == option::some(1), 0); decrement_supply( collection, string::utf8(b"token_id"), - @0x11112, + @0x11112 ); assert!(count(collection) == option::some(0), 0); } - #[test(creator = @0x123)] - #[expected_failure(abort_code = 0x10007, location = Self)] - fun test_create_collection_with_invalid_name(creator: &signer) { - create_collection_helper(creator, string::utf8(b"collection::hello")); - } - - #[test(creator = @0x123, trader = @0x456)] - #[expected_failure(abort_code = 0x50003, location = minitia_std::object)] - entry fun test_create_and_transfer(creator: &signer, trader: &signer) { + #[test(creator = @0x123, receipient = @0x456)] + entry fun test_create_and_transfer(creator: &signer, receipient: &signer) { let creator_address = signer::address_of(creator); let collection_name = string::utf8(b"collection name"); create_collection_helper(creator, collection_name); @@ -566,15 +546,22 @@ module minitia_std::collection { ); assert!( object::owner(collection) == creator_address, - 1, + 1 ); object::transfer( creator, collection, - signer::address_of(trader), + signer::address_of(receipient) ); } + #[test(creator = @0x123)] + #[expected_failure(abort_code = 0x10007, location = Self)] + fun test_create_collection_with_invalid_name(creator: &signer) { + create_collection_helper(creator, string::utf8(b"collection::hello")); + } + + #[test(creator = @0x123)] #[expected_failure(abort_code = 0x80001, location = minitia_std::object)] entry fun test_duplicate_collection(creator: &signer) { @@ -591,8 +578,8 @@ module minitia_std::collection { object::address_to_object( create_collection_address( signer::address_of(creator), - &collection_name, - ), + &collection_name + ) ); let mutator_ref = generate_mutator_ref(&constructor_ref); let description = string::utf8(b"no fail"); @@ -610,8 +597,8 @@ module minitia_std::collection { object::address_to_object( create_collection_address( signer::address_of(creator), - &collection_name, - ), + &collection_name + ) ); let uri = string::utf8(b"no fail"); assert!(uri != uri(collection), 0); @@ -628,24 +615,24 @@ module minitia_std::collection { string::utf8(b""), name, option::none(), - string::utf8(b""), + string::utf8(b"") ); let collection_address = create_collection_address(creator_address, &name); let collection = object::address_to_object(collection_address); increment_supply( collection, string::utf8(b"1"), - @0x001, + @0x001 ); increment_supply( collection, string::utf8(b"2"), - @0x002, + @0x002 ); increment_supply( collection, string::utf8(b"3"), - @0x003, + @0x003 ); let nfts = nfts(collection, option::none(), 5); @@ -654,21 +641,23 @@ module minitia_std::collection { == vector[ NftResponse { token_id: string::utf8(b"3"), nft: @0x003 }, NftResponse { token_id: string::utf8(b"2"), nft: @0x002 }, - NftResponse { token_id: string::utf8(b"1"), nft: @0x001 },], - 0, + NftResponse { token_id: string::utf8(b"1"), nft: @0x001 } + ], + 0 ); nfts = nfts( collection, option::some(string::utf8(b"3")), - 5, + 5 ); assert!( nfts == vector[ NftResponse { token_id: string::utf8(b"2"), nft: @0x002 }, - NftResponse { token_id: string::utf8(b"1"), nft: @0x001 },], - 1, + NftResponse { token_id: string::utf8(b"1"), nft: @0x001 } + ], + 1 ) } @@ -679,7 +668,7 @@ module minitia_std::collection { string::utf8(b"collection description"), name, option::none(), - string::utf8(b"collection uri"), + string::utf8(b"collection uri") ) } } diff --git a/minitia_stdlib/sources/token/initia_nft.move b/minitia_stdlib/sources/token/initia_nft.move index af6c580..54d7dc5 100644 --- a/minitia_stdlib/sources/token/initia_nft.move +++ b/minitia_stdlib/sources/token/initia_nft.move @@ -13,10 +13,10 @@ module minitia_std::initia_nft { use std::string::String; use std::signer; use minitia_std::object::{Self, ConstructorRef, ExtendRef, Object}; - use minitia_std::collection; + use minitia_std::collection::{Self, Collection}; use minitia_std::royalty; use minitia_std::nft; - use minitia_std::decimal128::Decimal128; + use minitia_std::bigdecimal::BigDecimal; /// The collection does not exist const ECOLLECTION_DOES_NOT_EXIST: u64 = 1; @@ -44,7 +44,7 @@ module minitia_std::initia_nft { /// Determines if the creator can mutate nft descriptions mutable_nft_description: bool, /// Determines if the creator can mutate nft uris - mutable_nft_uri: bool, + mutable_nft_uri: bool } /// Storage state for managing the no-code Nft. @@ -52,7 +52,7 @@ module minitia_std::initia_nft { /// Used to burn. burn_ref: Option, /// Used to mutate fields - mutator_ref: Option, + mutator_ref: Option } /// Create a new collection @@ -67,7 +67,7 @@ module minitia_std::initia_nft { mutable_uri: bool, mutable_nft_description: bool, mutable_nft_uri: bool, - royalty: Decimal128, + royalty: BigDecimal ) { create_collection_object( creator, @@ -80,7 +80,7 @@ module minitia_std::initia_nft { mutable_uri, mutable_nft_description, mutable_nft_uri, - royalty, + royalty ); } @@ -95,7 +95,7 @@ module minitia_std::initia_nft { mutable_uri: bool, mutable_nft_description: bool, mutable_nft_uri: bool, - royalty: Decimal128, + royalty: BigDecimal ): (Object, ExtendRef) { let creator_addr = signer::address_of(creator); let royalty = royalty::create(royalty, creator_addr); @@ -107,7 +107,7 @@ module minitia_std::initia_nft { option::extract(&mut max_supply), name, option::some(royalty), - uri, + uri ) } else { collection::create_unlimited_collection( @@ -115,7 +115,7 @@ module minitia_std::initia_nft { description, name, option::some(royalty), - uri, + uri ) }; @@ -132,7 +132,7 @@ module minitia_std::initia_nft { option::some( royalty::generate_mutator_ref( object::generate_extend_ref(&constructor_ref) - ), + ) ) } else { option::none() @@ -146,7 +146,7 @@ module minitia_std::initia_nft { mutable_description, mutable_uri, mutable_nft_description, - mutable_nft_uri, + mutable_nft_uri }; move_to(&object_signer, initia_nft_collection); (object::object_from_constructor_ref(&constructor_ref), extend_ref) @@ -160,7 +160,7 @@ module minitia_std::initia_nft { token_id: String, uri: String, can_burn: bool, - to: Option
, + to: Option
) acquires InitiaNftCollection { let (nft_object, _) = mint_nft_object( @@ -169,13 +169,13 @@ module minitia_std::initia_nft { description, token_id, uri, - can_burn, + can_burn ); if (option::is_some(&to)) { object::transfer( creator, nft_object, - option::extract(&mut to), + option::extract(&mut to) ); } } @@ -187,7 +187,7 @@ module minitia_std::initia_nft { description: String, token_id: String, uri: String, - can_burn: bool, + can_burn: bool ): (Object, ExtendRef) acquires InitiaNftCollection { let constructor_ref = mint_internal( @@ -196,7 +196,7 @@ module minitia_std::initia_nft { description, token_id, uri, - can_burn, + can_burn ); let extend_ref = object::generate_extend_ref(&constructor_ref); @@ -205,25 +205,24 @@ module minitia_std::initia_nft { fun mint_internal( creator: &signer, - collection: String, + collection_name: String, description: String, token_id: String, uri: String, - can_burn: bool, + can_burn: bool ): ConstructorRef acquires InitiaNftCollection { + let collection_obj = collection_object(creator, &collection_name); let constructor_ref = nft::create( creator, - collection, + object::convert(collection_obj), description, token_id, option::none(), - uri, + uri ); let object_signer = object::generate_signer(&constructor_ref); - - let collection_obj = collection_object(creator, &collection); let collection = borrow_collection(collection_obj); let mutator_ref = @@ -240,7 +239,7 @@ module minitia_std::initia_nft { option::none() }; - let initia_nft = InitiaNft { burn_ref, mutator_ref, }; + let initia_nft = InitiaNft { burn_ref, mutator_ref }; move_to(&object_signer, initia_nft); constructor_ref @@ -252,7 +251,7 @@ module minitia_std::initia_nft { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); borrow_global(nft_address) } @@ -273,12 +272,12 @@ module minitia_std::initia_nft { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); assert!( nft::creator(nft) == signer::address_of(creator), - error::permission_denied(ENOT_CREATOR), + error::permission_denied(ENOT_CREATOR) ); borrow_global(nft_address) } @@ -287,46 +286,42 @@ module minitia_std::initia_nft { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); assert!( object::owns(nft, signer::address_of(owner)), - error::permission_denied(ENOT_OWNER), + error::permission_denied(ENOT_OWNER) ); let initia_nft = move_from(object::object_address(&nft)); assert!( option::is_some(&initia_nft.burn_ref), - error::invalid_state(ECAN_NOT_BURN), + error::invalid_state(ECAN_NOT_BURN) ); - let InitiaNft { burn_ref, mutator_ref: _, } = initia_nft; + let InitiaNft { burn_ref, mutator_ref: _ } = initia_nft; nft::burn(option::extract(&mut burn_ref)); } public entry fun set_description( - creator: &signer, - nft: Object, - description: String, + creator: &signer, nft: Object, description: String ) acquires InitiaNftCollection, InitiaNft { assert!( is_mutable_description(nft), - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); let initia_nft = authorized_borrow(nft, creator); nft::set_description( option::borrow(&initia_nft.mutator_ref), - description, + description ); } public entry fun set_uri( - creator: &signer, - nft: Object, - uri: String, + creator: &signer, nft: Object, uri: String ) acquires InitiaNftCollection, InitiaNft { assert!( is_mutable_uri(nft), - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); let initia_nft = authorized_borrow(nft, creator); nft::set_uri(option::borrow(&initia_nft.mutator_ref), uri); @@ -344,35 +339,37 @@ module minitia_std::initia_nft { let collection_address = object::object_address(&nft); assert!( exists(collection_address), - error::not_found(ECOLLECTION_DOES_NOT_EXIST), + error::not_found(ECOLLECTION_DOES_NOT_EXIST) ); borrow_global(collection_address) } public fun is_mutable_collection_description( - collection: Object, + collection: Object ): bool acquires InitiaNftCollection { borrow_collection(collection).mutable_description } public fun is_mutable_collection_royalty( - collection: Object, + collection: Object ): bool acquires InitiaNftCollection { option::is_some(&borrow_collection(collection).royalty_mutator_ref) } - public fun is_mutable_collection_uri(collection: Object,): bool acquires InitiaNftCollection { + public fun is_mutable_collection_uri( + collection: Object + ): bool acquires InitiaNftCollection { borrow_collection(collection).mutable_uri } public fun is_mutable_collection_nft_description( - collection: Object, + collection: Object ): bool acquires InitiaNftCollection { borrow_collection(collection).mutable_nft_description } public fun is_mutable_collection_nft_uri( - collection: Object, + collection: Object ): bool acquires InitiaNftCollection { borrow_collection(collection).mutable_nft_uri } @@ -385,70 +382,64 @@ module minitia_std::initia_nft { let collection_address = object::object_address(&collection); assert!( exists(collection_address), - error::not_found(ECOLLECTION_DOES_NOT_EXIST), + error::not_found(ECOLLECTION_DOES_NOT_EXIST) ); assert!( collection::creator(collection) == signer::address_of(creator), - error::permission_denied(ENOT_CREATOR), + error::permission_denied(ENOT_CREATOR) ); borrow_global(collection_address) } public entry fun set_collection_description( - creator: &signer, - collection: Object, - description: String, + creator: &signer, collection: Object, description: String ) acquires InitiaNftCollection { let initia_nft_collection = authorized_borrow_collection(collection, creator); assert!( initia_nft_collection.mutable_description, - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); collection::set_description( option::borrow(&initia_nft_collection.mutator_ref), - description, + description ); } public fun set_collection_royalties( - creator: &signer, - collection: Object, - royalty: royalty::Royalty, + creator: &signer, collection: Object, royalty: royalty::Royalty ) acquires InitiaNftCollection { let initia_nft_collection = authorized_borrow_collection(collection, creator); assert!( option::is_some(&initia_nft_collection.royalty_mutator_ref), - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); royalty::update( option::borrow(&initia_nft_collection.royalty_mutator_ref), - royalty, + royalty ); } public fun set_collection_royalties_call( creator: &signer, collection: Object, - royalty: Decimal128, - payee_address: address, + royalty: BigDecimal, + payee_address: address ) acquires InitiaNftCollection { let royalty = royalty::create(royalty, payee_address); set_collection_royalties(creator, collection, royalty); } public entry fun set_collection_uri( - creator: &signer, - collection: Object, - uri: String, + creator: &signer, collection: Object, uri: String ) acquires InitiaNftCollection { let initia_nft_collection = authorized_borrow_collection(collection, creator); assert!( initia_nft_collection.mutable_uri, - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); collection::set_uri( option::borrow(&initia_nft_collection.mutator_ref), - uri, + uri ); } @@ -458,7 +449,7 @@ module minitia_std::initia_nft { use std::string; #[test_only] - use minitia_std::decimal128; + use minitia_std::bigdecimal; #[test(creator = @0x123)] fun test_create_and_transfer(creator: &signer) acquires InitiaNftCollection { @@ -470,7 +461,7 @@ module minitia_std::initia_nft { assert!( object::owner(nft) == signer::address_of(creator), - 1, + 1 ); object::transfer(creator, nft, @0x345); assert!(object::owner(nft) == @0x345, 1); @@ -505,7 +496,7 @@ module minitia_std::initia_nft { #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] fun test_set_description_non_creator( - creator: &signer, noncreator: &signer, + creator: &signer, noncreator: &signer ) acquires InitiaNftCollection, InitiaNft { let collection_name = string::utf8(b"collection name"); let token_id = string::utf8(b"nft name"); @@ -545,7 +536,9 @@ module minitia_std::initia_nft { #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] - fun test_set_uri_non_creator(creator: &signer, noncreator: &signer,) acquires InitiaNftCollection, InitiaNft { + fun test_set_uri_non_creator( + creator: &signer, noncreator: &signer + ) acquires InitiaNftCollection, InitiaNft { let collection_name = string::utf8(b"collection name"); let token_id = string::utf8(b"nft name"); @@ -572,7 +565,9 @@ module minitia_std::initia_nft { #[test(creator = @0x123, nonowner = @0x456)] #[expected_failure(abort_code = 0x50005, location = Self)] - fun test_burn_non_owner(creator: &signer, nonowner: &signer,) acquires InitiaNftCollection, InitiaNft { + fun test_burn_non_owner( + creator: &signer, nonowner: &signer + ) acquires InitiaNftCollection, InitiaNft { let collection_name = string::utf8(b"collection name"); let token_id = string::utf8(b"nft name"); @@ -589,12 +584,12 @@ module minitia_std::initia_nft { let value = string::utf8(b"not"); assert!( collection::description(collection) != value, - 0, + 0 ); set_collection_description(creator, collection, value); assert!( collection::description(collection) == value, - 1, + 1 ); } @@ -606,21 +601,21 @@ module minitia_std::initia_nft { set_collection_description( creator, collection, - string::utf8(b""), + string::utf8(b"") ); } #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] fun test_set_collection_description_non_creator( - creator: &signer, noncreator: &signer, + creator: &signer, noncreator: &signer ) acquires InitiaNftCollection { let collection_name = string::utf8(b"collection name"); let collection = create_collection_helper(creator, collection_name, true); set_collection_description( noncreator, collection, - string::utf8(b""), + string::utf8(b"") ); } @@ -642,21 +637,21 @@ module minitia_std::initia_nft { set_collection_uri( creator, collection, - string::utf8(b""), + string::utf8(b"") ); } #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] fun test_set_collection_uri_non_creator( - creator: &signer, noncreator: &signer, + creator: &signer, noncreator: &signer ) acquires InitiaNftCollection { let collection_name = string::utf8(b"collection name"); let collection = create_collection_helper(creator, collection_name, true); set_collection_uri( noncreator, collection, - string::utf8(b""), + string::utf8(b"") ); } @@ -672,8 +667,8 @@ module minitia_std::initia_nft { set_collection_royalties_call( creator, collection, - decimal128::from_ratio(2, 3), - @0x444, + bigdecimal::from_ratio_u64(2, 3), + @0x444 ); let royalty_after = option::extract(&mut nft::royalty(nft)); assert!(royalty_before != royalty_after, 0); @@ -681,9 +676,7 @@ module minitia_std::initia_nft { #[test_only] fun create_collection_helper( - creator: &signer, - collection_name: String, - flag: bool, + creator: &signer, collection_name: String, flag: bool ): Object { let (obj, _) = create_collection_object( @@ -697,7 +690,7 @@ module minitia_std::initia_nft { flag, flag, flag, - decimal128::from_ratio(1, 100), + bigdecimal::from_ratio_u64(1, 100) ); obj @@ -705,9 +698,7 @@ module minitia_std::initia_nft { #[test_only] fun mint_helper( - creator: &signer, - collection_name: String, - token_id: String, + creator: &signer, collection_name: String, token_id: String ): Object acquires InitiaNftCollection { let (obj, _) = mint_nft_object( @@ -716,7 +707,7 @@ module minitia_std::initia_nft { string::utf8(b"description"), token_id, string::utf8(b"uri"), - true, + true ); obj diff --git a/minitia_stdlib/sources/token/nft.move b/minitia_stdlib/sources/token/nft.move index 5287392..a786f60 100644 --- a/minitia_stdlib/sources/token/nft.move +++ b/minitia_stdlib/sources/token/nft.move @@ -31,6 +31,8 @@ module minitia_std::nft { const EQUERY_LENGTH_TOO_LONG: u64 = 8; /// The provided token id is invalid const EINVALID_TOKEN_ID: u64 = 9; + /// The calling signer is not the owner + const ENOT_OWNER: u64 = 10; const MAX_NFT_TOKEN_ID_LENGTH: u64 = 128; const MAX_URI_LENGTH: u64 = 512; @@ -48,19 +50,19 @@ module minitia_std::nft { token_id: String, /// The Uniform Resource Identifier (uri) pointing to the JSON file stored in off-chain /// storage; the URL length will likely need a maximum any suggestions? - uri: String, + uri: String } /// This enables burning an NFT, if possible, it will also delete the object. Note, the data /// in inner and self occupies 32-bytes each, rather than have both, this data structure makes /// a small optimization to support either and take a fixed amount of 34-bytes. struct BurnRef has drop, store { - delete_ref: object::DeleteRef, + delete_ref: object::DeleteRef } /// This enables mutating descritpion and URI by higher level services. struct MutatorRef has drop, store { - self: address, + self: address } #[event] @@ -78,58 +80,59 @@ module minitia_std::nft { collection: Object, description: String, token_id: String, - uri: String, + uri: String } fun assert_token_id(token_id: &String) { let len = string::length(token_id); assert!( len <= MAX_NFT_TOKEN_ID_LENGTH, - error::out_of_range(ENFT_TOKEN_ID_TOO_LONG), + error::out_of_range(ENFT_TOKEN_ID_TOO_LONG) ); assert!( - string::index_of(token_id, &string::utf8(b"::")) == len, - error::invalid_argument(EINVALID_TOKEN_ID), + string::index_of(token_id, &string::utf8(b":")) == len, + error::invalid_argument(EINVALID_TOKEN_ID) ); } inline fun create_common( + owner: &signer, constructor_ref: &ConstructorRef, - creator_address: address, - collection_name: String, + collection: Object, description: String, token_id: String, royalty: Option, - uri: String, + uri: String ) { + // only the collection owner can create nfts + assert!( + object::owner(collection) == signer::address_of(owner), + error::unauthenticated(ENOT_OWNER) + ); assert_token_id(&token_id); assert!( string::length(&description) <= MAX_DESCRIPTION_LENGTH, - error::out_of_range(EDESCRIPTION_TOO_LONG), + error::out_of_range(EDESCRIPTION_TOO_LONG) ); assert!( string::length(&uri) <= MAX_URI_LENGTH, - error::out_of_range(EURI_TOO_LONG), + error::out_of_range(EURI_TOO_LONG) ); let object_signer = object::generate_signer(constructor_ref); - - let collection_addr = - collection::create_collection_address(creator_address, &collection_name); - let collection = object::address_to_object(collection_addr); collection::increment_supply( collection, token_id, - signer::address_of(&object_signer), + signer::address_of(&object_signer) ); - let nft = Nft { collection, description, token_id, uri, }; + let nft = Nft { collection, description, token_id, uri }; move_to(&object_signer, nft); if (option::is_some(&royalty)) { royalty::init( constructor_ref, - option::extract(&mut royalty), + option::extract(&mut royalty) ) }; } @@ -137,25 +140,28 @@ module minitia_std::nft { /// Creates a new nft object from a nft name and returns the ConstructorRef for /// additional specialization. public fun create( - creator: &signer, - collection_name: String, + owner: &signer, + collection: Object, description: String, token_id: String, royalty: Option, - uri: String, + uri: String ): ConstructorRef { - let creator_address = signer::address_of(creator); + let owner_address = signer::address_of(owner); + let creator_address = collection::creator(collection); + let collection_name = collection::name(collection); let seed = create_nft_seed(&collection_name, &token_id); - let constructor_ref = object::create_deletable_named_object(creator, seed); + let constructor_ref = + object::create_nft_object(owner_address, creator_address, seed); create_common( + owner, &constructor_ref, - creator_address, - collection_name, + collection, description, token_id, royalty, - uri, + uri ); constructor_ref } @@ -166,7 +172,7 @@ module minitia_std::nft { ): address { object::create_object_address( &creator, - create_nft_seed(collection, token_id), + create_nft_seed(collection, token_id) ) } @@ -174,7 +180,7 @@ module minitia_std::nft { public fun create_nft_seed(collection: &String, token_id: &String): vector { assert!( string::length(token_id) <= MAX_NFT_TOKEN_ID_LENGTH, - error::out_of_range(ENFT_TOKEN_ID_TOO_LONG), + error::out_of_range(ENFT_TOKEN_ID_TOO_LONG) ); let seed = *string::bytes(collection); vector::append(&mut seed, b"::"); @@ -205,7 +211,7 @@ module minitia_std::nft { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); borrow_global(nft_address) } @@ -269,7 +275,7 @@ module minitia_std::nft { collection: nft.collection, description: nft.description, token_id: nft.token_id, - uri: nft.uri, + uri: nft.uri } } @@ -278,7 +284,7 @@ module minitia_std::nft { let len = vector::length(&nfts); assert!( len <= MAX_QUERY_LENGTH, - error::invalid_argument(EQUERY_LENGTH_TOO_LONG), + error::invalid_argument(EQUERY_LENGTH_TOO_LONG) ); let index = 0; let res: vector = vector[]; @@ -296,7 +302,7 @@ module minitia_std::nft { inline fun borrow_mut(mutator_ref: &MutatorRef): &mut Nft acquires Nft { assert!( exists(mutator_ref.self), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); borrow_global_mut(mutator_ref.self) } @@ -310,7 +316,7 @@ module minitia_std::nft { royalty::delete(addr) }; - let Nft { collection, description: _, token_id, uri: _, } = move_from(addr); + let Nft { collection, description: _, token_id, uri: _ } = move_from(addr); collection::decrement_supply(collection, token_id, addr); } @@ -320,7 +326,7 @@ module minitia_std::nft { ) acquires Nft { assert!( string::length(&description) <= MAX_DESCRIPTION_LENGTH, - error::out_of_range(EDESCRIPTION_TOO_LONG), + error::out_of_range(EDESCRIPTION_TOO_LONG) ); let nft = borrow_mut(mutator_ref); event::emit( @@ -329,7 +335,7 @@ module minitia_std::nft { mutated_field_name: string::utf8(b"description"), old_value: nft.description, new_value: description - }, + } ); nft.description = description; } @@ -337,7 +343,7 @@ module minitia_std::nft { public fun set_uri(mutator_ref: &MutatorRef, uri: String) acquires Nft { assert!( string::length(&uri) <= MAX_URI_LENGTH, - error::out_of_range(EURI_TOO_LONG), + error::out_of_range(EURI_TOO_LONG) ); let nft = borrow_mut(mutator_ref); event::emit( @@ -345,46 +351,89 @@ module minitia_std::nft { nft: mutator_ref.self, mutated_field_name: string::utf8(b"uri"), old_value: nft.uri, - new_value: uri, - }, + new_value: uri + } ); nft.uri = uri; } + #[test_only] + use minitia_std::bigdecimal; + + #[test_only] + fun generate_collection_object( + creator: &signer, collection_name: &String + ): Object { + let creator_address = signer::address_of(creator); + let collection_address = + collection::create_collection_address(creator_address, collection_name); + object::address_to_object(collection_address) + } + + #[test(creator = @0x123, owner = @0x456, trader = @0x789)] + fun test_create_after_collection_transfer( + creator: &signer, owner: &signer + ) { + let collection_name = string::utf8(b"collection name"); + let token_id = string::utf8(b"nft token_id"); + + create_collection_helper(creator, collection_name, 1); + + // transfer collection to owner + let owner_address = signer::address_of(owner); + object::transfer( + creator, + generate_collection_object(creator, &collection_name), + owner_address + ); + + // create nft + create_nft_helper(owner, creator, collection_name, token_id); + + let creator_address = signer::address_of(creator); + let nft_addr = create_nft_address( + creator_address, + &collection_name, + &token_id + ); + let nft = object::address_to_object(nft_addr); + assert!(object::owner(nft) == owner_address, 1); + } + #[test(creator = @0x123, trader = @0x456)] fun test_create_and_transfer(creator: &signer, trader: &signer) acquires Nft { let collection_name = string::utf8(b"collection name"); let token_id = string::utf8(b"nft token_id"); create_collection_helper(creator, collection_name, 1); - create_nft_helper(creator, collection_name, token_id); + create_nft_helper(creator, creator, collection_name, token_id); let creator_address = signer::address_of(creator); let nft_addr = create_nft_address( creator_address, &collection_name, - &token_id, + &token_id ); let nft = object::address_to_object(nft_addr); assert!(object::owner(nft) == creator_address, 1); object::transfer( creator, nft, - signer::address_of(trader), + signer::address_of(trader) ); assert!( object::owner(nft) == signer::address_of(trader), - 1, + 1 ); let expected_royalty = royalty::create( - minitia_std::decimal128::from_ratio(25, 10000), - creator_address, + bigdecimal::from_ratio_u64(25, 10000), + creator_address ); assert!( option::some(expected_royalty) == royalty(nft), - 2, + 2 ); } @@ -396,8 +445,8 @@ module minitia_std::nft { let creator_address = signer::address_of(creator); let expected_royalty = royalty::create( - minitia_std::decimal128::from_ratio(10, 1000), - creator_address, + bigdecimal::from_ratio_u64(10, 1000), + creator_address ); collection::create_fixed_collection( creator, @@ -405,27 +454,27 @@ module minitia_std::nft { 5, collection_name, option::some(expected_royalty), - string::utf8(b"collection uri"), + string::utf8(b"collection uri") ); create( creator, - collection_name, + generate_collection_object(creator, &collection_name), string::utf8(b"nft description"), token_id, option::none(), - string::utf8(b"nft uri"), + string::utf8(b"nft uri") ); let nft_addr = create_nft_address( creator_address, &collection_name, - &token_id, + &token_id ); let nft = object::address_to_object(nft_addr); assert!( option::some(expected_royalty) == royalty(nft), - 0, + 0 ); } @@ -439,23 +488,23 @@ module minitia_std::nft { string::utf8(b"collection description"), collection_name, option::none(), - string::utf8(b"collection uri"), + string::utf8(b"collection uri") ); create( creator, - collection_name, + generate_collection_object(creator, &collection_name), string::utf8(b"nft description"), token_id, option::none(), - string::utf8(b"nft uri"), + string::utf8(b"nft uri") ); let creator_address = signer::address_of(creator); let nft_addr = create_nft_address( creator_address, &collection_name, - &token_id, + &token_id ); let nft = object::address_to_object(nft_addr); assert!(option::none() == royalty(nft), 0); @@ -467,7 +516,7 @@ module minitia_std::nft { let collection_name = string::utf8(b"collection name"); let token_id = string::utf8(b"nft token_id::hello"); create_collection_helper(creator, collection_name, 1); - create_nft_helper(creator, collection_name, token_id); + create_nft_helper(creator, creator, collection_name, token_id); } #[test(creator = @0x123)] @@ -478,8 +527,8 @@ module minitia_std::nft { let token_id2 = string::utf8(b"nft token_id2"); create_collection_helper(creator, collection_name, 1); - create_nft_helper(creator, collection_name, token_id); - create_nft_helper(creator, collection_name, token_id2); + create_nft_helper(creator, creator, collection_name, token_id); + create_nft_helper(creator, creator, collection_name, token_id2); } #[test(creator = @0x123)] @@ -489,8 +538,8 @@ module minitia_std::nft { let token_id = string::utf8(b"nft token_id"); create_collection_helper(creator, collection_name, 2); - create_nft_helper(creator, collection_name, token_id); - create_nft_helper(creator, collection_name, token_id); + create_nft_helper(creator, creator, collection_name, token_id); + create_nft_helper(creator, creator, collection_name, token_id); } #[test(creator = @0x123)] @@ -505,8 +554,8 @@ module minitia_std::nft { create_nft_address( signer::address_of(creator), &collection_name, - &token_id, - ), + &token_id + ) ); let description = string::utf8(b"no fail"); @@ -527,8 +576,8 @@ module minitia_std::nft { create_nft_address( signer::address_of(creator), &collection_name, - &token_id, - ), + &token_id + ) ); let uri = string::utf8(b"no fail"); @@ -546,11 +595,11 @@ module minitia_std::nft { let constructor_ref = create( creator, - collection_name, + generate_collection_object(creator, &collection_name), string::utf8(b"nft description"), token_id, option::none(), - string::utf8(b"nft uri"), + string::utf8(b"nft uri") ); let burn_ref = generate_burn_ref(&constructor_ref); let nft_addr = object::address_from_constructor_ref(&constructor_ref); @@ -570,16 +619,16 @@ module minitia_std::nft { let constructor_ref = create( creator, - collection_name, + generate_collection_object(creator, &collection_name), string::utf8(b"nft description"), token_id, option::some( royalty::create( - minitia_std::decimal128::from_ratio(1, 1), - signer::address_of(creator), - ), + bigdecimal::from_ratio_u64(1, 1), + signer::address_of(creator) + ) ), - string::utf8(b"nft uri"), + string::utf8(b"nft uri") ); let burn_ref = generate_burn_ref(&constructor_ref); let nft_addr = object::address_from_constructor_ref(&constructor_ref); @@ -600,11 +649,11 @@ module minitia_std::nft { let constructor_ref = create( creator, - collection_name, + generate_collection_object(creator, &collection_name), string::utf8(b"nft description"), token_id, option::none(), - string::utf8(b"nft uri"), + string::utf8(b"nft uri") ); let burn_ref = generate_burn_ref(&constructor_ref); let nft_addr = object::address_from_constructor_ref(&constructor_ref); @@ -614,11 +663,11 @@ module minitia_std::nft { // mint again create( creator, - collection_name, + generate_collection_object(creator, &collection_name), string::utf8(b"nft description"), token_id, option::none(), - string::utf8(b"nft uri"), + string::utf8(b"nft uri") ); assert!(exists(nft_addr), 2); } @@ -633,36 +682,39 @@ module minitia_std::nft { max_supply, collection_name, option::none(), - string::utf8(b"collection uri"), + string::utf8(b"collection uri") ); } #[test_only] fun create_nft_helper( - creator: &signer, collection_name: String, token_id: String + owner: &signer, + creator: &signer, + collection_name: String, + token_id: String ): ConstructorRef { create( - creator, - collection_name, + owner, + generate_collection_object(creator, &collection_name), string::utf8(b"nft description"), token_id, option::some( royalty::create( - minitia_std::decimal128::from_ratio(25, 10000), - signer::address_of(creator), - ), + bigdecimal::from_ratio_u64(25, 10000), + signer::address_of(creator) + ) ), - string::utf8(b"uri"), + string::utf8(b"uri") ) } #[test_only] fun create_nft_with_mutation_ref( - creator: &signer, - collection_name: String, - token_id: String, + creator: &signer, collection_name: String, token_id: String ): MutatorRef { - let constructor_ref = create_nft_helper(creator, collection_name, token_id); + let constructor_ref = create_nft_helper( + creator, creator, collection_name, token_id + ); generate_mutator_ref(&constructor_ref) } } diff --git a/minitia_stdlib/sources/token/property_map.move b/minitia_stdlib/sources/token/property_map.move index 7ca6cb5..f61addd 100644 --- a/minitia_stdlib/sources/token/property_map.move +++ b/minitia_stdlib/sources/token/property_map.move @@ -53,18 +53,18 @@ module minitia_std::property_map { /// A Map for typed key to value mapping, the contract using it /// should keep track of what keys are what types, and parse them accordingly. struct PropertyMap has drop, key { - inner: SimpleMap, + inner: SimpleMap } /// A typed value for the `PropertyMap` to ensure that typing is always consistent struct PropertyValue has drop, store { type: u8, - value: vector, + value: vector } /// A mutator ref that allows for mutation of the property map struct MutatorRef has drop, store { - self: address, + self: address } public fun init(s: &signer, container: PropertyMap) { @@ -81,20 +81,20 @@ module minitia_std::property_map { public fun prepare_input( keys: vector, types: vector, - values: vector>, + values: vector> ): PropertyMap { let length = vector::length(&keys); assert!( length <= MAX_PROPERTY_MAP_SIZE, - error::invalid_argument(ETOO_MANY_PROPERTIES), + error::invalid_argument(ETOO_MANY_PROPERTIES) ); assert!( length == vector::length(&values), - error::invalid_argument(EKEY_VALUE_COUNT_MISMATCH), + error::invalid_argument(EKEY_VALUE_COUNT_MISMATCH) ); assert!( length == vector::length(&types), - error::invalid_argument(EKEY_TYPE_COUNT_MISMATCH), + error::invalid_argument(EKEY_TYPE_COUNT_MISMATCH) ); let container = simple_map::create(); @@ -102,7 +102,7 @@ module minitia_std::property_map { let key = vector::pop_back(&mut keys); assert!( string::length(&key) <= MAX_PROPERTY_NAME_LENGTH, - error::invalid_argument(EPROPERTY_MAP_KEY_TOO_LONG), + error::invalid_argument(EPROPERTY_MAP_KEY_TOO_LONG) ); let value = vector::pop_back(&mut values); @@ -114,7 +114,7 @@ module minitia_std::property_map { simple_map::add( &mut container, key, - PropertyValue { value, type: new_type }, + PropertyValue { value, type: new_type } ); }; @@ -232,7 +232,7 @@ module minitia_std::property_map { inline fun assert_exists(object: address) { assert!( exists(object), - error::not_found(EPROPERTY_MAP_DOES_NOT_EXIST), + error::not_found(EPROPERTY_MAP_DOES_NOT_EXIST) ); } @@ -241,7 +241,7 @@ module minitia_std::property_map { let (type, value) = read(object, key); assert!( type == type_info::type_name(), - error::invalid_argument(ETYPE_MISMATCH), + error::invalid_argument(ETYPE_MISMATCH) ); value } @@ -326,7 +326,7 @@ module minitia_std::property_map { simple_map::add( &mut property_map.inner, key, - PropertyValue { type, value }, + PropertyValue { type, value } ); } @@ -384,24 +384,29 @@ module minitia_std::property_map { b"u32" ), string::utf8(b"u64"), string::utf8(b"u128"), string::utf8(b"u256"), string::utf8( b"vector" - ), string::utf8(b"0x1::string::String"),], + ), string::utf8(b"0x1::string::String") + ], vector[ string::utf8(b"bool"), string::utf8(b"u8"), string::utf8(b"u16"), string::utf8( b"u32" ), string::utf8(b"u64"), string::utf8(b"u128"), string::utf8(b"u256"), string::utf8( b"vector" - ), string::utf8(b"0x1::string::String"),], + ), string::utf8(b"0x1::string::String") + ], vector[ - bcs::to_bytes(&true), bcs::to_bytes(&0x12), bcs::to_bytes( - &0x1234 - ), bcs::to_bytes(&0x12345678), bcs::to_bytes( - &0x1234567812345678 - ), bcs::to_bytes(&0x12345678123456781234567812345678), bcs::to_bytes( + bcs::to_bytes(&true), + bcs::to_bytes(&0x12), + bcs::to_bytes(&0x1234), + bcs::to_bytes(&0x12345678), + bcs::to_bytes(&0x1234567812345678), + bcs::to_bytes(&0x12345678123456781234567812345678), + bcs::to_bytes( & 0x1234567812345678123456781234567812345678123456781234567812345678 - ), bcs::to_bytes>(&vector[0x01]), bcs::to_bytes( - &string::utf8(b"a") - ),], + ), + bcs::to_bytes>(&vector[0x01]), + bcs::to_bytes(&string::utf8(b"a")) + ] ); init(&s, input); let mutator = generate_mutator_ref(&s); @@ -409,43 +414,43 @@ module minitia_std::property_map { assert!(read_bool(object, &string::utf8(b"bool")), 0); assert!( read_u8(object, &string::utf8(b"u8")) == 0x12, - 1, + 1 ); assert!( read_u16(object, &string::utf8(b"u16")) == 0x1234, - 2, + 2 ); assert!( read_u32(object, &string::utf8(b"u32")) == 0x12345678, - 3, + 3 ); assert!( read_u64(object, &string::utf8(b"u64")) == 0x1234567812345678, - 4, + 4 ); assert!( - read_u128(object, &string::utf8(b"u128")) == - 0x12345678123456781234567812345678, - 5, + read_u128(object, &string::utf8(b"u128")) + == 0x12345678123456781234567812345678, + 5 ); assert!( read_u256(object, &string::utf8(b"u256")) == 0x1234567812345678123456781234567812345678123456781234567812345678, - 6, + 6 ); assert!( read_bytes( object, - &string::utf8(b"vector"), + &string::utf8(b"vector") ) == vector[0x01], - 7, + 7 ); assert!( read_string( object, - &string::utf8(b"0x1::string::String"), + &string::utf8(b"0x1::string::String") ) == string::utf8(b"a"), - 8, + 8 ); assert!(length(object) == 9, 9); @@ -453,86 +458,86 @@ module minitia_std::property_map { update_typed( &mutator, &string::utf8(b"bool"), - false, + false ); update_typed(&mutator, &string::utf8(b"u8"), 0x21); update_typed( &mutator, &string::utf8(b"u16"), - 0x22, + 0x22 ); update_typed( &mutator, &string::utf8(b"u32"), - 0x23, + 0x23 ); update_typed( &mutator, &string::utf8(b"u64"), - 0x24, + 0x24 ); update_typed( &mutator, &string::utf8(b"u128"), - 0x25, + 0x25 ); update_typed( &mutator, &string::utf8(b"u256"), - 0x26, + 0x26 ); update_typed>( &mutator, &string::utf8(b"vector"), - vector[0x02], + vector[0x02] ); update_typed( &mutator, &string::utf8(b"0x1::string::String"), - string::utf8(b"ha"), + string::utf8(b"ha") ); assert!( !read_bool(object, &string::utf8(b"bool")), - 10, + 10 ); assert!( read_u8(object, &string::utf8(b"u8")) == 0x21, - 11, + 11 ); assert!( read_u16(object, &string::utf8(b"u16")) == 0x22, - 12, + 12 ); assert!( read_u32(object, &string::utf8(b"u32")) == 0x23, - 13, + 13 ); assert!( read_u64(object, &string::utf8(b"u64")) == 0x24, - 14, + 14 ); assert!( read_u128(object, &string::utf8(b"u128")) == 0x25, - 15, + 15 ); assert!( read_u256(object, &string::utf8(b"u256")) == 0x26, - 16, + 16 ); assert!( read_bytes( object, - &string::utf8(b"vector"), + &string::utf8(b"vector") ) == vector[0x02], - 17, + 17 ); assert!( read_string( object, - &string::utf8(b"0x1::string::String"), + &string::utf8(b"0x1::string::String") ) == string::utf8(b"ha"), - 18, + 18 ); assert!(length(object) == 9, 19); @@ -547,7 +552,7 @@ module minitia_std::property_map { remove(&mutator, &string::utf8(b"vector")); remove( &mutator, - &string::utf8(b"0x1::string::String"), + &string::utf8(b"0x1::string::String") ); assert!(length(object) == 0, 20); @@ -555,7 +560,7 @@ module minitia_std::property_map { add_typed( &mutator, string::utf8(b"bool"), - false, + false ); add_typed(&mutator, string::utf8(b"u8"), 0x21); add_typed(&mutator, string::utf8(b"u16"), 0x22); @@ -564,65 +569,65 @@ module minitia_std::property_map { add_typed( &mutator, string::utf8(b"u128"), - 0x25, + 0x25 ); add_typed( &mutator, string::utf8(b"u256"), - 0x26, + 0x26 ); add_typed>( &mutator, string::utf8(b"vector"), - vector[0x02], + vector[0x02] ); add_typed( &mutator, string::utf8(b"0x1::string::String"), - string::utf8(b"ha"), + string::utf8(b"ha") ); assert!( !read_bool(object, &string::utf8(b"bool")), - 21, + 21 ); assert!( read_u8(object, &string::utf8(b"u8")) == 0x21, - 22, + 22 ); assert!( read_u16(object, &string::utf8(b"u16")) == 0x22, - 23, + 23 ); assert!( read_u32(object, &string::utf8(b"u32")) == 0x23, - 24, + 24 ); assert!( read_u64(object, &string::utf8(b"u64")) == 0x24, - 25, + 25 ); assert!( read_u128(object, &string::utf8(b"u128")) == 0x25, - 26, + 26 ); assert!( read_u256(object, &string::utf8(b"u256")) == 0x26, - 27, + 27 ); assert!( read_bytes( object, - &string::utf8(b"vector"), + &string::utf8(b"vector") ) == vector[0x02], - 28, + 28 ); assert!( read_string( object, - &string::utf8(b"0x1::string::String"), + &string::utf8(b"0x1::string::String") ) == string::utf8(b"ha"), - 29, + 29 ); assert!(length(object) == 9, 30); @@ -637,7 +642,7 @@ module minitia_std::property_map { remove(&mutator, &string::utf8(b"vector")); remove( &mutator, - &string::utf8(b"0x1::string::String"), + &string::utf8(b"0x1::string::String") ); assert!(length(object) == 0, 31); @@ -646,37 +651,37 @@ module minitia_std::property_map { &mutator, string::utf8(b"bool"), string::utf8(b"bool"), - bcs::to_bytes(&true), + bcs::to_bytes(&true) ); add( &mutator, string::utf8(b"u8"), string::utf8(b"u8"), - bcs::to_bytes(&0x12), + bcs::to_bytes(&0x12) ); add( &mutator, string::utf8(b"u16"), string::utf8(b"u16"), - bcs::to_bytes(&0x1234), + bcs::to_bytes(&0x1234) ); add( &mutator, string::utf8(b"u32"), string::utf8(b"u32"), - bcs::to_bytes(&0x12345678), + bcs::to_bytes(&0x12345678) ); add( &mutator, string::utf8(b"u64"), string::utf8(b"u64"), - bcs::to_bytes(&0x1234567812345678), + bcs::to_bytes(&0x1234567812345678) ); add( &mutator, string::utf8(b"u128"), string::utf8(b"u128"), - bcs::to_bytes(&0x12345678123456781234567812345678), + bcs::to_bytes(&0x12345678123456781234567812345678) ); add( &mutator, @@ -684,61 +689,61 @@ module minitia_std::property_map { string::utf8(b"u256"), bcs::to_bytes( &0x1234567812345678123456781234567812345678123456781234567812345678 - ), + ) ); add( &mutator, string::utf8(b"vector"), string::utf8(b"vector"), - bcs::to_bytes>(&vector[0x01]), + bcs::to_bytes>(&vector[0x01]) ); add( &mutator, string::utf8(b"0x1::string::String"), string::utf8(b"0x1::string::String"), - bcs::to_bytes(&string::utf8(b"a")), + bcs::to_bytes(&string::utf8(b"a")) ); assert!(read_bool(object, &string::utf8(b"bool")), 32); assert!( read_u8(object, &string::utf8(b"u8")) == 0x12, - 33, + 33 ); assert!( read_u16(object, &string::utf8(b"u16")) == 0x1234, - 34, + 34 ); assert!( read_u32(object, &string::utf8(b"u32")) == 0x12345678, - 35, + 35 ); assert!( read_u64(object, &string::utf8(b"u64")) == 0x1234567812345678, - 36, + 36 ); assert!( - read_u128(object, &string::utf8(b"u128")) == - 0x12345678123456781234567812345678, - 37, + read_u128(object, &string::utf8(b"u128")) + == 0x12345678123456781234567812345678, + 37 ); assert!( read_u256(object, &string::utf8(b"u256")) == 0x1234567812345678123456781234567812345678123456781234567812345678, - 38, + 38 ); assert!( read_bytes( object, - &string::utf8(b"vector"), + &string::utf8(b"vector") ) == vector[0x01], - 39, + 39 ); assert!( read_string( object, - &string::utf8(b"0x1::string::String"), + &string::utf8(b"0x1::string::String") ) == string::utf8(b"a"), - 40, + 40 ); assert!(length(object) == 9, 41); @@ -747,98 +752,98 @@ module minitia_std::property_map { &mutator, &string::utf8(b"bool"), string::utf8(b"bool"), - bcs::to_bytes(&false), + bcs::to_bytes(&false) ); update( &mutator, &string::utf8(b"u8"), string::utf8(b"u8"), - bcs::to_bytes(&0x21), + bcs::to_bytes(&0x21) ); update( &mutator, &string::utf8(b"u16"), string::utf8(b"u16"), - bcs::to_bytes(&0x22), + bcs::to_bytes(&0x22) ); update( &mutator, &string::utf8(b"u32"), string::utf8(b"u32"), - bcs::to_bytes(&0x23), + bcs::to_bytes(&0x23) ); update( &mutator, &string::utf8(b"u64"), string::utf8(b"u64"), - bcs::to_bytes(&0x24), + bcs::to_bytes(&0x24) ); update( &mutator, &string::utf8(b"u128"), string::utf8(b"u128"), - bcs::to_bytes(&0x25), + bcs::to_bytes(&0x25) ); update( &mutator, &string::utf8(b"u256"), string::utf8(b"u256"), - bcs::to_bytes(&0x26), + bcs::to_bytes(&0x26) ); update( &mutator, &string::utf8(b"vector"), string::utf8(b"vector"), - bcs::to_bytes>(&vector[0x02]), + bcs::to_bytes>(&vector[0x02]) ); update( &mutator, &string::utf8(b"0x1::string::String"), string::utf8(b"0x1::string::String"), - bcs::to_bytes(&string::utf8(b"ha")), + bcs::to_bytes(&string::utf8(b"ha")) ); assert!( !read_bool(object, &string::utf8(b"bool")), - 10, + 10 ); assert!( read_u8(object, &string::utf8(b"u8")) == 0x21, - 11, + 11 ); assert!( read_u16(object, &string::utf8(b"u16")) == 0x22, - 12, + 12 ); assert!( read_u32(object, &string::utf8(b"u32")) == 0x23, - 13, + 13 ); assert!( read_u64(object, &string::utf8(b"u64")) == 0x24, - 14, + 14 ); assert!( read_u128(object, &string::utf8(b"u128")) == 0x25, - 15, + 15 ); assert!( read_u256(object, &string::utf8(b"u256")) == 0x26, - 16, + 16 ); assert!( read_bytes( object, - &string::utf8(b"vector"), + &string::utf8(b"vector") ) == vector[0x02], - 17, + 17 ); assert!( read_string( object, - &string::utf8(b"0x1::string::String"), + &string::utf8(b"0x1::string::String") ) == string::utf8(b"ha"), - 18, + 18 ); } @@ -852,7 +857,7 @@ module minitia_std::property_map { prepare_input( vector[string::utf8(b"bool")], vector[string::utf8(b"u16")], - vector[bcs::to_bytes(&true)], + vector[bcs::to_bytes(&true)] ); init(&s, input); } @@ -867,7 +872,7 @@ module minitia_std::property_map { prepare_input( vector[string::utf8(b"bool"), string::utf8(b"u8")], vector[string::utf8(b"bool"), string::utf8(b"u8")], - vector[bcs::to_bytes(&true)], + vector[bcs::to_bytes(&true)] ); init(&s, input); } @@ -882,7 +887,7 @@ module minitia_std::property_map { prepare_input( vector[string::utf8(b"bool"), string::utf8(b"u8")], vector[string::utf8(b"bool")], - vector[bcs::to_bytes(&true), bcs::to_bytes(&0x2)], + vector[bcs::to_bytes(&true), bcs::to_bytes(&0x2)] ); init(&s, input); } @@ -897,7 +902,7 @@ module minitia_std::property_map { prepare_input( vector[string::utf8(b"bool")], vector[string::utf8(b"bool")], - vector[bcs::to_bytes(&true)], + vector[bcs::to_bytes(&true)] ); init(&s, input); let mutator = generate_mutator_ref(&s); @@ -906,7 +911,7 @@ module minitia_std::property_map { &mutator, &string::utf8(b"u16"), string::utf8(b"bool"), - bcs::to_bytes(&0x1234), + bcs::to_bytes(&0x1234) ); } @@ -920,7 +925,7 @@ module minitia_std::property_map { prepare_input( vector[string::utf8(b"bool")], vector[string::utf8(b"bool")], - vector[bcs::to_bytes(&true)], + vector[bcs::to_bytes(&true)] ); init(&s, input); let mutator = generate_mutator_ref(&s); @@ -929,7 +934,7 @@ module minitia_std::property_map { &mutator, &string::utf8(b"bool"), string::utf8(b"bool"), - bcs::to_bytes(&0x1234), + bcs::to_bytes(&0x1234) ); } @@ -945,7 +950,7 @@ module minitia_std::property_map { prepare_input( vector[string::utf8(b"bool")], vector[string::utf8(b"bool")], - vector[bcs::to_bytes(&true)], + vector[bcs::to_bytes(&true)] ); init(&s, input); read_u8(object, &string::utf8(b"bool")); diff --git a/minitia_stdlib/sources/token/royalty.move b/minitia_stdlib/sources/token/royalty.move index 3bb62c7..7fe6f29 100644 --- a/minitia_stdlib/sources/token/royalty.move +++ b/minitia_stdlib/sources/token/royalty.move @@ -4,7 +4,7 @@ module minitia_std::royalty { use std::error; use std::option::{Self, Option}; - use minitia_std::decimal128::{Self, Decimal128}; + use minitia_std::bigdecimal::{Self, BigDecimal}; use minitia_std::object::{Self, ConstructorRef, ExtendRef, Object}; friend minitia_std::nft; @@ -20,14 +20,14 @@ module minitia_std::royalty { /// /// Royalties are optional for a collection. struct Royalty has copy, drop, key { - royalty: Decimal128, + royalty: BigDecimal, /// creators. - payee_address: address, + payee_address: address } /// This enables creating or overwriting a `MutatorRef`. struct MutatorRef has drop, store { - inner: ExtendRef, + inner: ExtendRef } /// Add a royalty, given a ConstructorRef. @@ -48,10 +48,10 @@ module minitia_std::royalty { } /// Creates a new royalty, verifying that it is a valid percentage - public fun create(royalty: Decimal128, payee_address: address): Royalty { + public fun create(royalty: BigDecimal, payee_address: address): Royalty { assert!( - decimal128::val(&royalty) <= decimal128::val(&decimal128::one()), - error::out_of_range(EROYALTY_EXCEEDS_MAXIMUM), + bigdecimal::le(royalty, bigdecimal::one()), + error::out_of_range(EROYALTY_EXCEEDS_MAXIMUM) ); Royalty { royalty, payee_address } @@ -68,7 +68,7 @@ module minitia_std::royalty { public(friend) fun delete(addr: address) acquires Royalty { assert!( exists(addr), - error::not_found(EROYALTY_DOES_NOT_EXIST), + error::not_found(EROYALTY_DOES_NOT_EXIST) ); move_from(addr); } @@ -83,7 +83,7 @@ module minitia_std::royalty { } } - public fun royalty(royalty: &Royalty): Decimal128 { + public fun royalty(royalty: &Royalty): BigDecimal { royalty.royalty } @@ -104,26 +104,26 @@ module minitia_std::royalty { let constructor_ref = object::create_named_object(creator, b""); let object = object::object_from_constructor_ref(&constructor_ref); - let init_royalty = create(decimal128::from_ratio(1, 2), @0x123); + let init_royalty = create(bigdecimal::from_ratio_u64(1, 2), @0x123); init(&constructor_ref, init_royalty); assert!(option::some(init_royalty) == get(object), 0); assert!( - royalty(&init_royalty) == decimal128::from_ratio(1, 2), - 1, + royalty(&init_royalty) == bigdecimal::from_ratio_u64(1, 2), + 1 ); assert!(payee_address(&init_royalty) == @0x123, 2); let mutator_ref = generate_mutator_ref(object::generate_extend_ref(&constructor_ref)); - let update_royalty = create(decimal128::from_ratio(2, 5), @0x456); + let update_royalty = create(bigdecimal::from_ratio_u64(2, 5), @0x456); update(&mutator_ref, update_royalty); assert!( option::some(update_royalty) == get(object), - 3, + 3 ); assert!( - royalty(&update_royalty) == decimal128::from_ratio(2, 5), - 4, + royalty(&update_royalty) == bigdecimal::from_ratio_u64(2, 5), + 4 ); assert!(payee_address(&update_royalty) == @0x456, 5); } @@ -137,11 +137,11 @@ module minitia_std::royalty { let mutator_ref = generate_mutator_ref(object::generate_extend_ref(&constructor_ref)); - let update_royalty = create(decimal128::from_ratio(1, 5), @0x123); + let update_royalty = create(bigdecimal::from_ratio_u64(1, 5), @0x123); update(&mutator_ref, update_royalty); assert!( option::some(update_royalty) == get(object), - 1, + 1 ); } @@ -154,6 +154,6 @@ module minitia_std::royalty { #[test] #[expected_failure(abort_code = 0x20002, location = Self)] fun test_exceeds_maximum() { - create(decimal128::from_ratio(6, 5), @0x1); + create(bigdecimal::from_ratio_u64(6, 5), @0x1); } } diff --git a/minitia_stdlib/sources/token/simple_nft.move b/minitia_stdlib/sources/token/simple_nft.move index 6ec646c..43cf4b4 100644 --- a/minitia_stdlib/sources/token/simple_nft.move +++ b/minitia_stdlib/sources/token/simple_nft.move @@ -10,7 +10,7 @@ module minitia_std::simple_nft { use minitia_std::royalty; use minitia_std::nft; use minitia_std::initia_nft::{Self, InitiaNft}; - use minitia_std::decimal128::Decimal128; + use minitia_std::bigdecimal::BigDecimal; /// The collection does not exist const ECOLLECTION_DOES_NOT_EXIST: u64 = 1; @@ -26,13 +26,13 @@ module minitia_std::simple_nft { /// Storage state for managing the no-code Collection. struct SimpleNftCollection has key { /// Determines if the creator can mutate nft properties - mutable_nft_properties: bool, + mutable_nft_properties: bool } /// Storage state for managing the no-code Nft. struct SimpleNft has key { /// Used to mutate properties - property_mutator_ref: property_map::MutatorRef, + property_mutator_ref: property_map::MutatorRef } /// Create a new collection @@ -48,7 +48,7 @@ module minitia_std::simple_nft { mutable_nft_description: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, - royalty: Decimal128, + royalty: BigDecimal ) { create_collection_object( creator, @@ -62,7 +62,7 @@ module minitia_std::simple_nft { mutable_nft_description, mutable_nft_properties, mutable_nft_uri, - royalty, + royalty ); } @@ -78,7 +78,7 @@ module minitia_std::simple_nft { mutable_nft_description: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, - royalty: Decimal128, + royalty: BigDecimal ): Object { let (_, extend_ref) = initia_nft::create_collection_object( @@ -92,12 +92,12 @@ module minitia_std::simple_nft { mutable_uri, mutable_nft_description, mutable_nft_uri, - royalty, + royalty ); let object_signer = object::generate_signer_for_extending(&extend_ref); - let simple_nft_collection = SimpleNftCollection { mutable_nft_properties, }; + let simple_nft_collection = SimpleNftCollection { mutable_nft_properties }; move_to(&object_signer, simple_nft_collection); object::address_to_object(signer::address_of(&object_signer)) } @@ -112,7 +112,7 @@ module minitia_std::simple_nft { property_keys: vector, property_types: vector, property_values: vector>, - to: Option
, + to: Option
) { let nft_object = mint_nft_object( @@ -123,13 +123,13 @@ module minitia_std::simple_nft { uri, property_keys, property_types, - property_values, + property_values ); if (option::is_some(&to)) { object::transfer( creator, nft_object, - option::extract(&mut to), + option::extract(&mut to) ); } } @@ -143,7 +143,7 @@ module minitia_std::simple_nft { uri: String, property_keys: vector, property_types: vector, - property_values: vector>, + property_values: vector> ): Object { let (object, extend_ref) = initia_nft::mint_nft_object( @@ -152,7 +152,7 @@ module minitia_std::simple_nft { description, token_id, uri, - true, + true ); let s = object::generate_signer_for_extending(&extend_ref); @@ -160,12 +160,12 @@ module minitia_std::simple_nft { property_map::prepare_input( property_keys, property_types, - property_values, + property_values ); property_map::init(&s, properties); let simple_nft = SimpleNft { - property_mutator_ref: property_map::generate_mutator_ref(&s), + property_mutator_ref: property_map::generate_mutator_ref(&s) }; move_to(&s, simple_nft); @@ -178,7 +178,7 @@ module minitia_std::simple_nft { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); borrow_global(nft_address) } @@ -195,12 +195,12 @@ module minitia_std::simple_nft { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); assert!( nft::creator(nft) == signer::address_of(creator), - error::permission_denied(ENOT_CREATOR), + error::permission_denied(ENOT_CREATOR) ); borrow_global(nft_address) } @@ -209,11 +209,11 @@ module minitia_std::simple_nft { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); assert!( object::owns(nft, signer::address_of(owner)), - error::permission_denied(ENOT_OWNER), + error::permission_denied(ENOT_OWNER) ); let simple_nft = move_from(object::object_address(&nft)); @@ -223,17 +223,13 @@ module minitia_std::simple_nft { } public entry fun set_description( - creator: &signer, - nft: Object, - description: String, + creator: &signer, nft: Object, description: String ) { initia_nft::set_description(creator, nft, description); } public entry fun set_uri( - creator: &signer, - nft: Object, - uri: String, + creator: &signer, nft: Object, uri: String ) { initia_nft::set_uri(creator, nft, uri); } @@ -243,19 +239,19 @@ module minitia_std::simple_nft { nft: Object, key: String, type: String, - value: vector, + value: vector ) acquires SimpleNftCollection, SimpleNft { let simple_nft = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::add( &simple_nft.property_mutator_ref, key, type, - value, + value ); } @@ -263,26 +259,24 @@ module minitia_std::simple_nft { creator: &signer, nft: Object, key: String, - value: V, + value: V ) acquires SimpleNftCollection, SimpleNft { let simple_nft = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::add_typed(&simple_nft.property_mutator_ref, key, value); } public entry fun remove_property( - creator: &signer, - nft: Object, - key: String, + creator: &signer, nft: Object, key: String ) acquires SimpleNftCollection, SimpleNft { let simple_nft = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::remove(&simple_nft.property_mutator_ref, &key); @@ -293,19 +287,19 @@ module minitia_std::simple_nft { nft: Object, key: String, type: String, - value: vector, + value: vector ) acquires SimpleNftCollection, SimpleNft { let simple_nft = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::update( &simple_nft.property_mutator_ref, &key, type, - value, + value ); } @@ -313,18 +307,18 @@ module minitia_std::simple_nft { creator: &signer, nft: Object, key: String, - value: V, + value: V ) acquires SimpleNftCollection, SimpleNft { let simple_nft = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::update_typed( &simple_nft.property_mutator_ref, &key, - value, + value ); } @@ -340,41 +334,41 @@ module minitia_std::simple_nft { let collection_address = object::object_address(&nft); assert!( exists(collection_address), - error::not_found(ECOLLECTION_DOES_NOT_EXIST), + error::not_found(ECOLLECTION_DOES_NOT_EXIST) ); borrow_global(collection_address) } public fun is_mutable_collection_description( - collection: Object, + collection: Object ): bool { initia_nft::is_mutable_collection_description(collection) } public fun is_mutable_collection_royalty( - collection: Object, + collection: Object ): bool { initia_nft::is_mutable_collection_royalty(collection) } - public fun is_mutable_collection_uri(collection: Object,): bool { + public fun is_mutable_collection_uri(collection: Object): bool { initia_nft::is_mutable_collection_uri(collection) } public fun is_mutable_collection_nft_description( - collection: Object, + collection: Object ): bool { initia_nft::is_mutable_collection_nft_description(collection) } public fun is_mutable_collection_nft_uri( - collection: Object, + collection: Object ): bool { initia_nft::is_mutable_collection_nft_uri(collection) } public fun is_mutable_collection_nft_properties( - collection: Object, + collection: Object ): bool acquires SimpleNftCollection { borrow_collection(collection).mutable_nft_properties } @@ -387,27 +381,23 @@ module minitia_std::simple_nft { let collection_address = object::object_address(&collection); assert!( exists(collection_address), - error::not_found(ECOLLECTION_DOES_NOT_EXIST), + error::not_found(ECOLLECTION_DOES_NOT_EXIST) ); assert!( collection::creator(collection) == signer::address_of(creator), - error::permission_denied(ENOT_CREATOR), + error::permission_denied(ENOT_CREATOR) ); borrow_global(collection_address) } public entry fun set_collection_description( - creator: &signer, - collection: Object, - description: String, + creator: &signer, collection: Object, description: String ) { initia_nft::set_collection_description(creator, collection, description); } public fun set_collection_royalties( - creator: &signer, - collection: Object, - royalty: royalty::Royalty, + creator: &signer, collection: Object, royalty: royalty::Royalty ) { initia_nft::set_collection_royalties(creator, collection, royalty); } @@ -415,17 +405,15 @@ module minitia_std::simple_nft { entry fun set_collection_royalties_call( creator: &signer, collection: Object, - royalty: Decimal128, - payee_address: address, + royalty: BigDecimal, + payee_address: address ) { let royalty = royalty::create(royalty, payee_address); set_collection_royalties(creator, collection, royalty); } public entry fun set_collection_uri( - creator: &signer, - collection: Object, - uri: String, + creator: &signer, collection: Object, uri: String ) { initia_nft::set_collection_uri(creator, collection, uri); } @@ -436,7 +424,7 @@ module minitia_std::simple_nft { use std::string; #[test_only] - use minitia_std::decimal128; + use minitia_std::bigdecimal; #[test(creator = @0x123)] fun test_create_and_transfer(creator: &signer) { @@ -448,7 +436,7 @@ module minitia_std::simple_nft { assert!( object::owner(nft) == signer::address_of(creator), - 1, + 1 ); object::transfer(creator, nft, @0x345); assert!(object::owner(nft) == @0x345, 1); @@ -468,12 +456,12 @@ module minitia_std::simple_nft { nft, property_name, property_type, - vector[0x08], + vector[0x08] ); assert!( property_map::read_u8(nft, &property_name) == 0x8, - 0, + 0 ); } @@ -489,7 +477,7 @@ module minitia_std::simple_nft { assert!( property_map::read_u8(nft, &property_name) == 0x8, - 0, + 0 ); } @@ -507,12 +495,12 @@ module minitia_std::simple_nft { nft, property_name, property_type, - vector[0x00], + vector[0x00] ); assert!( !property_map::read_bool(nft, &property_name), - 0, + 0 ); } @@ -528,7 +516,7 @@ module minitia_std::simple_nft { assert!( !property_map::read_bool(nft, &property_name), - 0, + 0 ); } @@ -545,9 +533,7 @@ module minitia_std::simple_nft { #[test_only] fun create_collection_helper( - creator: &signer, - collection_name: String, - flag: bool, + creator: &signer, collection_name: String, flag: bool ): Object { create_collection_object( creator, @@ -561,15 +547,13 @@ module minitia_std::simple_nft { flag, flag, flag, - decimal128::from_ratio(1, 100), + bigdecimal::from_ratio_u64(1, 100) ) } #[test_only] fun mint_helper( - creator: &signer, - collection_name: String, - token_id: String, + creator: &signer, collection_name: String, token_id: String ): Object { mint_nft_object( creator, @@ -579,7 +563,7 @@ module minitia_std::simple_nft { string::utf8(b"uri"), vector[string::utf8(b"bool")], vector[string::utf8(b"bool")], - vector[vector[0x01]], + vector[vector[0x01]] ) } } diff --git a/minitia_stdlib/sources/token/soul_bound_token.move b/minitia_stdlib/sources/token/soul_bound_token.move index f089742..727f65a 100644 --- a/minitia_stdlib/sources/token/soul_bound_token.move +++ b/minitia_stdlib/sources/token/soul_bound_token.move @@ -6,11 +6,11 @@ module minitia_std::soul_bound_token { use std::string::String; use std::signer; use minitia_std::object::{Self, ConstructorRef, Object}; - use minitia_std::collection; + use minitia_std::collection::{Self, Collection}; use minitia_std::property_map; use minitia_std::royalty; use minitia_std::nft; - use minitia_std::decimal128::Decimal128; + use minitia_std::bigdecimal::BigDecimal; /// The collection does not exist const ECOLLECTION_DOES_NOT_EXIST: u64 = 1; @@ -40,7 +40,7 @@ module minitia_std::soul_bound_token { /// Determines if the creator can mutate nft properties mutable_nft_properties: bool, /// Determines if the creator can mutate nft uris - mutable_nft_uri: bool, + mutable_nft_uri: bool } /// Storage state for managing the no-code Token. @@ -48,7 +48,7 @@ module minitia_std::soul_bound_token { /// Used to mutate fields mutator_ref: Option, /// Used to mutate properties - property_mutator_ref: property_map::MutatorRef, + property_mutator_ref: property_map::MutatorRef } /// Create a new collection @@ -65,7 +65,7 @@ module minitia_std::soul_bound_token { mutable_nft_name: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, - royalty: Decimal128, + royalty: BigDecimal ) { create_collection_object( creator, @@ -80,7 +80,7 @@ module minitia_std::soul_bound_token { mutable_nft_name, mutable_nft_properties, mutable_nft_uri, - royalty, + royalty ); } @@ -97,7 +97,7 @@ module minitia_std::soul_bound_token { mutable_nft_name: bool, mutable_nft_properties: bool, mutable_nft_uri: bool, - royalty: Decimal128, + royalty: BigDecimal ): Object { let creator_addr = signer::address_of(creator); let royalty = royalty::create(royalty, creator_addr); @@ -108,7 +108,7 @@ module minitia_std::soul_bound_token { max_supply, name, option::some(royalty), - uri, + uri ); let object_signer = object::generate_signer(&constructor_ref); @@ -124,7 +124,7 @@ module minitia_std::soul_bound_token { option::some( royalty::generate_mutator_ref( object::generate_extend_ref(&constructor_ref) - ), + ) ) } else { option::none() @@ -138,7 +138,7 @@ module minitia_std::soul_bound_token { mutable_nft_description, mutable_nft_name, mutable_nft_properties, - mutable_nft_uri, + mutable_nft_uri }; move_to(&object_signer, soul_bound_token_collection); object::object_from_constructor_ref(&constructor_ref) @@ -154,7 +154,7 @@ module minitia_std::soul_bound_token { property_keys: vector, property_types: vector, property_values: vector>, - soul_bound_to: address, + soul_bound_to: address ) acquires SoulBoundTokenCollection { mint_soul_bound_token_object( creator, @@ -165,7 +165,7 @@ module minitia_std::soul_bound_token { property_keys, property_types, property_values, - soul_bound_to, + soul_bound_to ); } @@ -179,7 +179,7 @@ module minitia_std::soul_bound_token { property_keys: vector, property_types: vector, property_values: vector>, - soul_bound_to: address, + soul_bound_to: address ): Object acquires SoulBoundTokenCollection { let constructor_ref = mint_internal( @@ -190,7 +190,7 @@ module minitia_std::soul_bound_token { uri, property_keys, property_types, - property_values, + property_values ); let transfer_ref = object::generate_transfer_ref(&constructor_ref); @@ -203,28 +203,28 @@ module minitia_std::soul_bound_token { fun mint_internal( creator: &signer, - collection: String, + collection_name: String, description: String, name: String, uri: String, property_keys: vector, property_types: vector, - property_values: vector>, + property_values: vector> ): ConstructorRef acquires SoulBoundTokenCollection { + let collection_obj = collection_object(creator, &collection_name); let constructor_ref = nft::create( creator, - collection, + object::convert(collection_obj), description, name, option::none(), - uri, + uri ); let s = object::generate_signer(&constructor_ref); let object_signer = object::generate_signer(&constructor_ref); - let collection_obj = collection_object(creator, &collection); let collection = borrow_collection(collection_obj); let mutator_ref = @@ -238,7 +238,7 @@ module minitia_std::soul_bound_token { let soul_bound_token = SoulBoundToken { mutator_ref, - property_mutator_ref: property_map::generate_mutator_ref(&s), + property_mutator_ref: property_map::generate_mutator_ref(&s) }; move_to(&object_signer, soul_bound_token); @@ -246,7 +246,7 @@ module minitia_std::soul_bound_token { property_map::prepare_input( property_keys, property_types, - property_values, + property_values ); property_map::init(&s, properties); @@ -259,7 +259,7 @@ module minitia_std::soul_bound_token { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); borrow_global(nft_address) } @@ -291,45 +291,41 @@ module minitia_std::soul_bound_token { let nft_address = object::object_address(&nft); assert!( exists(nft_address), - error::not_found(ENFT_DOES_NOT_EXIST), + error::not_found(ENFT_DOES_NOT_EXIST) ); assert!( nft::creator(nft) == signer::address_of(creator), - error::permission_denied(ENOT_CREATOR), + error::permission_denied(ENOT_CREATOR) ); borrow_global(nft_address) } public entry fun set_description( - creator: &signer, - nft: Object, - description: String, + creator: &signer, nft: Object, description: String ) acquires SoulBoundTokenCollection, SoulBoundToken { assert!( is_mutable_description(nft), - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); let soul_bound_token = authorized_borrow(nft, creator); nft::set_description( option::borrow(&soul_bound_token.mutator_ref), - description, + description ); } public entry fun set_uri( - creator: &signer, - nft: Object, - uri: String, + creator: &signer, nft: Object, uri: String ) acquires SoulBoundTokenCollection, SoulBoundToken { assert!( is_mutable_uri(nft), - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); let soul_bound_token = authorized_borrow(nft, creator); nft::set_uri( option::borrow(&soul_bound_token.mutator_ref), - uri, + uri ); } @@ -338,19 +334,19 @@ module minitia_std::soul_bound_token { nft: Object, key: String, type: String, - value: vector, + value: vector ) acquires SoulBoundTokenCollection, SoulBoundToken { let soul_bound_token = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::add( &soul_bound_token.property_mutator_ref, key, type, - value, + value ); } @@ -358,30 +354,28 @@ module minitia_std::soul_bound_token { creator: &signer, nft: Object, key: String, - value: V, + value: V ) acquires SoulBoundTokenCollection, SoulBoundToken { let soul_bound_token = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::add_typed( &soul_bound_token.property_mutator_ref, key, - value, + value ); } public entry fun remove_property( - creator: &signer, - nft: Object, - key: String, + creator: &signer, nft: Object, key: String ) acquires SoulBoundTokenCollection, SoulBoundToken { let soul_bound_token = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::remove(&soul_bound_token.property_mutator_ref, &key); @@ -392,19 +386,19 @@ module minitia_std::soul_bound_token { nft: Object, key: String, type: String, - value: vector, + value: vector ) acquires SoulBoundTokenCollection, SoulBoundToken { let soul_bound_token = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::update( &soul_bound_token.property_mutator_ref, &key, type, - value, + value ); } @@ -412,25 +406,25 @@ module minitia_std::soul_bound_token { creator: &signer, nft: Object, key: String, - value: V, + value: V ) acquires SoulBoundTokenCollection, SoulBoundToken { let soul_bound_token = authorized_borrow(nft, creator); assert!( are_properties_mutable(nft), - error::permission_denied(EPROPERTIES_NOT_MUTABLE), + error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); property_map::update_typed( &soul_bound_token.property_mutator_ref, &key, - value, + value ); } // Collection accessors - inline fun collection_object(creator: &signer, name: &String) - : Object { + inline fun collection_object(creator: &signer, name: &String): + Object { let collection_addr = collection::create_collection_address(signer::address_of(creator), name); object::address_to_object(collection_addr) @@ -440,47 +434,49 @@ module minitia_std::soul_bound_token { let collection_address = object::object_address(&nft); assert!( exists(collection_address), - error::not_found(ECOLLECTION_DOES_NOT_EXIST), + error::not_found(ECOLLECTION_DOES_NOT_EXIST) ); borrow_global(collection_address) } public fun is_mutable_collection_description( - collection: Object, + collection: Object ): bool acquires SoulBoundTokenCollection { borrow_collection(collection).mutable_description } public fun is_mutable_collection_royalty( - collection: Object, + collection: Object ): bool acquires SoulBoundTokenCollection { option::is_some(&borrow_collection(collection).royalty_mutator_ref) } - public fun is_mutable_collection_uri(collection: Object,): bool acquires SoulBoundTokenCollection { + public fun is_mutable_collection_uri( + collection: Object + ): bool acquires SoulBoundTokenCollection { borrow_collection(collection).mutable_uri } public fun is_mutable_collection_nft_description( - collection: Object, + collection: Object ): bool acquires SoulBoundTokenCollection { borrow_collection(collection).mutable_nft_description } public fun is_mutable_collection_nft_name( - collection: Object, + collection: Object ): bool acquires SoulBoundTokenCollection { borrow_collection(collection).mutable_nft_name } public fun is_mutable_collection_nft_uri( - collection: Object, + collection: Object ): bool acquires SoulBoundTokenCollection { borrow_collection(collection).mutable_nft_uri } public fun is_mutable_collection_nft_properties( - collection: Object, + collection: Object ): bool acquires SoulBoundTokenCollection { borrow_collection(collection).mutable_nft_properties } @@ -493,73 +489,67 @@ module minitia_std::soul_bound_token { let collection_address = object::object_address(&collection); assert!( exists(collection_address), - error::not_found(ECOLLECTION_DOES_NOT_EXIST), + error::not_found(ECOLLECTION_DOES_NOT_EXIST) ); assert!( collection::creator(collection) == signer::address_of(creator), - error::permission_denied(ENOT_CREATOR), + error::permission_denied(ENOT_CREATOR) ); borrow_global(collection_address) } public entry fun set_collection_description( - creator: &signer, - collection: Object, - description: String, + creator: &signer, collection: Object, description: String ) acquires SoulBoundTokenCollection { let soul_bound_token_collection = authorized_borrow_collection(collection, creator); assert!( soul_bound_token_collection.mutable_description, - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); collection::set_description( option::borrow(&soul_bound_token_collection.mutator_ref), - description, + description ); } public fun set_collection_royalties( - creator: &signer, - collection: Object, - royalty: royalty::Royalty, + creator: &signer, collection: Object, royalty: royalty::Royalty ) acquires SoulBoundTokenCollection { let soul_bound_token_collection = authorized_borrow_collection(collection, creator); assert!( option::is_some(&soul_bound_token_collection.royalty_mutator_ref), - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); royalty::update( option::borrow(&soul_bound_token_collection.royalty_mutator_ref), - royalty, + royalty ); } entry fun set_collection_royalties_call( creator: &signer, collection: Object, - royalty: Decimal128, - payee_address: address, + royalty: BigDecimal, + payee_address: address ) acquires SoulBoundTokenCollection { let royalty = royalty::create(royalty, payee_address); set_collection_royalties(creator, collection, royalty); } public entry fun set_collection_uri( - creator: &signer, - collection: Object, - uri: String, + creator: &signer, collection: Object, uri: String ) acquires SoulBoundTokenCollection { let soul_bound_token_collection = authorized_borrow_collection(collection, creator); assert!( soul_bound_token_collection.mutable_uri, - error::permission_denied(EFIELD_NOT_MUTABLE), + error::permission_denied(EFIELD_NOT_MUTABLE) ); collection::set_uri( option::borrow(&soul_bound_token_collection.mutator_ref), - uri, + uri ); } @@ -569,7 +559,7 @@ module minitia_std::soul_bound_token { use std::string; #[test_only] - use minitia_std::decimal128; + use minitia_std::bigdecimal; #[test(creator = @0x123)] fun test_set_description(creator: &signer) acquires SoulBoundTokenCollection, SoulBoundToken { @@ -581,7 +571,7 @@ module minitia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); let description = string::utf8(b"not"); @@ -592,7 +582,9 @@ module minitia_std::soul_bound_token { #[test(creator = @0x123)] #[expected_failure(abort_code = 0x50004, location = Self)] - fun test_set_immutable_description(creator: &signer) acquires SoulBoundTokenCollection, SoulBoundToken { + fun test_set_immutable_description( + creator: &signer + ) acquires SoulBoundTokenCollection, SoulBoundToken { let collection_name = string::utf8(b"collection name"); let nft_name = string::utf8(b"nft name"); @@ -601,7 +593,7 @@ module minitia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); set_description(creator, nft, string::utf8(b"")); @@ -610,7 +602,7 @@ module minitia_std::soul_bound_token { #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] fun test_set_description_non_creator( - creator: &signer, noncreator: &signer, + creator: &signer, noncreator: &signer ) acquires SoulBoundTokenCollection, SoulBoundToken { let collection_name = string::utf8(b"collection name"); let nft_name = string::utf8(b"nft name"); @@ -620,7 +612,7 @@ module minitia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); let description = string::utf8(b"not"); @@ -637,7 +629,7 @@ module minitia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); let uri = string::utf8(b"not"); @@ -657,7 +649,7 @@ module minitia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); set_uri(creator, nft, string::utf8(b"")); @@ -665,7 +657,9 @@ module minitia_std::soul_bound_token { #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] - fun test_set_uri_non_creator(creator: &signer, noncreator: &signer,) acquires SoulBoundTokenCollection, SoulBoundToken { + fun test_set_uri_non_creator( + creator: &signer, noncreator: &signer + ) acquires SoulBoundTokenCollection, SoulBoundToken { let collection_name = string::utf8(b"collection name"); let nft_name = string::utf8(b"nft name"); @@ -674,7 +668,7 @@ module minitia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); let uri = string::utf8(b"not"); @@ -688,38 +682,40 @@ module minitia_std::soul_bound_token { let value = string::utf8(b"not"); assert!( collection::description(collection) != value, - 0, + 0 ); set_collection_description(creator, collection, value); assert!( collection::description(collection) == value, - 1, + 1 ); } #[test(creator = @0x123)] #[expected_failure(abort_code = 0x50004, location = Self)] - fun test_set_immutable_collection_description(creator: &signer) acquires SoulBoundTokenCollection { + fun test_set_immutable_collection_description( + creator: &signer + ) acquires SoulBoundTokenCollection { let collection_name = string::utf8(b"collection name"); let collection = create_collection_helper(creator, collection_name, false); set_collection_description( creator, collection, - string::utf8(b""), + string::utf8(b"") ); } #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] fun test_set_collection_description_non_creator( - creator: &signer, noncreator: &signer, + creator: &signer, noncreator: &signer ) acquires SoulBoundTokenCollection { let collection_name = string::utf8(b"collection name"); let collection = create_collection_helper(creator, collection_name, true); set_collection_description( noncreator, collection, - string::utf8(b""), + string::utf8(b"") ); } @@ -741,21 +737,21 @@ module minitia_std::soul_bound_token { set_collection_uri( creator, collection, - string::utf8(b""), + string::utf8(b"") ); } #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50003, location = Self)] fun test_set_collection_uri_non_creator( - creator: &signer, noncreator: &signer, + creator: &signer, noncreator: &signer ) acquires SoulBoundTokenCollection { let collection_name = string::utf8(b"collection name"); let collection = create_collection_helper(creator, collection_name, true); set_collection_uri( noncreator, collection, - string::utf8(b""), + string::utf8(b"") ); } @@ -771,19 +767,19 @@ module minitia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); add_property( creator, nft, property_name, property_type, - vector[0x08], + vector[0x08] ); assert!( property_map::read_u8(nft, &property_name) == 0x8, - 0, + 0 ); } @@ -798,13 +794,13 @@ module minitia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); add_typed_property(creator, nft, property_name, 0x8); assert!( property_map::read_u8(nft, &property_name) == 0x8, - 0, + 0 ); } @@ -820,24 +816,26 @@ module minitia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); update_property( creator, nft, property_name, property_type, - vector[0x00], + vector[0x00] ); assert!( !property_map::read_bool(nft, &property_name), - 0, + 0 ); } #[test(creator = @0x123)] - fun test_property_update_typed(creator: &signer) acquires SoulBoundTokenCollection, SoulBoundToken { + fun test_property_update_typed( + creator: &signer + ) acquires SoulBoundTokenCollection, SoulBoundToken { let collection_name = string::utf8(b"collection name"); let nft_name = string::utf8(b"nft name"); let property_name = string::utf8(b"bool"); @@ -847,13 +845,13 @@ module minitia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); update_typed_property(creator, nft, property_name, false); assert!( !property_map::read_bool(nft, &property_name), - 0, + 0 ); } @@ -868,7 +866,7 @@ module minitia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); remove_property(creator, nft, property_name); } @@ -883,15 +881,15 @@ module minitia_std::soul_bound_token { creator, collection_name, nft_name, - @0x123, + @0x123 ); let royalty_before = option::extract(&mut nft::royalty(nft)); set_collection_royalties_call( creator, collection, - decimal128::from_ratio(2, 3), - @0x444, + bigdecimal::from_ratio_u64(2, 3), + @0x444 ); let royalty_after = option::extract(&mut nft::royalty(nft)); assert!(royalty_before != royalty_after, 0); @@ -899,9 +897,7 @@ module minitia_std::soul_bound_token { #[test_only] fun create_collection_helper( - creator: &signer, - collection_name: String, - flag: bool, + creator: &signer, collection_name: String, flag: bool ): Object { create_collection_object( creator, @@ -916,7 +912,7 @@ module minitia_std::soul_bound_token { flag, flag, flag, - decimal128::from_ratio(1, 100), + bigdecimal::from_ratio_u64(1, 100) ) } @@ -936,7 +932,7 @@ module minitia_std::soul_bound_token { vector[string::utf8(b"bool")], vector[string::utf8(b"bool")], vector[vector[0x01]], - soul_bound_to, + soul_bound_to ) } } diff --git a/minitia_stdlib/sources/transaction_context.move b/minitia_stdlib/sources/transaction_context.move index 677427c..b8f8efe 100644 --- a/minitia_stdlib/sources/transaction_context.move +++ b/minitia_stdlib/sources/transaction_context.move @@ -12,6 +12,19 @@ module minitia_std::transaction_context { #[test_only] native fun get_session_id(): vector; + #[test_only] + use minitia_std::vector; + + #[test_only] + public fun set_transaction_hash(transaction_hash: vector) { + assert!(vector::length(&transaction_hash) == 32, 100); + + set_transaction_hash_internal(transaction_hash); + } + + #[test_only] + native fun set_transaction_hash_internal(transaction_hash: vector); + #[test] fun test_address_uniquess() { use std::vector; @@ -23,7 +36,7 @@ module minitia_std::transaction_context { i = i + 1; vector::push_back( &mut addrs, - generate_unique_address(), + generate_unique_address() ); }; @@ -33,7 +46,7 @@ module minitia_std::transaction_context { while (j < count) { assert!( *vector::borrow(&addrs, i) != *vector::borrow(&addrs, j), - 0, + 0 ); j = j + 1; }; @@ -63,4 +76,16 @@ module minitia_std::transaction_context { let addr2 = minitia_std::from_bcs::to_address(std::hash::sha3_256(bytes)); assert!(addr1 == addr2, 0); } + + #[test] + fun test_get_transaction_hash() { + set_transaction_hash( + x"0000000000000000000000000000000000000000000000000000000000000001" + ); + assert!( + get_transaction_hash() + == x"0000000000000000000000000000000000000000000000000000000000000001", + 0 + ); + } } diff --git a/minitia_stdlib/sources/type_info.move b/minitia_stdlib/sources/type_info.move index c48351e..8cfd1fd 100644 --- a/minitia_stdlib/sources/type_info.move +++ b/minitia_stdlib/sources/type_info.move @@ -4,7 +4,7 @@ module minitia_std::type_info { struct TypeInfo has copy, drop, store { account_address: address, module_name: vector, - struct_name: vector, + struct_name: vector } public fun account_address(type_info: &TypeInfo): address { @@ -28,7 +28,7 @@ module minitia_std::type_info { let type_info = type_of(); assert!( account_address(&type_info) == @minitia_std, - 0, + 0 ); assert!(module_name(&type_info) == b"type_info", 1); assert!(struct_name(&type_info) == b"TypeInfo", 2); @@ -45,39 +45,39 @@ module minitia_std::type_info { assert!(type_name() == string::utf8(b"u128"), 3); assert!( type_name
() == string::utf8(b"address"), - 4, + 4 ); assert!( type_name() == string::utf8(b"signer"), - 5, + 5 ); // vector assert!( type_name>() == string::utf8(b"vector"), - 6, + 6 ); assert!( type_name>>() == string::utf8(b"vector>"), - 7, + 7 ); assert!( type_name>>() == string::utf8(b"vector>"), - 8, + 8 ); // struct assert!( type_name() == string::utf8(b"0x1::type_info::TypeInfo"), - 9, + 9 ); assert!( type_name>>>() == string::utf8( - b"0x1::table::Table<0x1::type_info::TypeInfo, 0x1::table::Table>>", + b"0x1::table::Table<0x1::type_info::TypeInfo, 0x1::table::Table>>" ), - 10, + 10 ); } } diff --git a/minitia_stdlib/sources/vip/score.move b/minitia_stdlib/sources/vip/score.move index 2e1c09d..d3d4f3e 100644 --- a/minitia_stdlib/sources/vip/score.move +++ b/minitia_stdlib/sources/vip/score.move @@ -11,13 +11,13 @@ module minitia_std::vip_score { struct ModuleStore has key { init_stage: u64, deployers: SimpleMap, - scores: table::Table, + scores: table::Table } struct Scores has store { total_score: u64, is_finalized: bool, - score: table::Table
, + score: table::Table
} // @@ -87,8 +87,8 @@ module minitia_std::vip_score { ModuleStore { init_stage: 1, deployers: simple_map::create(), - scores: table::new(), - }, + scores: table::new() + } ); } @@ -102,7 +102,7 @@ module minitia_std::vip_score { fun check_chain_permission(chain: &signer) { assert!( signer::address_of(chain) == @minitia_std, - error::permission_denied(EUNAUTHORIZED), + error::permission_denied(EUNAUTHORIZED) ); } @@ -111,7 +111,7 @@ module minitia_std::vip_score { let found = simple_map::contains_key( &module_store.deployers, - &signer::address_of(deployer), + &signer::address_of(deployer) ); assert!(found, error::invalid_argument(EUNAUTHORIZED)); } @@ -134,7 +134,7 @@ module minitia_std::vip_score { stage: stage, score: *score, total_score: scores.total_score - }, + } ) } @@ -147,7 +147,7 @@ module minitia_std::vip_score { assert!( table::contains(&module_store.scores, stage - 1) && table::borrow(&module_store.scores, stage - 1).is_finalized, - error::invalid_argument(EPREVIOUS_STAGE_NOT_FINALIZED), + error::invalid_argument(EPREVIOUS_STAGE_NOT_FINALIZED) ); return @@ -193,7 +193,7 @@ module minitia_std::vip_score { total_score: 0, is_finalized: false, score: table::new() - }, + } ); }; } @@ -211,13 +211,13 @@ module minitia_std::vip_score { assert!( table::contains(&module_store.scores, stage), - error::invalid_argument(EINVALID_STAGE), + error::invalid_argument(EINVALID_STAGE) ); let scores = table::borrow_mut(&mut module_store.scores, stage); assert!( !scores.is_finalized, - error::invalid_argument(EFINALIED_STAGE), + error::invalid_argument(EFINALIED_STAGE) ); let score = table::borrow_mut_with_default(&mut scores.score, account, 0); @@ -231,7 +231,7 @@ module minitia_std::vip_score { stage: stage, score: *score, total_score: scores.total_score - }, + } ) } @@ -248,19 +248,19 @@ module minitia_std::vip_score { assert!( table::contains(&module_store.scores, stage), - error::invalid_argument(EINVALID_STAGE), + error::invalid_argument(EINVALID_STAGE) ); let scores = table::borrow_mut(&mut module_store.scores, stage); assert!( !scores.is_finalized, - error::invalid_argument(EFINALIED_STAGE), + error::invalid_argument(EFINALIED_STAGE) ); let score = table::borrow_mut(&mut scores.score, account); assert!( *score >= amount, - error::invalid_argument(EINSUFFICIENT_SCORE), + error::invalid_argument(EINSUFFICIENT_SCORE) ); *score = *score - amount; scores.total_score = scores.total_score - amount; @@ -271,7 +271,7 @@ module minitia_std::vip_score { stage: stage, score: *score, total_score: scores.total_score - }, + } ) } @@ -284,20 +284,20 @@ module minitia_std::vip_score { check_deployer_permission(deployer); assert!( amount >= 0, - error::invalid_argument(EINVALID_SCORE), + error::invalid_argument(EINVALID_SCORE) ); let module_store = borrow_global_mut(@minitia_std); check_previous_stage_finalized(module_store, stage); assert!( table::contains(&module_store.scores, stage), - error::invalid_argument(EINVALID_STAGE), + error::invalid_argument(EINVALID_STAGE) ); let scores = table::borrow_mut(&mut module_store.scores, stage); assert!( !scores.is_finalized, - error::invalid_argument(EFINALIED_STAGE), + error::invalid_argument(EFINALIED_STAGE) ); update_score_internal(scores, account, stage, amount); @@ -311,13 +311,13 @@ module minitia_std::vip_score { let module_store = borrow_global_mut(@minitia_std); assert!( table::contains(&module_store.scores, stage), - error::invalid_argument(EINVALID_STAGE), + error::invalid_argument(EINVALID_STAGE) ); let scores = table::borrow_mut(&mut module_store.scores, stage); assert!( !scores.is_finalized, - error::invalid_argument(EFINALIED_STAGE), + error::invalid_argument(EFINALIED_STAGE) ); scores.is_finalized = true; @@ -333,7 +333,7 @@ module minitia_std::vip_score { ) acquires ModuleStore { assert!( vector::length(&addrs) == vector::length(&update_scores), - error::invalid_argument(ENOT_MATCH_LENGTH), + error::invalid_argument(ENOT_MATCH_LENGTH) ); // permission check is performed in prepare_stage prepare_stage(deployer, stage); @@ -342,13 +342,13 @@ module minitia_std::vip_score { check_previous_stage_finalized(module_store, stage); assert!( table::contains(&module_store.scores, stage), - error::invalid_argument(EINVALID_STAGE), + error::invalid_argument(EINVALID_STAGE) ); let scores = table::borrow_mut(&mut module_store.scores, stage); assert!( !scores.is_finalized, - error::invalid_argument(EFINALIED_STAGE), + error::invalid_argument(EFINALIED_STAGE) ); vector::enumerate_ref( &addrs, @@ -357,38 +357,38 @@ module minitia_std::vip_score { scores, *addr, stage, - *vector::borrow(&update_scores, i), + *vector::borrow(&update_scores, i) ); - }, + } ); } public entry fun add_deployer_script( - chain: &signer, deployer: address, + chain: &signer, deployer: address ) acquires ModuleStore { check_chain_permission(chain); let module_store = borrow_global_mut(@minitia_std); assert!( !simple_map::contains_key(&module_store.deployers, &deployer), - error::invalid_argument(EDEPLOYER_ALREADY_ADDED), + error::invalid_argument(EDEPLOYER_ALREADY_ADDED) ); simple_map::add( &mut module_store.deployers, deployer, - true, + true ); event::emit(DeployerAddedEvent { deployer: deployer }) } public entry fun remove_deployer_script( - chain: &signer, deployer: address, + chain: &signer, deployer: address ) acquires ModuleStore { check_chain_permission(chain); let module_store = borrow_global_mut(@minitia_std); assert!( simple_map::contains_key(&module_store.deployers, &deployer), - error::invalid_argument(EDEPLOYER_NOT_FOUND), + error::invalid_argument(EDEPLOYER_NOT_FOUND) ); simple_map::remove(&mut module_store.deployers, &deployer); @@ -479,7 +479,7 @@ module minitia_std::vip_score { deployer, 1, vector[@0x123, @0x234], - vector[], + vector[] ); } @@ -498,7 +498,15 @@ module minitia_std::vip_score { increase_score(deployer, user, 1, 100); } - #[test(chain = @0x1, deployer_a = @0x2, deployer_b = @0x3, user_a = @0x123, user_b = @0x456)] + #[ + test( + chain = @0x1, + deployer_a = @0x2, + deployer_b = @0x3, + user_a = @0x123, + user_b = @0x456 + ) + ] fun test_e2e( chain: &signer, deployer_a: &signer, @@ -545,7 +553,7 @@ module minitia_std::vip_score { deployer_a, 2, vector[user_a, user_b], - vector[100, 200], + vector[100, 200] ); assert!(get_score(user_a, 2) == 100, 12); diff --git a/minitia_stdlib/tests/deflation_token.move b/minitia_stdlib/tests/deflation_token.move index ba888cd..1da2511 100644 --- a/minitia_stdlib/tests/deflation_token.move +++ b/minitia_stdlib/tests/deflation_token.move @@ -10,7 +10,7 @@ module 0xcafe::deflation_token { use std::string; struct BurnStore has key { - burn_ref: BurnRef, + burn_ref: BurnRef } public fun initialize( @@ -25,21 +25,19 @@ module 0xcafe::deflation_token { function_info::new_function_info( account, string::utf8(b"deflation_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); dispatchable_fungible_asset::register_dispatch_functions( constructor_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } public fun withdraw( - store: Object, - amount: u64, - transfer_ref: &TransferRef, + store: Object, amount: u64, transfer_ref: &TransferRef ): FungibleAsset acquires BurnStore { // For every withdraw, we burn 10% from the store. let burn_amount = amount / 10; @@ -58,8 +56,12 @@ module 0xcafe::deflation_token { use minitia_std::fungible_asset::{Metadata, TestToken}; #[test(creator = @0xcafe)] - #[expected_failure(major_status = 4037, location = minitia_std::dispatchable_fungible_asset)] - fun test_self_reentrancy(creator: &signer,) { + #[ + expected_failure( + major_status = 4037, location = minitia_std::dispatchable_fungible_asset + ) + ] + fun test_self_reentrancy(creator: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); diff --git a/minitia_stdlib/tests/deflation_token_tests.move b/minitia_stdlib/tests/deflation_token_tests.move index 23ea548..d5c6dc4 100644 --- a/minitia_stdlib/tests/deflation_token_tests.move +++ b/minitia_stdlib/tests/deflation_token_tests.move @@ -11,7 +11,7 @@ module 0xcafe::deflation_token_tests { use std::signer; #[test(creator = @0xcafe, aaron = @0xface)] - fun test_deflation_e2e_basic_flow(creator: &signer, aaron: &signer,) { + fun test_deflation_e2e_basic_flow(creator: &signer, aaron: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); @@ -56,9 +56,13 @@ module 0xcafe::deflation_token_tests { } #[test(creator = @0xcafe, aaron = @0xface)] - #[expected_failure(abort_code = 0x70002, location = minitia_std::dispatchable_fungible_asset)] + #[ + expected_failure( + abort_code = 0x70002, location = minitia_std::dispatchable_fungible_asset + ) + ] fun test_deflation_assert_min_deposit( - creator: &signer, aaron: &signer, + creator: &signer, aaron: &signer ) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); @@ -82,7 +86,7 @@ module 0xcafe::deflation_token_tests { #[test(creator = @0xcafe)] #[expected_failure(abort_code = 0x1001C, location = minitia_std::fungible_asset)] - fun test_deflation_fa_deposit(creator: &signer,) { + fun test_deflation_fa_deposit(creator: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); @@ -104,7 +108,7 @@ module 0xcafe::deflation_token_tests { #[test(creator = @0xcafe, aaron = @0xface)] #[expected_failure(abort_code = 0x1001C, location = minitia_std::fungible_asset)] - fun test_deflation_fa_withdraw(creator: &signer, aaron: &signer,) { + fun test_deflation_fa_withdraw(creator: &signer, aaron: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); @@ -128,7 +132,7 @@ module 0xcafe::deflation_token_tests { #[test(creator = @0xcafe, aaron = @0xface)] #[expected_failure(abort_code = 0x8001D, location = minitia_std::fungible_asset)] - fun test_double_init(creator: &signer,) { + fun test_double_init(creator: &signer) { let (creator_ref, _) = fungible_asset::create_test_token(creator); let (_, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); deflation_token::initialize(creator, &creator_ref); @@ -137,7 +141,7 @@ module 0xcafe::deflation_token_tests { function_info::new_function_info( creator, string::utf8(b"deflation_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); // Re-registering the overload function should yield an error @@ -145,20 +149,20 @@ module 0xcafe::deflation_token_tests { &creator_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } #[test(creator = @0xcafe)] #[expected_failure(abort_code = 0x10019, location = minitia_std::fungible_asset)] - fun test_register_bad_withdraw(creator: &signer,) { + fun test_register_bad_withdraw(creator: &signer) { let (creator_ref, _) = fungible_asset::create_test_token(creator); let withdraw = function_info::new_function_info( creator, string::utf8(b"deflation_token"), - string::utf8(b"initialize"), + string::utf8(b"initialize") ); // Change the deposit and withdraw function. Should give a type mismatch error. @@ -166,20 +170,20 @@ module 0xcafe::deflation_token_tests { &creator_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } #[test(creator = @0xcafe)] #[expected_failure(abort_code = 0x1001A, location = minitia_std::fungible_asset)] - fun test_register_bad_deposit(creator: &signer,) { + fun test_register_bad_deposit(creator: &signer) { let (creator_ref, _) = fungible_asset::create_test_token(creator); let withdraw = function_info::new_function_info( creator, string::utf8(b"deflation_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); // Change the deposit and withdraw function. Should give a type mismatch error. @@ -187,20 +191,20 @@ module 0xcafe::deflation_token_tests { &creator_ref, option::some(withdraw), option::some(withdraw), - option::none(), + option::none() ); } #[test(creator = @0xcafe)] #[expected_failure(abort_code = 0x1001B, location = minitia_std::fungible_asset)] - fun test_register_bad_value(creator: &signer,) { + fun test_register_bad_value(creator: &signer) { let (creator_ref, _) = fungible_asset::create_test_token(creator); let withdraw = function_info::new_function_info( creator, string::utf8(b"deflation_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); // Change the deposit and withdraw function. Should give a type mismatch error. @@ -208,14 +212,14 @@ module 0xcafe::deflation_token_tests { &creator_ref, option::some(withdraw), option::none(), - option::some(withdraw), + option::some(withdraw) ); } #[test(creator = @0xcafe, aaron = @0xface)] #[expected_failure(major_status = 1081, location = minitia_std::function_info)] fun test_register_bad_withdraw_non_exist( - creator: &signer, aaron: &signer, + creator: &signer, aaron: &signer ) { let (creator_ref, _) = fungible_asset::create_test_token(creator); @@ -223,7 +227,7 @@ module 0xcafe::deflation_token_tests { function_info::new_function_info( aaron, string::utf8(b"deflation_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); // Change the deposit and withdraw function. Should give a type mismatch error. @@ -231,20 +235,20 @@ module 0xcafe::deflation_token_tests { &creator_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } #[test(creator = @0xcafe)] #[expected_failure(abort_code = 2, location = minitia_std::function_info)] - fun test_register_bad_withdraw_non_exist_2(creator: &signer,) { + fun test_register_bad_withdraw_non_exist_2(creator: &signer) { let (creator_ref, _) = fungible_asset::create_test_token(creator); let withdraw = function_info::new_function_info( creator, string::utf8(b"deflation_token"), - string::utf8(b"withdraw2"), + string::utf8(b"withdraw2") ); // Change the deposit and withdraw function. Should give a type mismatch error. @@ -252,12 +256,12 @@ module 0xcafe::deflation_token_tests { &creator_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } #[test(creator = @0xcafe)] - fun test_calling_overloadable_api_on_regular_fa(creator: &signer,) { + fun test_calling_overloadable_api_on_regular_fa(creator: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); @@ -274,13 +278,13 @@ module 0xcafe::deflation_token_tests { #[test(creator = @0xcafe)] #[expected_failure(abort_code = 0x6001E, location = minitia_std::fungible_asset)] - fun test_register_on_non_metadata_object(creator: &signer,) { + fun test_register_on_non_metadata_object(creator: &signer) { let creator_ref = object::create_named_object(creator, b"TEST"); let withdraw = function_info::new_function_info( creator, string::utf8(b"deflation_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); // Change the deposit and withdraw function. Should give a type mismatch error. @@ -288,12 +292,12 @@ module 0xcafe::deflation_token_tests { &creator_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } #[test(creator = @0xcafe, aaron = @0xface)] - fun test_basic_flow_primary_fa(creator: &signer, aaron: &signer,) { + fun test_basic_flow_primary_fa(creator: &signer, aaron: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint_ref, transfer_ref, burn_ref) = primary_fungible_store::init_test_metadata_with_primary_store_enabled( @@ -343,7 +347,7 @@ module 0xcafe::deflation_token_tests { #[test(creator = @0xcafe, aaron = @0xface)] #[expected_failure(abort_code = 0x50003, location = minitia_std::fungible_asset)] - fun test_deflation_set_frozen(creator: &signer, aaron: &signer,) { + fun test_deflation_set_frozen(creator: &signer, aaron: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, transfer_ref, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); @@ -375,7 +379,7 @@ module 0xcafe::deflation_token_tests { #[test(creator = @0xcafe, aaron = @0xface)] #[expected_failure(abort_code = 0x50008, location = minitia_std::fungible_asset)] - fun test_deflation_wrong_withdraw(creator: &signer, aaron: &signer,) { + fun test_deflation_wrong_withdraw(creator: &signer, aaron: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); diff --git a/minitia_stdlib/tests/nil_op_token.move b/minitia_stdlib/tests/nil_op_token.move index a46dbed..8f19ac2 100644 --- a/minitia_stdlib/tests/nil_op_token.move +++ b/minitia_stdlib/tests/nil_op_token.move @@ -17,21 +17,19 @@ module 0xcafe::nil_op_token { function_info::new_function_info( account, string::utf8(b"nil_op_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); dispatchable_fungible_asset::register_dispatch_functions( constructor_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } public fun withdraw( - store: Object, - _amount: u64, - transfer_ref: &TransferRef, + store: Object, _amount: u64, transfer_ref: &TransferRef ): FungibleAsset { // Always return a one FA. fungible_asset::withdraw_with_ref(transfer_ref, store, 1) diff --git a/minitia_stdlib/tests/nil_op_token_tests.move b/minitia_stdlib/tests/nil_op_token_tests.move index 54e5cc1..317d1ab 100644 --- a/minitia_stdlib/tests/nil_op_token_tests.move +++ b/minitia_stdlib/tests/nil_op_token_tests.move @@ -7,8 +7,12 @@ module minitia_std::nil_op_token_tests { use std::option; #[test(creator = @0xcafe)] - #[expected_failure(abort_code = 0x70002, location = minitia_std::dispatchable_fungible_asset)] - fun test_nil_op_token(creator: &signer,) { + #[ + expected_failure( + abort_code = 0x70002, location = minitia_std::dispatchable_fungible_asset + ) + ] + fun test_nil_op_token(creator: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); diff --git a/minitia_stdlib/tests/permissioned_token.move b/minitia_stdlib/tests/permissioned_token.move index ac52ba3..17305e7 100644 --- a/minitia_stdlib/tests/permissioned_token.move +++ b/minitia_stdlib/tests/permissioned_token.move @@ -14,7 +14,7 @@ module 0xcafe::permissioned_token { const EWITHDRAW_NOT_ALLOWED: u64 = 1; struct AllowlistStore has key { - allowed_sender: vector
, + allowed_sender: vector
} public fun initialize( @@ -27,14 +27,14 @@ module 0xcafe::permissioned_token { function_info::new_function_info( account, string::utf8(b"permissioned_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); dispatchable_fungible_asset::register_dispatch_functions( constructor_ref, option::some(withdraw), option::none(), - option::none(), + option::none() ); } @@ -47,16 +47,14 @@ module 0xcafe::permissioned_token { } public fun withdraw( - store: Object, - amount: u64, - transfer_ref: &TransferRef, + store: Object, amount: u64, transfer_ref: &TransferRef ): FungibleAsset acquires AllowlistStore { assert!( vector::contains( &borrow_global(@0xcafe).allowed_sender, - &object::object_address(&store), + &object::object_address(&store) ), - EWITHDRAW_NOT_ALLOWED, + EWITHDRAW_NOT_ALLOWED ); fungible_asset::withdraw_with_ref(transfer_ref, store, amount) diff --git a/minitia_stdlib/tests/permissioned_token_tests.move b/minitia_stdlib/tests/permissioned_token_tests.move index e786643..bc2978d 100644 --- a/minitia_stdlib/tests/permissioned_token_tests.move +++ b/minitia_stdlib/tests/permissioned_token_tests.move @@ -8,7 +8,7 @@ module 0xcafe::permissioned_token_tests { #[test(creator = @0xcafe, aaron = @0xface)] fun test_permissioned_e2e_basic_flow( - creator: &signer, aaron: &signer, + creator: &signer, aaron: &signer ) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); @@ -18,7 +18,8 @@ module 0xcafe::permissioned_token_tests { let aaron_store = fungible_asset::create_test_store(aaron, metadata); let allowed_sender = vector[ object::object_address(&creator_store), - object::object_address(&aaron_store),]; + object::object_address(&aaron_store) + ]; permissioned_token::initialize(creator, &creator_ref, allowed_sender); @@ -41,7 +42,7 @@ module 0xcafe::permissioned_token_tests { #[test(creator = @0xcafe, aaron = @0xface)] #[expected_failure(abort_code = 1, location = 0xcafe::permissioned_token)] fun test_permissioned_disallowed_sender( - creator: &signer, aaron: &signer, + creator: &signer, aaron: &signer ) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); @@ -49,7 +50,7 @@ module 0xcafe::permissioned_token_tests { let creator_store = fungible_asset::create_test_store(creator, metadata); let aaron_store = fungible_asset::create_test_store(aaron, metadata); - let allowed_sender = vector[object::object_address(&creator_store),]; + let allowed_sender = vector[object::object_address(&creator_store)]; permissioned_token::initialize(creator, &creator_ref, allowed_sender); @@ -72,7 +73,7 @@ module 0xcafe::permissioned_token_tests { #[test(creator = @0xcafe, aaron = @0xface)] fun test_permissioned_update_disallowed_sender( - creator: &signer, aaron: &signer, + creator: &signer, aaron: &signer ) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); @@ -80,7 +81,7 @@ module 0xcafe::permissioned_token_tests { let creator_store = fungible_asset::create_test_store(creator, metadata); let aaron_store = fungible_asset::create_test_store(aaron, metadata); - let allowed_sender = vector[object::object_address(&creator_store),]; + let allowed_sender = vector[object::object_address(&creator_store)]; permissioned_token::initialize(creator, &creator_ref, allowed_sender); diff --git a/minitia_stdlib/tests/reentrant_token.move b/minitia_stdlib/tests/reentrant_token.move index 55383c2..a43728f 100644 --- a/minitia_stdlib/tests/reentrant_token.move +++ b/minitia_stdlib/tests/reentrant_token.move @@ -17,21 +17,19 @@ module 0xcafe::reentrant_token { function_info::new_function_info( account, string::utf8(b"reentrant_token"), - string::utf8(b"deposit"), + string::utf8(b"deposit") ); dispatchable_fungible_asset::register_dispatch_functions( constructor_ref, option::none(), option::some(deposit), - option::none(), + option::none() ); } public fun deposit( - store: Object, - fa: FungibleAsset, - _transfer_ref: &TransferRef, + store: Object, fa: FungibleAsset, _transfer_ref: &TransferRef ) { // Re-entering into dispatchable_fungible_asset. Will be rejected by the MoveVM runtime. dispatchable_fungible_asset::deposit(store, fa); diff --git a/minitia_stdlib/tests/reentrant_token_tests.move b/minitia_stdlib/tests/reentrant_token_tests.move index e04f398..bf414dd 100644 --- a/minitia_stdlib/tests/reentrant_token_tests.move +++ b/minitia_stdlib/tests/reentrant_token_tests.move @@ -7,8 +7,12 @@ module 0xcafe::reentrant_token_tests { use std::option; #[test(creator = @0xcafe)] - #[expected_failure(major_status = 4037, location = minitia_std::dispatchable_fungible_asset)] - fun test_reentrant_deposit(creator: &signer,) { + #[ + expected_failure( + major_status = 4037, location = minitia_std::dispatchable_fungible_asset + ) + ] + fun test_reentrant_deposit(creator: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); diff --git a/minitia_stdlib/tests/simple_dispatchable_token.move b/minitia_stdlib/tests/simple_dispatchable_token.move index 4dfc0bf..263d347 100644 --- a/minitia_stdlib/tests/simple_dispatchable_token.move +++ b/minitia_stdlib/tests/simple_dispatchable_token.move @@ -18,36 +18,32 @@ module 0xcafe::simple_token { function_info::new_function_info( account, string::utf8(b"simple_token"), - string::utf8(b"withdraw"), + string::utf8(b"withdraw") ); let deposit = function_info::new_function_info( account, string::utf8(b"simple_token"), - string::utf8(b"deposit"), + string::utf8(b"deposit") ); dispatchable_fungible_asset::register_dispatch_functions( constructor_ref, option::some(withdraw), option::some(deposit), - option::none(), + option::none() ); } public fun withdraw( - store: Object, - amount: u64, - transfer_ref: &TransferRef, + store: Object, amount: u64, transfer_ref: &TransferRef ): FungibleAsset { fungible_asset::withdraw_with_ref(transfer_ref, store, amount) } public fun deposit( - store: Object, - fa: FungibleAsset, - transfer_ref: &TransferRef, + store: Object, fa: FungibleAsset, transfer_ref: &TransferRef ) { fungible_asset::deposit_with_ref(transfer_ref, store, fa) } diff --git a/minitia_stdlib/tests/simple_dispatchable_token_fa_tests.move b/minitia_stdlib/tests/simple_dispatchable_token_fa_tests.move index 8d6ec00..80e6bdd 100644 --- a/minitia_stdlib/tests/simple_dispatchable_token_fa_tests.move +++ b/minitia_stdlib/tests/simple_dispatchable_token_fa_tests.move @@ -38,7 +38,7 @@ module minitia_std::simple_token_fa_tests { } #[test(creator = @0xcafe, aaron = @0xface)] - fun test_transfer_with_ref(creator: &signer, aaron: &signer,) { + fun test_transfer_with_ref(creator: &signer, aaron: &signer) { let (creator_ref, test_token) = create_test_token(creator); let (mint_ref, transfer_ref, _burn_ref, _mutate_metadata_ref) = init_test_metadata(&creator_ref); diff --git a/minitia_stdlib/tests/simple_dispatchable_token_pfs_tests.move b/minitia_stdlib/tests/simple_dispatchable_token_pfs_tests.move index f6fcd2a..81b42c6 100644 --- a/minitia_stdlib/tests/simple_dispatchable_token_pfs_tests.move +++ b/minitia_stdlib/tests/simple_dispatchable_token_pfs_tests.move @@ -16,7 +16,7 @@ module minitia_std::simple_token_pfs_tests { deposit_with_ref, withdraw_with_ref, primary_store_exists, - ensure_primary_store_exists, + ensure_primary_store_exists }; use 0xcafe::simple_token; use std::signer; @@ -42,7 +42,7 @@ module minitia_std::simple_token_pfs_tests { } #[test(creator = @0xcafe, aaron = @0xface)] - fun test_basic_flow(creator: &signer, aaron: &signer,) { + fun test_basic_flow(creator: &signer, aaron: &signer) { let (creator_ref, metadata) = create_test_token(creator); let (mint_ref, transfer_ref, burn_ref) = init_test_metadata_with_primary_store_enabled(&creator_ref); @@ -71,7 +71,7 @@ module minitia_std::simple_token_pfs_tests { #[test(creator = @0xcafe, aaron = @0xface)] fun test_basic_flow_with_min_balance( - creator: &signer, aaron: &signer, + creator: &signer, aaron: &signer ) { let (creator_ref, metadata) = create_test_token(creator); let (mint_ref, _transfer_ref, _) = diff --git a/minitia_stdlib/tests/ten_x_token.move b/minitia_stdlib/tests/ten_x_token.move index c000f46..a65497d 100644 --- a/minitia_stdlib/tests/ten_x_token.move +++ b/minitia_stdlib/tests/ten_x_token.move @@ -18,19 +18,19 @@ module 0xcafe::ten_x_token { function_info::new_function_info( account, string::utf8(b"ten_x_token"), - string::utf8(b"derived_balance"), + string::utf8(b"derived_balance") ); let supply_value = function_info::new_function_info( account, string::utf8(b"ten_x_token"), - string::utf8(b"derived_supply"), + string::utf8(b"derived_supply") ); dispatchable_fungible_asset::register_dispatch_functions( constructor_ref, option::none(), option::none(), - option::some(balance_value), + option::some(balance_value) ); dispatchable_fungible_asset::register_derive_supply_dispatch_function( constructor_ref, option::some(supply_value) diff --git a/minitia_stdlib/tests/ten_x_token_tests.move b/minitia_stdlib/tests/ten_x_token_tests.move index 9ee2bcf..cffbbf2 100644 --- a/minitia_stdlib/tests/ten_x_token_tests.move +++ b/minitia_stdlib/tests/ten_x_token_tests.move @@ -7,7 +7,7 @@ module minitia_std::ten_x_token_tests { use std::option; #[test(creator = @0xcafe)] - fun test_ten_x(creator: &signer,) { + fun test_ten_x(creator: &signer) { let (creator_ref, token_object) = fungible_asset::create_test_token(creator); let (mint, _, _, _) = fungible_asset::init_test_metadata(&creator_ref); let metadata = object::convert(token_object); diff --git a/move_nursery/sources/acl.move b/move_nursery/sources/acl.move index da6480e..239e9ef 100644 --- a/move_nursery/sources/acl.move +++ b/move_nursery/sources/acl.move @@ -25,7 +25,7 @@ module std::acl { public fun add(acl: &mut ACL, addr: address) { assert!( !vector::contains(&mut acl.list, &addr), - error::invalid_argument(ECONTAIN), + error::invalid_argument(ECONTAIN) ); vector::push_back(&mut acl.list, addr); } @@ -46,7 +46,7 @@ module std::acl { public fun assert_contains(acl: &ACL, addr: address) { assert!( contains(acl, addr), - error::invalid_argument(ENOT_CONTAIN), + error::invalid_argument(ENOT_CONTAIN) ); } } diff --git a/move_nursery/sources/capability.move b/move_nursery/sources/capability.move index bbcdf6b..136c75f 100644 --- a/move_nursery/sources/capability.move +++ b/move_nursery/sources/capability.move @@ -108,7 +108,7 @@ module std::capability { let addr = signer::address_of(owner); assert!( !exists>(addr), - error::already_exists(ECAP), + error::already_exists(ECAP) ); move_to>(owner, CapState { delegates: vector::empty() }); } @@ -119,7 +119,9 @@ module std::capability { public fun acquire( requester: &signer, _feature_witness: &Feature ): Cap acquires CapState, CapDelegateState { - Cap { root: validate_acquire(requester) } + Cap { + root: validate_acquire(requester) + } } /// Acquires a linear capability token. It is up to the module which owns `Feature` to decide @@ -127,7 +129,9 @@ module std::capability { public fun acquire_linear( requester: &signer, _feature_witness: &Feature ): LinearCap acquires CapState, CapDelegateState { - LinearCap { root: validate_acquire(requester) } + LinearCap { + root: validate_acquire(requester) + } } /// Helper to validate an acquire. Returns the root address of the capability. @@ -138,20 +142,20 @@ module std::capability { // double check that requester is actually registered as a delegate assert!( exists>(root_addr), - error::invalid_state(EDELEGATE), + error::invalid_state(EDELEGATE) ); assert!( vector::contains( &borrow_global>(root_addr).delegates, - &addr, + &addr ), - error::invalid_state(EDELEGATE), + error::invalid_state(EDELEGATE) ); root_addr } else { assert!( exists>(addr), - error::not_found(ECAP), + error::not_found(ECAP) ); addr } @@ -182,11 +186,11 @@ module std::capability { if (exists>(addr)) return; move_to( to, - CapDelegateState { root: cap.root }, + CapDelegateState { root: cap.root } ); add_element( &mut borrow_global_mut>(cap.root).delegates, - addr, + addr ); } @@ -199,7 +203,7 @@ module std::capability { let CapDelegateState { root: _root } = move_from>(from); remove_element( &mut borrow_global_mut>(cap.root).delegates, - &from, + &from ); } diff --git a/move_nursery/sources/compare.move b/move_nursery/sources/compare.move index beed63b..54864c6 100644 --- a/move_nursery/sources/compare.move +++ b/move_nursery/sources/compare.move @@ -51,7 +51,7 @@ module std::compare { i2 = i2 - 1; let elem_cmp = cmp_u8( *vector::borrow(v1, i1), - *vector::borrow(v2, i2), + *vector::borrow(v2, i2) ); if (elem_cmp != 0) return elem_cmp // else, compare next element diff --git a/move_nursery/sources/guid.move b/move_nursery/sources/guid.move index 99289ca..1f8fdf2 100644 --- a/move_nursery/sources/guid.move +++ b/move_nursery/sources/guid.move @@ -5,7 +5,7 @@ module std::guid { /// A generator for new GUIDs. struct Generator has key { /// A monotonically increasing counter - counter: u64, + counter: u64 } /// A globally unique identifier derived from the sender's address and a counter @@ -49,7 +49,7 @@ module std::guid { ): GUID acquires Generator { assert!( exists(addr), - EGUID_GENERATOR_NOT_PUBLISHED, + EGUID_GENERATOR_NOT_PUBLISHED ); create_impl(addr) } diff --git a/move_stdlib/sources/ascii.move b/move_stdlib/sources/ascii.move index a0ba642..da13c27 100644 --- a/move_stdlib/sources/ascii.move +++ b/move_stdlib/sources/ascii.move @@ -13,7 +13,7 @@ module std::ascii { /// characters you should use the `all_characters_printable` predicate /// defined in this module. struct String has copy, drop, store { - bytes: vector, + bytes: vector } spec String { @@ -22,7 +22,7 @@ module std::ascii { /// An ASCII character. struct Char has copy, drop, store { - byte: u8, + byte: u8 } spec Char { @@ -58,12 +58,12 @@ module std::ascii { let len = vector::length(&bytes); let i = 0; while ({ - spec { - invariant i <= len; - invariant forall j in 0..i: is_valid_char(bytes[j]); - }; - i < len - }) { + spec { + invariant i <= len; + invariant forall j in 0..i: is_valid_char(bytes[j]); + }; + i < len + }) { let possible_byte = *vector::borrow(&bytes, i); if (!is_valid_char(possible_byte)) return option::none(); i = i + 1; @@ -81,12 +81,12 @@ module std::ascii { let len = vector::length(&string.bytes); let i = 0; while ({ - spec { - invariant i <= len; - invariant forall j in 0..i: is_printable_char(string.bytes[j]); - }; - i < len - }) { + spec { + invariant i <= len; + invariant forall j in 0..i: is_printable_char(string.bytes[j]); + }; + i < len + }) { let byte = *vector::borrow(&string.bytes, i); if (!is_printable_char(byte)) return false; i = i + 1; diff --git a/move_stdlib/sources/bit_vector.move b/move_stdlib/sources/bit_vector.move index a88dfba..19d58c3 100644 --- a/move_stdlib/sources/bit_vector.move +++ b/move_stdlib/sources/bit_vector.move @@ -12,7 +12,7 @@ module std::bit_vector { struct BitVector has copy, drop, store { length: u64, - bit_field: vector, + bit_field: vector } public fun new(length: u64): BitVector { @@ -21,12 +21,12 @@ module std::bit_vector { let counter = 0; let bit_field = vector::empty(); while ({ - spec { - invariant counter <= length; - invariant len(bit_field) == counter; - }; - (counter < length) - }) { + spec { + invariant counter <= length; + invariant len(bit_field) == counter; + }; + (counter < length) + }) { vector::push_back(&mut bit_field, false); counter = counter + 1; }; @@ -35,7 +35,7 @@ module std::bit_vector { assert len(bit_field) == length; }; - BitVector { length, bit_field, } + BitVector { length, bit_field } } spec new { @@ -54,7 +54,7 @@ module std::bit_vector { public fun set(bitvector: &mut BitVector, bit_index: u64) { assert!( bit_index < vector::length(&bitvector.bit_field), - EINDEX, + EINDEX ); let x = vector::borrow_mut(&mut bitvector.bit_field, bit_index); *x = true; @@ -75,7 +75,7 @@ module std::bit_vector { public fun unset(bitvector: &mut BitVector, bit_index: u64) { assert!( bit_index < vector::length(&bitvector.bit_field), - EINDEX, + EINDEX ); let x = vector::borrow_mut(&mut bitvector.bit_field, bit_index); *x = false; @@ -126,7 +126,7 @@ module std::bit_vector { public fun is_index_set(bitvector: &BitVector, bit_index: u64): bool { assert!( bit_index < vector::length(&bitvector.bit_field), - EINDEX, + EINDEX ); *vector::borrow(&bitvector.bit_field, bit_index) } diff --git a/move_stdlib/sources/fixed_point32.move b/move_stdlib/sources/fixed_point32.move index 33679fe..8fd6d8f 100644 --- a/move_stdlib/sources/fixed_point32.move +++ b/move_stdlib/sources/fixed_point32.move @@ -115,10 +115,7 @@ module std::fixed_point32 { let scaled_denominator = (denominator as u128) << 32; assert!(scaled_denominator != 0, EDENOMINATOR); let quotient = scaled_numerator / scaled_denominator; - assert!( - quotient != 0 || numerator == 0, - ERATIO_OUT_OF_RANGE, - ); + assert!(quotient != 0 || numerator == 0, ERATIO_OUT_OF_RANGE); // Return the quotient as a fixed-point number. We first need to check whether the cast // can succeed. assert!(quotient <= MAX_U64, ERATIO_OUT_OF_RANGE); @@ -126,6 +123,7 @@ module std::fixed_point32 { } spec create_from_rational { + pragma verify = false; // TIMEOUT pragma opaque; include CreateFromRationalAbortsIf; ensures result == spec_create_from_rational(numerator, denominator); @@ -143,7 +141,9 @@ module std::fixed_point32 { } spec fun spec_create_from_rational(numerator: num, denominator: num): FixedPoint32 { - FixedPoint32 { value: (numerator << 64) / (denominator << 32) } + FixedPoint32 { + value: (numerator << 64) / (denominator << 32) + } } /// Create a fixedpoint value from a raw value. @@ -257,6 +257,7 @@ module std::fixed_point32 { } spec ceil { + pragma verify = false; // timeout pragma opaque; aborts_if false; ensures result == spec_ceil(num); @@ -285,6 +286,7 @@ module std::fixed_point32 { spec round { pragma opaque; + pragma timeout = 120; aborts_if false; ensures result == spec_round(num); } diff --git a/move_stdlib/sources/option.move b/move_stdlib/sources/option.move index ab368b1..6dcee44 100644 --- a/move_stdlib/sources/option.move +++ b/move_stdlib/sources/option.move @@ -131,19 +131,21 @@ module std::option { t: &Option, default_ref: &Element ): &Element { let vec_ref = &t.vec; - if (vector::is_empty(vec_ref)) default_ref else vector::borrow(vec_ref, 0) + if (vector::is_empty(vec_ref)) default_ref + else vector::borrow(vec_ref, 0) } spec borrow_with_default { pragma opaque; aborts_if false; - ensures result == (if (spec_is_some(t)) spec_borrow(t) else default_ref); + ensures result == (if (spec_is_some(t)) spec_borrow(t) + else default_ref); } /// Return the value inside `t` if it holds one /// Return `default` if `t` does not hold a value public fun get_with_default( - t: &Option, default: Element, + t: &Option, default: Element ): Element { let vec_ref = &t.vec; if (vector::is_empty(vec_ref)) default else *vector::borrow(vec_ref, 0) @@ -152,15 +154,16 @@ module std::option { spec get_with_default { pragma opaque; aborts_if false; - ensures result == (if (spec_is_some(t)) spec_borrow(t) else default); + ensures result == (if (spec_is_some(t)) spec_borrow(t) + else default); } /// Convert the none option `t` to a some option by adding `e`. /// Aborts if `t` already holds a value public fun fill(t: &mut Option, e: Element) { let vec_ref = &mut t.vec; - if (vector::is_empty(vec_ref)) vector::push_back(vec_ref, e) else - abort EOPTION_IS_SET + if (vector::is_empty(vec_ref)) vector::push_back(vec_ref, e) + else abort EOPTION_IS_SET } spec fill { @@ -221,7 +224,8 @@ module std::option { public fun swap_or_fill(t: &mut Option, e: Element): Option { let vec_ref = &mut t.vec; let old_value = - if (vector::is_empty(vec_ref)) none() else some(vector::pop_back(vec_ref)); + if (vector::is_empty(vec_ref)) none() + else some(vector::pop_back(vec_ref)); vector::push_back(vec_ref, e); old_value } @@ -244,7 +248,8 @@ module std::option { spec destroy_with_default { pragma opaque; aborts_if false; - ensures result == (if (spec_is_some(t)) spec_borrow(t) else default); + ensures result == (if (spec_is_some(t)) spec_borrow(t) + else default); } /// Unpack `t` and return its contents diff --git a/move_stdlib/sources/string.move b/move_stdlib/sources/string.move index cf0ec3f..bc03084 100644 --- a/move_stdlib/sources/string.move +++ b/move_stdlib/sources/string.move @@ -11,7 +11,7 @@ module std::string { /// A `String` holds a sequence of bytes which is guaranteed to be in utf8 format. struct String has copy, drop, store { - bytes: vector, + bytes: vector } /// Creates a new string from a sequence of bytes. Aborts if the bytes do not represent valid utf8. @@ -60,7 +60,7 @@ module std::string { let bytes = &s.bytes; assert!( at <= vector::length(bytes) && internal_is_char_boundary(bytes, at), - EINVALID_INDEX, + EINVALID_INDEX ); let l = length(s); let front = sub_string(s, 0, at); @@ -78,10 +78,10 @@ module std::string { let l = vector::length(bytes); assert!( j <= l - && i <= j - && internal_is_char_boundary(bytes, i) - && internal_is_char_boundary(bytes, j), - EINVALID_INDEX, + && i <= j + && internal_is_char_boundary(bytes, i) + && internal_is_char_boundary(bytes, j), + EINVALID_INDEX ); String { bytes: internal_sub_string(bytes, i, j) } } diff --git a/move_stdlib/sources/vector.move b/move_stdlib/sources/vector.move index 59f996a..2ad413d 100644 --- a/move_stdlib/sources/vector.move +++ b/move_stdlib/sources/vector.move @@ -39,7 +39,9 @@ module std::vector { #[bytecode_instruction] /// Add element `e` to the end of the vector `v`. - native public fun push_back(v: &mut vector, e: Element); + native public fun push_back( + v: &mut vector, e: Element + ); #[bytecode_instruction] /// Return a mutable reference to the `i`th element in the vector `v`. @@ -59,7 +61,9 @@ module std::vector { #[bytecode_instruction] /// Swaps the elements at the `i`th and `j`th indices in the vector `v`. /// Aborts if `i` or `j` is out of bounds. - native public fun swap(v: &mut vector, i: u64, j: u64); + native public fun swap( + v: &mut vector, i: u64, j: u64 + ); /// Return an vector of size one containing element `e`. public fun singleton(e: Element): vector { @@ -253,7 +257,7 @@ module std::vector { { i = i + 1; i - }, + } ); pop_back(v) } @@ -331,7 +335,9 @@ module std::vector { /// Apply the function to each pair of elements in the two given vectors, consuming them. public inline fun zip( - v1: vector, v2: vector, f: |Element1, Element2| + v1: vector, + v2: vector, + f: |Element1, Element2| ) { // We need to reverse the vectors to consume it efficiently reverse(&mut v1); @@ -344,7 +350,7 @@ module std::vector { public inline fun zip_reverse( v1: vector, v2: vector, - f: |Element1, Element2|, + f: |Element1, Element2| ) { let len = length(&v1); // We can't use the constant EVECTORS_LENGTH_MISMATCH here as all calling code would then need to define it @@ -363,7 +369,7 @@ module std::vector { public inline fun zip_ref( v1: &vector, v2: &vector, - f: |&Element1, &Element2|, + f: |&Element1, &Element2| ) { let len = length(v1); // We can't use the constant EVECTORS_LENGTH_MISMATCH here as all calling code would then need to define it @@ -405,7 +411,7 @@ module std::vector { public inline fun zip_mut( v1: &mut vector, v2: &mut vector, - f: |&mut Element1, &mut Element2|, + f: |&mut Element1, &mut Element2| ) { let i = 0; let len = length(v1); @@ -513,7 +519,7 @@ module std::vector { v, |elem| { if (p(&elem)) push_back(&mut result, elem); - }, + } ); result }