From d32352427be0c72e6cda575d85244081ae2a8c4e Mon Sep 17 00:00:00 2001 From: ALPAC-4 Date: Tue, 22 Oct 2024 16:17:23 +0900 Subject: [PATCH] update to v0.5.0 --- initia_stdlib/doc/account.md | 12 +- initia_stdlib/doc/bigdecimal.md | 6 +- initia_stdlib/doc/code.md | 39 +- initia_stdlib/doc/coin.md | 42 +- initia_stdlib/doc/collection.md | 5 +- initia_stdlib/doc/cosmos.md | 6 +- initia_stdlib/doc/dex.md | 235 +- .../doc/dispatchable_fungible_asset.md | 12 +- initia_stdlib/doc/ed25519.md | 6 +- initia_stdlib/doc/fixed_point64.md | 5 +- initia_stdlib/doc/fungible_asset.md | 19 +- initia_stdlib/doc/initia_nft.md | 18 +- initia_stdlib/doc/json.md | 218 +- initia_stdlib/doc/minitswap.md | 81 +- initia_stdlib/doc/multisig.md | 16 +- initia_stdlib/doc/nft.md | 27 +- initia_stdlib/doc/object.md | 40 +- initia_stdlib/doc/primary_fungible_store.md | 35 +- initia_stdlib/doc/secp256k1.md | 46 +- initia_stdlib/doc/simple_map.md | 4 +- initia_stdlib/doc/simple_nft.md | 12 +- initia_stdlib/doc/stableswap.md | 62 +- initia_stdlib/doc/staking.md | 84 +- initia_stdlib/sources/account.move | 45 +- initia_stdlib/sources/any.move | 5 +- initia_stdlib/sources/bigdecimal.move | 26 +- initia_stdlib/sources/biguint.move | 40 +- initia_stdlib/sources/code.move | 53 +- initia_stdlib/sources/coin.move | 23 +- initia_stdlib/sources/copyable_any.move | 5 +- initia_stdlib/sources/cosmos.move | 103 +- initia_stdlib/sources/crypto/ed25519.move | 6 +- initia_stdlib/sources/crypto/secp256k1.move | 26 +- initia_stdlib/sources/debug.move | 10 +- initia_stdlib/sources/dex.move | 130 +- .../fa/dispatchable_fungible_asset.move | 12 +- initia_stdlib/sources/fa/fungible_asset.move | 97 +- .../sources/fa/primary_fungible_store.move | 35 +- initia_stdlib/sources/fixed_point64.move | 5 +- initia_stdlib/sources/json.move | 92 +- initia_stdlib/sources/managed_coin.move | 35 +- initia_stdlib/sources/math128.move | 6 +- initia_stdlib/sources/math64.move | 5 +- initia_stdlib/sources/minitswap.move | 138 +- initia_stdlib/sources/multisig.move | 16 +- initia_stdlib/sources/multisig_v2.move | 2465 +++++++++++++++++ initia_stdlib/sources/object.move | 18 +- initia_stdlib/sources/simple_map.move | 4 +- initia_stdlib/sources/stableswap.move | 73 +- initia_stdlib/sources/staking.move | 167 +- initia_stdlib/sources/string_utils.move | 44 +- initia_stdlib/sources/token/collection.move | 32 +- initia_stdlib/sources/token/initia_nft.move | 30 +- initia_stdlib/sources/token/nft.move | 38 +- initia_stdlib/sources/token/property_map.move | 79 +- initia_stdlib/sources/token/royalty.move | 10 +- initia_stdlib/sources/token/simple_nft.move | 12 +- .../sources/token/soul_bound_token.move | 108 +- .../sources/transaction_context.move | 5 +- .../tests/deflation_token_tests.move | 5 +- .../simple_dispatchable_token_pfs_tests.move | 7 +- initia_stdlib/tests/ten_x_token_tests.move | 3 +- minitia_stdlib/doc/account.md | 12 +- minitia_stdlib/doc/bigdecimal.md | 6 +- minitia_stdlib/doc/code.md | 39 +- minitia_stdlib/doc/coin.md | 42 +- minitia_stdlib/doc/collection.md | 5 +- minitia_stdlib/doc/cosmos.md | 6 +- minitia_stdlib/doc/dex.md | 235 +- .../doc/dispatchable_fungible_asset.md | 12 +- minitia_stdlib/doc/ed25519.md | 6 +- minitia_stdlib/doc/fixed_point64.md | 5 +- minitia_stdlib/doc/fungible_asset.md | 3 +- minitia_stdlib/doc/initia_nft.md | 18 +- minitia_stdlib/doc/json.md | 218 +- minitia_stdlib/doc/multisig.md | 16 +- minitia_stdlib/doc/nft.md | 27 +- minitia_stdlib/doc/object.md | 40 +- minitia_stdlib/doc/primary_fungible_store.md | 33 +- minitia_stdlib/doc/score.md | 6 +- minitia_stdlib/doc/secp256k1.md | 46 +- minitia_stdlib/doc/simple_map.md | 4 +- minitia_stdlib/doc/simple_nft.md | 12 +- minitia_stdlib/sources/account.move | 45 +- minitia_stdlib/sources/any.move | 5 +- minitia_stdlib/sources/bigdecimal.move | 26 +- minitia_stdlib/sources/biguint.move | 40 +- minitia_stdlib/sources/code.move | 53 +- minitia_stdlib/sources/coin.move | 17 +- minitia_stdlib/sources/copyable_any.move | 5 +- minitia_stdlib/sources/cosmos.move | 103 +- minitia_stdlib/sources/crypto/ed25519.move | 6 +- minitia_stdlib/sources/crypto/secp256k1.move | 24 +- minitia_stdlib/sources/debug.move | 10 +- minitia_stdlib/sources/dex.move | 130 +- .../fa/dispatchable_fungible_asset.move | 12 +- minitia_stdlib/sources/fa/fungible_asset.move | 72 +- .../sources/fa/primary_fungible_store.move | 33 +- minitia_stdlib/sources/fixed_point64.move | 5 +- minitia_stdlib/sources/json.move | 92 +- minitia_stdlib/sources/managed_coin.move | 35 +- minitia_stdlib/sources/math128.move | 6 +- minitia_stdlib/sources/math64.move | 5 +- minitia_stdlib/sources/multisig.move | 16 +- minitia_stdlib/sources/multisig_v2.move | 2465 +++++++++++++++++ minitia_stdlib/sources/object.move | 18 +- minitia_stdlib/sources/simple_map.move | 4 +- minitia_stdlib/sources/string_utils.move | 44 +- minitia_stdlib/sources/token/collection.move | 35 +- minitia_stdlib/sources/token/initia_nft.move | 30 +- minitia_stdlib/sources/token/nft.move | 38 +- .../sources/token/property_map.move | 79 +- minitia_stdlib/sources/token/royalty.move | 10 +- minitia_stdlib/sources/token/simple_nft.move | 12 +- .../sources/token/soul_bound_token.move | 108 +- .../sources/transaction_context.move | 5 +- minitia_stdlib/sources/type_info.move | 5 +- minitia_stdlib/sources/vip/score.move | 13 +- .../tests/deflation_token_tests.move | 5 +- .../simple_dispatchable_token_pfs_tests.move | 7 +- minitia_stdlib/tests/ten_x_token_tests.move | 3 +- move_nursery/sources/capability.move | 5 +- move_stdlib/sources/fixed_point32.move | 5 +- move_stdlib/sources/vector.move | 17 +- 124 files changed, 6968 insertions(+), 2514 deletions(-) create mode 100644 initia_stdlib/sources/multisig_v2.move create mode 100644 minitia_stdlib/sources/multisig_v2.move diff --git a/initia_stdlib/doc/account.md b/initia_stdlib/doc/account.md index 43802ef..999c060 100644 --- a/initia_stdlib/doc/account.md +++ b/initia_stdlib/doc/account.md @@ -211,11 +211,7 @@ as both cannot have a pubkey, there is no way to use the account externally. error::already_exists(EACCOUNT_ALREADY_EXISTS) ); - request_create_account( - addr, - account_number, - ACCOUNT_TYPE_TABLE - ) + request_create_account(addr, account_number, ACCOUNT_TYPE_TABLE) } @@ -242,11 +238,7 @@ as both cannot have a pubkey, there is no way to use the account externally. // 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 - ) + 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, diff --git a/initia_stdlib/doc/bigdecimal.md b/initia_stdlib/doc/bigdecimal.md index 1c35a5e..5de3e7d 100644 --- a/initia_stdlib/doc/bigdecimal.md +++ b/initia_stdlib/doc/bigdecimal.md @@ -337,7 +337,8 @@ Create a BigDecimal from a scaled BigUint le_bytes value.
public fun from_ratio(numerator: BigUint, denominator: BigUint): BigDecimal {
     assert!(
-        !biguint::is_zero(denominator), error::invalid_argument(EDIVISION_BY_ZERO)
+        !biguint::is_zero(denominator),
+        error::invalid_argument(EDIVISION_BY_ZERO)
     );
 
     let numerator = biguint::mul(numerator, f());
@@ -1093,7 +1094,8 @@ Create a BigDecimal from a scaled BigUint le_bytes value.
 
 
public fun div(num1: BigDecimal, num2: BigDecimal): BigDecimal {
     assert!(
-        !biguint::is_zero(num2.scaled), error::invalid_argument(EDIVISION_BY_ZERO)
+        !biguint::is_zero(num2.scaled),
+        error::invalid_argument(EDIVISION_BY_ZERO)
     );
 
     BigDecimal {
diff --git a/initia_stdlib/doc/code.md b/initia_stdlib/doc/code.md
index dceb074..a837123 100644
--- a/initia_stdlib/doc/code.md
+++ b/initia_stdlib/doc/code.md
@@ -349,6 +349,7 @@ strengthened but not weakened.
         signer::address_of(chain) == @initia_std,
         error::permission_denied(EINVALID_CHAIN_OPERATOR)
     );
+    assert_no_duplication(&module_ids);
 
     let metadata_table = table::new<String, ModuleMetadata>();
     vector::for_each_ref(
@@ -433,7 +434,10 @@ strengthened but not weakened.
 
     let registry = borrow_global_mut<MetadataStore>(code_object_addr);
     let iter = table::iter_mut(
-        &mut registry.metadata, option::none(), option::none(), 1
+        &mut registry.metadata,
+        option::none(),
+        option::none(),
+        1
     );
     loop {
         if (!table::prepare_mut(iter)) { break };
@@ -473,23 +477,7 @@ package.
         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
-            );
-        }
-    );
+    assert_no_duplication(&module_ids);
 
     // Check whether arbitrary publish is allowed or not.
     let module_store = borrow_global_mut<ModuleStore>(@initia_std);
@@ -503,13 +491,11 @@ package.
     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 new_modules = 0;
     let metadata_table = &mut borrow_global_mut<MetadataStore>(addr).metadata;
     vector::for_each_ref(
         &module_ids,
@@ -525,8 +511,7 @@ package.
                 );
                 assert!(
                     can_change_upgrade_policy_to(
-                        metadata.upgrade_policy,
-                        upgrade_policy
+                        metadata.upgrade_policy, upgrade_policy
                     ),
                     error::invalid_argument(EUPGRADE_WEAKER_POLICY)
                 );
@@ -538,6 +523,7 @@ package.
                     *module_id,
                     ModuleMetadata { upgrade_policy }
                 );
+                new_modules = new_modules + 1;
             };
 
             event::emit(
@@ -546,8 +532,11 @@ package.
         }
     );
 
+    if (new_modules > 0) {
+        increase_total_modules(new_modules)
+    };
+
     // Request publish
-    increase_total_modules(vector::length(&module_ids));
     request_publish(addr, module_ids, code)
 }
 
diff --git a/initia_stdlib/doc/coin.md b/initia_stdlib/doc/coin.md index c50801a..e7659c0 100644 --- a/initia_stdlib/doc/coin.md +++ b/initia_stdlib/doc/coin.md @@ -11,6 +11,7 @@ TODO - make is_module_account or some blacklist from freeze. - [Struct `MintCapability`](#0x1_coin_MintCapability) - [Struct `BurnCapability`](#0x1_coin_BurnCapability) - [Struct `FreezeCapability`](#0x1_coin_FreezeCapability) +- [Struct `Coin`](#0x1_coin_Coin) - [Constants](#@Constants_0) - [Function `sudo_transfer`](#0x1_coin_sudo_transfer) - [Function `sudo_deposit`](#0x1_coin_sudo_deposit) @@ -188,6 +189,30 @@ TODO - make is_module_account or some blacklist from freeze. + + +## Struct `Coin` + + + +
struct Coin<CoinType>
+
+ + + +##### Fields + + +
+
+dummy_field: bool +
+
+ +
+
+ + ## Constants @@ -339,10 +364,7 @@ Only fungible asset metadata owner can make changes. ): (MintCapability, BurnCapability, FreezeCapability, ExtendRef) { // create object for fungible asset metadata let constructor_ref = - &object::create_named_object( - creator, - *string::bytes(&symbol) - ); + &object::create_named_object(creator, *string::bytes(&symbol)); primary_fungible_store::create_primary_store_enabled_fungible_asset( constructor_ref, @@ -571,11 +593,7 @@ Freeze the primary store of an account. ); 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) }
@@ -608,11 +626,7 @@ Unfreeze the primary store of an account. ); 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) } diff --git a/initia_stdlib/doc/collection.md b/initia_stdlib/doc/collection.md index 4949e3b..108c7f8 100644 --- a/initia_stdlib/doc/collection.md +++ b/initia_stdlib/doc/collection.md @@ -906,10 +906,7 @@ if start_after is not none, seach nfts in range (start_after, ...] && 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 } - ); + vector::push_back(&mut res, NftResponse { token_id, nft: *nft }); }; res diff --git a/initia_stdlib/doc/cosmos.md b/initia_stdlib/doc/cosmos.md index 689c9ba..b4eed82 100644 --- a/initia_stdlib/doc/cosmos.md +++ b/initia_stdlib/doc/cosmos.md @@ -322,11 +322,7 @@ execution after the move execution finished.
public entry fun fund_community_pool(
     sender: &signer, metadata: Object<Metadata>, amount: u64
 ) {
-    fund_community_pool_internal(
-        signer::address_of(sender),
-        &metadata,
-        amount
-    )
+    fund_community_pool_internal(signer::address_of(sender), &metadata, amount)
 }
 
diff --git a/initia_stdlib/doc/dex.md b/initia_stdlib/doc/dex.md index f4b8c74..c99add0 100644 --- a/initia_stdlib/doc/dex.md +++ b/initia_stdlib/doc/dex.md @@ -34,6 +34,8 @@ - [Function `get_swap_simulation_by_denom`](#0x1_dex_get_swap_simulation_by_denom) - [Function `get_swap_simulation_given_out`](#0x1_dex_get_swap_simulation_given_out) - [Function `get_swap_simulation_given_out_by_denom`](#0x1_dex_get_swap_simulation_given_out_by_denom) +- [Function `get_provide_simulation`](#0x1_dex_get_provide_simulation) +- [Function `get_single_asset_provide_simulation`](#0x1_dex_get_single_asset_provide_simulation) - [Function `get_pool_info`](#0x1_dex_get_pool_info) - [Function `get_pool_info_by_denom`](#0x1_dex_get_pool_info_by_denom) - [Function `get_config`](#0x1_dex_get_config) @@ -1377,6 +1379,67 @@ Return swap simulation result + + +## Function `get_provide_simulation` + + + +
#[view]
+public fun get_provide_simulation(pair: object::Object<dex::Config>, coin_a_amount_in: u64, coin_b_amount_in: u64): u64
+
+ + + +##### Implementation + + +
public fun get_provide_simulation(
+    pair: Object<Config>, 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>(pool_addr);
+
+    calculate_provide_liquidity_return_amount(
+        pool, pair, coin_a_amount_in, coin_b_amount_in
+    )
+}
+
+ + + + + +## Function `get_single_asset_provide_simulation` + + + +
#[view]
+public fun get_single_asset_provide_simulation(pair: object::Object<dex::Config>, offer_asset_metadata: object::Object<fungible_asset::Metadata>, amount_in: u64): u64
+
+ + + +##### Implementation + + +
public fun get_single_asset_provide_simulation(
+    pair: Object<Config>, offer_asset_metadata: Object<Metadata>, amount_in: u64
+): u64 acquires Config, Pool {
+    let pair_addr = object::object_address(&pair);
+    let pool = borrow_global<Pool>(pair_addr);
+
+    let (liquidity_amount, _, _) =
+        calculate_single_asset_provide_liquidity_return_amount(
+            pool, pair, offer_asset_metadata, amount_in
+        );
+
+    liquidity_amount
+}
+
+ + + ## Function `get_pool_info` @@ -1571,7 +1634,9 @@ get config 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 { @@ -2046,16 +2111,8 @@ get config 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( @@ -2128,16 +2185,8 @@ only LP struct owner can initialize } }; - 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( @@ -2391,18 +2440,12 @@ Swap with the coin in the coin store offer_coin_amount: 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 - ), + || *option::borrow(&min_return) <= fungible_asset::amount(&return_coin), error::invalid_state(EMIN_RETURN) ); @@ -2560,86 +2603,24 @@ CONTRACT: not allow until LBP is ended min_liquidity_amount: Option<u64> ): FungibleAsset acquires Config, CoinCapabilities, Pool { 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 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<Pool>(pair_addr); - 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); - - (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 = - 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 + 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 = - 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); + let pair_key = generate_pair_key(pair); // check min liquidity assertion assert!( @@ -2653,9 +2634,9 @@ CONTRACT: not allow until LBP is ended 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 } @@ -2732,18 +2713,10 @@ Swap directly 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 - ) + 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 - ) + fungible_asset::withdraw(pair_signer, pool.coin_a_store, return_amount) }; // emit events @@ -2828,10 +2801,7 @@ Swap directly 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 } - ); + move_to(pair_signer, Pool { coin_a_store, coin_b_store }); move_to( pair_signer, @@ -2942,33 +2912,12 @@ CONTRACT: not allow until LBP is ended 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 = - 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 - ) - } - }; + calculate_provide_liquidity_return_amount( + pool, pair, coin_a_amount_in, coin_b_amount_in + ); assert!( option::is_none(&min_liquidity_amount) diff --git a/initia_stdlib/doc/dispatchable_fungible_asset.md b/initia_stdlib/doc/dispatchable_fungible_asset.md index d5d9ac2..04e1caa 100644 --- a/initia_stdlib/doc/dispatchable_fungible_asset.md +++ b/initia_stdlib/doc/dispatchable_fungible_asset.md @@ -242,12 +242,7 @@ The semantics of deposit will be governed by the function specified in DispatchF 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 - ) + dispatchable_deposit(store, fa, borrow_transfer_ref(store), func) } else { fungible_asset::deposit_internal(object::object_address(&store), fa) } @@ -313,7 +308,10 @@ Note: it does not move the underlying object. let fa = withdraw(sender, from, amount); deposit(to, fa); let end = fungible_asset::balance(to); - assert!(end - start >= expected, error::aborted(EAMOUNT_MISMATCH)); + assert!( + end - start >= expected, + error::aborted(EAMOUNT_MISMATCH) + ); } diff --git a/initia_stdlib/doc/ed25519.md b/initia_stdlib/doc/ed25519.md index 21787aa..84d3fcf 100644 --- a/initia_stdlib/doc/ed25519.md +++ b/initia_stdlib/doc/ed25519.md @@ -243,11 +243,7 @@ Verifies a Ed25519 signature under an public_key on th
public fun verify(
     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)
 }
 
diff --git a/initia_stdlib/doc/fixed_point64.md b/initia_stdlib/doc/fixed_point64.md index 9da9a36..7c7ee5e 100644 --- a/initia_stdlib/doc/fixed_point64.md +++ b/initia_stdlib/doc/fixed_point64.md @@ -613,7 +613,10 @@ rounding, e.g., 0.0125 will round down to 0.012 instead of up to 0.013. 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); diff --git a/initia_stdlib/doc/fungible_asset.md b/initia_stdlib/doc/fungible_asset.md index 3b9f93e..a945727 100644 --- a/initia_stdlib/doc/fungible_asset.md +++ b/initia_stdlib/doc/fungible_asset.md @@ -1172,8 +1172,7 @@ Define the derived supply dispatch with the provided function. // 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 + &function_info, supply_function ), error::invalid_argument( EDERIVED_SUPPLY_FUNCTION_SIGNATURE_MISMATCH @@ -1419,7 +1418,13 @@ Get the symbol of the fungible asset from the metadata object.
public fun symbol<T: key>(metadata: Object<T>): 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
 }
 
@@ -1511,7 +1516,13 @@ Get the decimals from the metadata object.
public fun decimals<T: key>(metadata: Object<T>): 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
 }
 
diff --git a/initia_stdlib/doc/initia_nft.md b/initia_stdlib/doc/initia_nft.md index ccac1b7..7014af7 100644 --- a/initia_stdlib/doc/initia_nft.md +++ b/initia_stdlib/doc/initia_nft.md @@ -181,22 +181,22 @@ The provided signer is not the creator - + -The NFT is not allowed to burn +The provided signer is not the owner -
const ECAN_NOT_BURN: u64 = 6;
+
const ENOT_OWNER: u64 = 5;
 
- + -The provided signer is not the owner +The NFT is not allowed to burn -
const ENOT_OWNER: u64 = 5;
+
const ECAN_NOT_BURN: u64 = 6;
 
@@ -366,11 +366,7 @@ With an existing collection, directly mint a viable nft into the creators accoun 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)); } }
diff --git a/initia_stdlib/doc/json.md b/initia_stdlib/doc/json.md index 9d4de2a..59d0ff2 100644 --- a/initia_stdlib/doc/json.md +++ b/initia_stdlib/doc/json.md @@ -5,12 +5,228 @@ +- [Struct `JSONValue`](#0x1_json_JSONValue) +- [Struct `JSONObject`](#0x1_json_JSONObject) +- [Struct `Element`](#0x1_json_Element) +- [Function `unmarshal_json_value`](#0x1_json_unmarshal_json_value) +- [Function `keys`](#0x1_json_keys) +- [Function `get_elem`](#0x1_json_get_elem) +- [Function `set_elem`](#0x1_json_set_elem) - [Function `marshal`](#0x1_json_marshal) - [Function `marshal_to_string`](#0x1_json_marshal_to_string) - [Function `unmarshal`](#0x1_json_unmarshal) -
use 0x1::string;
+
use 0x1::option;
+use 0x1::string;
+
+ + + + + +## Struct `JSONValue` + +JSONValue is a struct to hold any JSON value which is unknown at compile time. + + +
struct JSONValue has copy, drop
+
+ + + +##### Fields + + +
+
+value: vector<u8> +
+
+ +
+
+ + + + +## Struct `JSONObject` + +JSONObject is a struct to hold any json object which is unknown at compile time. + + +
struct JSONObject has copy, drop
+
+ + + +##### Fields + + +
+
+elems: vector<json::Element> +
+
+ +
+
+ + + + +## Struct `Element` + +Element is a struct to hold key-value pair in JSON object. + + +
struct Element has copy, drop
+
+ + + +##### Fields + + +
+
+key: vector<u8> +
+
+ +
+
+value: vector<u8> +
+
+ +
+
+ + + + +## Function `unmarshal_json_value` + +Unmarshal JSON value to the given type. + + +
public fun unmarshal_json_value<T: drop>(json_value: json::JSONValue): T
+
+ + + +##### Implementation + + +
public fun unmarshal_json_value<T: drop>(json_value: JSONValue): T {
+    unmarshal(json_value.value)
+}
+
+ + + + + +## Function `keys` + +Get the list of keys from the JSON object. + + +
public fun keys(obj: &json::JSONObject): vector<string::String>
+
+ + + +##### Implementation + + +
public fun keys(obj: &JSONObject): vector<String> {
+    vector::map_ref(
+        &obj.elems,
+        |elem| {
+            use_elem(elem);
+            string::utf8(elem.key)
+        }
+    )
+}
+
+ + + + + +## Function `get_elem` + +Get the value of the given key from the JSON object. + + +
public fun get_elem<T: drop>(obj: &json::JSONObject, key: string::String): option::Option<T>
+
+ + + +##### Implementation + + +
public fun get_elem<T: drop>(obj: &JSONObject, key: String): Option<T> {
+    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<T>(elem.value))
+}
+
+ + + + + +## Function `set_elem` + +Set or overwrite the element in the JSON object. + + +
public fun set_elem<T: drop>(obj: &mut json::JSONObject, key: string::String, value: &T)
+
+ + + +##### Implementation + + +
public fun set_elem<T: drop>(
+    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);
+    }
+}
 
diff --git a/initia_stdlib/doc/minitswap.md b/initia_stdlib/doc/minitswap.md index 3617bc6..5e42605 100644 --- a/initia_stdlib/doc/minitswap.md +++ b/initia_stdlib/doc/minitswap.md @@ -2205,11 +2205,7 @@ Event emitted when arb reverted offer_amount: u64 ): (u64, u64) acquires ModuleStore, VirtualPool { let (return_amount, fee_amount) = - safe_swap_simulation( - offer_metadata, - return_metadata, - offer_amount - ); + safe_swap_simulation(offer_metadata, return_metadata, offer_amount); assert!( return_amount != 0, error::invalid_state(EIBC_OP_INIT_PRICE_TOO_LOW) @@ -2276,11 +2272,7 @@ Event emitted when arb reverted ): (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) }
@@ -2377,10 +2369,7 @@ Event emitted when arb reverted 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 - ) + generate_unbond_key(account, *option::borrow(&start_after) + 1) } else { generate_unbond_key(account, 0) }; @@ -3247,15 +3236,9 @@ Event emitted when arb reverted let change_rate = if (new_pool_size > pool.pool_size) { - bigdecimal::from_ratio_u64( - new_pool_size - pool.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 - ) + bigdecimal::from_ratio_u64(pool.pool_size - new_pool_size, pool.pool_size) }; assert!( @@ -3286,8 +3269,7 @@ Event emitted when arb reverted ratio, pool.init_pool_amount ); pool.ibc_op_init_pool_amount = bigdecimal::mul_by_u64_truncate( - ratio, - pool.ibc_op_init_pool_amount + ratio, pool.ibc_op_init_pool_amount ); pool.pool_size = new_pool_size; @@ -3565,11 +3547,7 @@ Event emitted when arb reverted
public entry fun unbond(account: &signer, amount: u64) acquires ModuleStore {
     let share_token =
-        primary_fungible_store::withdraw(
-            account,
-            share_token_metadata(),
-            amount
-        );
+        primary_fungible_store::withdraw(account, share_token_metadata(), amount);
     unbond_internal(account, share_token);
 }
 
@@ -3657,11 +3635,7 @@ Event emitted when arb reverted min_return_amount: Option<u64> ) acquires ModuleStore, VirtualPool { let offer_asset = - primary_fungible_store::withdraw( - account, - offer_asset_metadata, - amount - ); + 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); @@ -3866,11 +3840,7 @@ Event emitted when arb reverted string::append(&mut symbol, ibc_denom); let coins: vector<FungibleAsset> = vector[ - coin::withdraw( - account, - init_metadata(), - init_amount - ), + coin::withdraw(account, init_metadata(), init_amount), coin::withdraw( account, ibc_op_init_metadata, @@ -4160,11 +4130,7 @@ Event emitted when arb reverted }; // check arb - check_arb( - module_store, - pool, - ibc_op_init_metadata - ); + check_arb(module_store, pool, ibc_op_init_metadata); event::emit<SwapEvent>( SwapEvent { @@ -4318,8 +4284,7 @@ Event emitted when arb reverted // take swap fee let swap_fee_amount = bigdecimal::mul_by_u64_ceil( - module_store.swap_fee_rate, - return_amount + module_store.swap_fee_rate, return_amount ); // take arb fee @@ -4328,10 +4293,7 @@ Event emitted when arb reverted 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 - ); + 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) @@ -4346,8 +4308,7 @@ Event emitted when arb reverted ); let fee_amount = bigdecimal::mul_by_u64_ceil( - module_store.swap_fee_rate, - return_amount + module_store.swap_fee_rate, return_amount ); (return_amount, fee_amount) @@ -4413,7 +4374,9 @@ Event emitted when arb reverted bigdecimal::truncate_u64( bigdecimal::div( bigdecimal::from_u64(return_amount), - bigdecimal::sub(bigdecimal::one(), module_store.swap_fee_rate) + bigdecimal::sub( + bigdecimal::one(), module_store.swap_fee_rate + ) ) ); if (ibc_op_init_pool_amount - return_amount_before_swap_fee < pool_size) { @@ -4437,10 +4400,7 @@ Event emitted when arb reverted return_amount - offer_amount } else { 0 }; let arb_fee_amount = - bigdecimal::mul_by_u64_ceil( - 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 let actual_return_amount = return_amount - arb_fee_amount; @@ -4475,8 +4435,7 @@ Event emitted when arb reverted 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 + module_store.arb_fee_rate, arb_profit ); actual_return_amount = return_amount_before_swap_fee - swap_fee_amount - arb_fee_amount; @@ -4493,7 +4452,9 @@ Event emitted when arb reverted bigdecimal::truncate_u64( bigdecimal::div( bigdecimal::from_u64(return_amount), - bigdecimal::sub(bigdecimal::one(), module_store.swap_fee_rate) + bigdecimal::sub( + bigdecimal::one(), module_store.swap_fee_rate + ) ) ); let fee_amount = return_amount_ - return_amount; diff --git a/initia_stdlib/doc/multisig.md b/initia_stdlib/doc/multisig.md index 0a881a7..e035a82 100644 --- a/initia_stdlib/doc/multisig.md +++ b/initia_stdlib/doc/multisig.md @@ -992,10 +992,7 @@ Vote proposal assert_member(&multisig_wallet.members, &voter); assert!( - table::contains( - &multisig_wallet.proposals, - proposal_id - ), + table::contains(&multisig_wallet.proposals, proposal_id), error::invalid_argument(EPROPOSAL_NOT_FOUND) ); let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id); @@ -1036,10 +1033,7 @@ Execute proposal assert_member(&multisig_wallet.members, &executor); assert!( - table::contains( - &multisig_wallet.proposals, - proposal_id - ), + table::contains(&multisig_wallet.proposals, proposal_id), error::invalid_argument(EPROPOSAL_NOT_FOUND) ); let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id); @@ -1049,10 +1043,8 @@ Execute proposal // check passed assert!( - yes_vote_count( - &proposal.votes, - &multisig_wallet.members - ) >= multisig_wallet.threshold, + yes_vote_count(&proposal.votes, &multisig_wallet.members) + >= multisig_wallet.threshold, error::invalid_state(ENOT_PASS) ); diff --git a/initia_stdlib/doc/nft.md b/initia_stdlib/doc/nft.md index 0216b6b..58b733f 100644 --- a/initia_stdlib/doc/nft.md +++ b/initia_stdlib/doc/nft.md @@ -328,6 +328,16 @@ The provided signer is not the creator + + +The calling signer is not the owner + + +
const ENOT_OWNER: u64 = 10;
+
+ + + The query length is over the maximum length @@ -364,7 +374,7 @@ Creates a new nft object from a nft name and returns the ConstructorRef for additional specialization. -
public fun create(creator: &signer, collection_name: string::String, description: string::String, token_id: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
+
public fun create(owner: &signer, collection: object::Object<collection::Collection>, description: string::String, token_id: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
 
@@ -373,21 +383,24 @@ additional specialization.
public fun create(
-    creator: &signer,
-    collection_name: String,
+    owner: &signer,
+    collection: Object<Collection>,
     description: String,
     token_id: String,
     royalty: Option<Royalty>,
     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,
diff --git a/initia_stdlib/doc/object.md b/initia_stdlib/doc/object.md
index 94710a9..438abc3 100644
--- a/initia_stdlib/doc/object.md
+++ b/initia_stdlib/doc/object.md
@@ -43,6 +43,7 @@ make it so that a reference to a global object can be returned from a function.
 -  [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_nft_object`](#0x1_object_create_nft_object)
 -  [Function `create_user_derived_object`](#0x1_object_create_user_derived_object)
 -  [Function `create_object`](#0x1_object_create_object)
 -  [Function `generate_delete_ref`](#0x1_object_generate_delete_ref)
@@ -858,6 +859,33 @@ Named objects can be queried globally by knowing the user generated seed used to
 
 
 
+
+
+## Function `create_nft_object`
+
+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<u8>): object::ConstructorRef
+
+ + + +##### Implementation + + +
public(friend) fun create_nft_object(
+    owner: address, creator: address, seed: vector<u8>
+): ConstructorRef acquires Tombstone {
+    let obj_addr = create_object_address(&creator, seed);
+    create_object_internal(owner, obj_addr, true)
+}
+
+ + + ## Function `create_user_derived_object` @@ -879,11 +907,7 @@ Derivde objects, similar to named objects, cannot be deleted. ): 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 - ) + create_object_internal(creator_address, obj_addr, can_delete) }
@@ -909,11 +933,7 @@ The unique address is computed sha3_256([transaction hash | auid counter | 0xFB] 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 - ) + create_object_internal(owner_address, unique_address, can_delete) }
diff --git a/initia_stdlib/doc/primary_fungible_store.md b/initia_stdlib/doc/primary_fungible_store.md index a28e034..dfbbd8a 100644 --- a/initia_stdlib/doc/primary_fungible_store.md +++ b/initia_stdlib/doc/primary_fungible_store.md @@ -274,10 +274,7 @@ Create a primary store object to hold fungible asset for the given address. // 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 - )) { + if (!table::contains(&module_store.user_stores, owner_addr)) { table::add( &mut module_store.user_stores, owner_addr, @@ -285,13 +282,11 @@ Create a primary store object to hold fungible asset for the given address. ); }; - 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 ); + + table::add(user_stores, metadata_addr, store_addr); }; // emit store created event @@ -476,12 +471,7 @@ Get the balances of account's ): (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 - ); + let iter = table::iter(account_stores, option::none(), start_after, 2); let metadata_vec: vector<Object<Metadata>> = vector[]; let balance_vec: vector<u64> = vector[]; @@ -564,12 +554,7 @@ This function is only callable by the chain. 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 - ); + fungible_asset::sudo_transfer(sender, sender_store, recipient_store, amount); }
@@ -820,11 +805,7 @@ Withdraw from the primary store of owner ignoring frozen flag. owner, fungible_asset::transfer_ref_metadata(transfer_ref) ); - fungible_asset::withdraw_with_ref( - transfer_ref, - from_primary_store, - amount - ) + fungible_asset::withdraw_with_ref(transfer_ref, from_primary_store, amount) } diff --git a/initia_stdlib/doc/secp256k1.md b/initia_stdlib/doc/secp256k1.md index d66c72a..c7c678c 100644 --- a/initia_stdlib/doc/secp256k1.md +++ b/initia_stdlib/doc/secp256k1.md @@ -17,6 +17,7 @@ This module implements ECDSA signatures based on the prime-order secp256k1 ellpt - [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 `verify`](#0x1_secp256k1_verify) - [Function `ecdsa_recover`](#0x1_secp256k1_ecdsa_recover) - [Function `ecdsa_recover_compressed`](#0x1_secp256k1_ecdsa_recover_compressed) @@ -326,6 +327,37 @@ Serializes an ECDSASignature struct to 64-bytes. + + +## Function `verify` + +Returns true if the signature can verify the public key on the message + + +
public fun verify(message: vector<u8>, public_key: &secp256k1::ECDSACompressedPublicKey, signature: &secp256k1::ECDSASignature): bool
+
+ + + +##### Implementation + + +
public fun verify(
+    message: vector<u8>,
+    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)
+}
+
+ + + ## Function `ecdsa_recover` @@ -355,12 +387,7 @@ public key (or its hash) is known beforehand. ); let (pk, success) = - recover_public_key_internal( - recovery_id, - message, - signature.bytes, - false - ); + recover_public_key_internal(recovery_id, message, signature.bytes, false); if (success) { std::option::some(ecdsa_raw_public_key_from_bytes(pk)) } else { @@ -400,12 +427,7 @@ public key (or its hash) is known beforehand. ); let (pk, success) = - recover_public_key_internal( - recovery_id, - message, - signature.bytes, - true - ); + recover_public_key_internal(recovery_id, message, signature.bytes, true); if (success) { std::option::some(ecdsa_compressed_public_key_from_bytes(pk)) } else { diff --git a/initia_stdlib/doc/simple_map.md b/initia_stdlib/doc/simple_map.md index d3a714b..f1158b9 100644 --- a/initia_stdlib/doc/simple_map.md +++ b/initia_stdlib/doc/simple_map.md @@ -332,7 +332,9 @@ Add a key/value pair to the map. The key must not already exist. value: Value ) { let maybe_idx = find(self, &key); - assert!(option::is_none(&maybe_idx), error::invalid_argument(EKEY_ALREADY_EXISTS)); + assert!( + option::is_none(&maybe_idx), error::invalid_argument(EKEY_ALREADY_EXISTS) + ); vector::push_back(&mut self.data, Element { key, value }); } diff --git a/initia_stdlib/doc/simple_nft.md b/initia_stdlib/doc/simple_nft.md index 418409e..c611f72 100644 --- a/initia_stdlib/doc/simple_nft.md +++ b/initia_stdlib/doc/simple_nft.md @@ -293,11 +293,7 @@ With an existing collection, directly mint a viable nft into the creators accoun 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)); } } @@ -625,11 +621,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); - property_map::update_typed( - &simple_nft.property_mutator_ref, - &key, - value - ); + property_map::update_typed(&simple_nft.property_mutator_ref, &key, value); } diff --git a/initia_stdlib/doc/stableswap.md b/initia_stdlib/doc/stableswap.md index e26a065..1a99cf3 100644 --- a/initia_stdlib/doc/stableswap.md +++ b/initia_stdlib/doc/stableswap.md @@ -843,11 +843,7 @@ Return swap simulation result pool_obj: Object<Pool>, coin_amounts: vector<u64> ): u64 acquires Pool { let (liquidity_amount, _) = - imbalance_withdraw_simulation( - pool_obj, - coin_amounts, - option::none() - ); + imbalance_withdraw_simulation(pool_obj, coin_amounts, option::none()); liquidity_amount } @@ -883,11 +879,7 @@ Return swap simulation result assert!(found, error::invalid_argument(ECOIN_TYPE)); let (liquidity_amount, _) = - single_asset_withdraw_simulation( - pool_obj, - liquidity_amount, - return_index - ); + single_asset_withdraw_simulation(pool_obj, liquidity_amount, return_index); liquidity_amount } @@ -1106,12 +1098,7 @@ Return swap simulation result }; let liquidity_token = create_pool( - creator, - name, - symbol, - swap_fee_rate, - coins, - ann + creator, name, symbol, swap_fee_rate, coins, ann ); primary_fungible_store::deposit(signer::address_of(creator), liquidity_token); } @@ -1291,11 +1278,7 @@ Return swap simulation result max_liquidity: Option<u64> ) acquires Pool { let (liquidity_amount, fee_amounts) = - imbalance_withdraw_simulation( - pool_obj, - coin_amounts, - max_liquidity - ); + 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); @@ -1386,11 +1369,7 @@ Return swap simulation result min_return_amount: Option<u64> ) acquires Pool { let offer_coin = - primary_fungible_store::withdraw( - account, - offer_coin_metadata, - offer_amount - ); + primary_fungible_store::withdraw(account, offer_coin_metadata, offer_amount); let return_coin = swap( pool_obj, @@ -1501,11 +1480,7 @@ Return swap simulation result let module_store = borrow_global_mut<ModuleStore>(@initia_std); module_store.pool_count = module_store.pool_count + 1; - table::add( - &mut module_store.pools, - pool_address, - true - ); + table::add(&mut module_store.pools, pool_address, true); // emit create pool event event::emit<CreatePoolEvent>( @@ -1642,9 +1617,7 @@ Return swap simulation result vector::push_back( &mut return_coins, primary_fungible_store::withdraw( - &pool_signer, - coin_metadata, - return_amount + &pool_signer, coin_metadata, return_amount ) ); i = i + 1; @@ -1711,11 +1684,7 @@ Return swap simulation result // calculate amount of returning asset let (return_amount, fee) = - single_asset_withdraw_simulation( - pool_obj, - liquidity_amount, - return_index - ); + single_asset_withdraw_simulation(pool_obj, liquidity_amount, return_index); assert!( option::is_none(&min_return_amount) || *option::borrow(&min_return_amount) <= return_amount, @@ -1898,12 +1867,7 @@ Return swap simulation result ) as u64 ); - let y_without_fee = get_y_with_given_d( - pool_amounts, - return_index, - ann, - d_after - ); + 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; @@ -2148,11 +2112,11 @@ Return swap simulation result 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 pool_amount_after = vector::borrow_mut( + &mut pool_amounts_after, i + ); let ideal_balance = mul_div_u64( - d_ideal, - pool_amount_before, - d_before + d_ideal, pool_amount_before, d_before ); let diff = if (ideal_balance > *pool_amount_after) { diff --git a/initia_stdlib/doc/staking.md b/initia_stdlib/doc/staking.md index fbfc515..5fd39b6 100644 --- a/initia_stdlib/doc/staking.md +++ b/initia_stdlib/doc/staking.md @@ -1010,12 +1010,7 @@ Get all delegation info of an addr let delegation_store = borrow_global<DelegationStore>(addr); let delegations = table::borrow(&delegation_store.delegations, metadata); - let delegations_iter = table::iter( - delegations, - option::none(), - start_after, - 2 - ); + let delegations_iter = table::iter(delegations, option::none(), start_after, 2); let prepare = table::prepare(delegations_iter); let res: vector<DelegationResponse> = vector[]; @@ -1143,12 +1138,7 @@ Get all unbondings of (addr, validator) option::none() }; - let unbondings_iter = table::iter( - unbondings, - option::none(), - start_after, - 2 - ); + let unbondings_iter = table::iter(unbondings, option::none(), start_after, 2); let res: vector<UnbondingResponse> = vector[]; while (vector::length(&res) < (limit as u64) @@ -1387,10 +1377,7 @@ Initialize, Make staking store let module_store = borrow_global_mut<ModuleStore>(@initia_std); assert!( - !table::contains( - &module_store.staking_states, - metadata - ), + !table::contains(&module_store.staking_states, metadata), error::already_exists(ESTAKING_STATE_ALREADY_EXISTS) ); table::add( @@ -1439,9 +1426,7 @@ Slash unbonding coin if (slash_amount > 0) { let unbonding_coin_store_signer = - &object::generate_signer_for_extending( - &state.unbonding_coin_store_ref - ); + &object::generate_signer_for_extending(&state.unbonding_coin_store_ref); let slash_coin = fungible_asset::withdraw( unbonding_coin_store_signer, @@ -1455,11 +1440,7 @@ Slash unbonding 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); } } @@ -1514,7 +1495,9 @@ Deposit unbonding coin to global store if (total_unbonding_amount == 0) { bigdecimal::one() } else { - bigdecimal::div_by_u64(state.unbonding_share, total_unbonding_amount) + bigdecimal::div_by_u64( + state.unbonding_share, total_unbonding_amount + ) }; let share_diff = @@ -1524,10 +1507,7 @@ Deposit unbonding coin to global store 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; } @@ -1585,7 +1565,9 @@ Deposit staking reward, and update reward_index ); state.reward_index = bigdecimal::add( state.reward_index, - bigdecimal::rev(bigdecimal::div_by_u64(state.total_share, reward_amount)) + bigdecimal::rev( + bigdecimal::div_by_u64(state.total_share, reward_amount) + ) ); fungible_asset::deposit(state.reward_coin_store, reward); @@ -1717,10 +1699,7 @@ Delegate a fa to a validator. let metadata = fungible_asset::asset_metadata(&fa); assert!( - table::contains( - &module_store.staking_states, - metadata - ), + 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); @@ -1733,16 +1712,14 @@ Delegate a fa to a validator. 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() + 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 + unbonding_coin_store_address, metadata ); table::add( @@ -1825,11 +1802,7 @@ unbonding amount can be slightly different with input amount due to round error. 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); @@ -1869,11 +1842,7 @@ unbonding amount can be slightly different with input amount due to round error. let metadata = delegation.metadata; let (unbonding_amount, release_time) = - undelegate_internal( - *string::bytes(&validator), - &metadata, - &share - ); + undelegate_internal(*string::bytes(&validator), &metadata, &share); let reward = destroy_delegation_and_extract_reward(delegation); let module_store = borrow_global_mut<ModuleStore>(@initia_std); @@ -1891,11 +1860,7 @@ unbonding amount can be slightly different with input amount due to round error. state.total_share = bigdecimal::sub(state.total_share, share); let unbonding_share = - unbonding_share_from_amount( - metadata, - validator, - unbonding_amount - ); + unbonding_share_from_amount(metadata, validator, unbonding_amount); let unbonding = Unbonding { metadata, validator, unbonding_share, release_time }; (reward, unbonding) @@ -2214,10 +2179,7 @@ Deposit the delegation into recipient's account. table::add( delegations, validator, - empty_delegation( - delegation.metadata, - delegation.validator - ) + empty_delegation(delegation.metadata, delegation.validator) ); }; @@ -2286,10 +2248,7 @@ Withdraw specified share from delegation. // If withdraw all, remove delegation if (delegation.share == share) { let delegations = - table::borrow_mut( - &mut delegation_store.delegations, - metadata - ); + table::borrow_mut(&mut delegation_store.delegations, metadata); table::remove(delegations, validator) // Else extract } else { @@ -2665,8 +2624,7 @@ Withdraw specifed amount of unbonding_amount from the unbonding. if (unbonding.unbonding_share == share) { // If withdraw all, remove unbonding let unbondings = table::borrow_mut( - &mut delegation_store.unbondings, - metadata + &mut delegation_store.unbondings, metadata ); table::remove( diff --git a/initia_stdlib/sources/account.move b/initia_stdlib/sources/account.move index 17c040f..f5f0e39 100644 --- a/initia_stdlib/sources/account.move +++ b/initia_stdlib/sources/account.move @@ -50,11 +50,7 @@ module initia_std::account { error::already_exists(EACCOUNT_ALREADY_EXISTS) ); - request_create_account( - addr, - account_number, - ACCOUNT_TYPE_TABLE - ) + request_create_account(addr, account_number, ACCOUNT_TYPE_TABLE) } /// ObjectAccount is similar to CosmosSDK's ModuleAccount in concept, @@ -64,11 +60,7 @@ module initia_std::account { // 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 - ) + 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, @@ -316,13 +308,7 @@ module initia_std::account { assert!(exists_at(new_address), 2); // set base account with 0 sequence - set_account_info( - new_address2, - 100, - 0, - ACCOUNT_TYPE_BASE, - false - ); + set_account_info(new_address2, 100, 0, ACCOUNT_TYPE_BASE, false); let table_account_num = create_table_account(new_address2); assert!( table_account_num == get_account_number(new_address2), @@ -342,13 +328,7 @@ module initia_std::account { assert!(exists_at(new_address3), 5); // set base account with 0 sequence - set_account_info( - new_address4, - 200, - 0, - ACCOUNT_TYPE_BASE, - false - ); + set_account_info(new_address4, 200, 0, ACCOUNT_TYPE_BASE, false); let object_account_num = create_object_account(new_address4); assert!( object_account_num == get_account_number(new_address4), @@ -364,22 +344,10 @@ module initia_std::account { public fun test_blocked_address( new_address: address, new_address2: address ) { - set_account_info( - new_address, - 200, - 0, - ACCOUNT_TYPE_BASE, - true - ); + set_account_info(new_address, 200, 0, ACCOUNT_TYPE_BASE, true); assert!(is_blocked(new_address), 1); - set_account_info( - new_address2, - 100, - 0, - ACCOUNT_TYPE_BASE, - false - ); + set_account_info(new_address2, 100, 0, ACCOUNT_TYPE_BASE, false); assert!(!is_blocked(new_address2), 2); } @@ -412,6 +380,7 @@ module initia_std::account { #[test_only] public fun create_account_for_test(new_address: address): signer { + create_account(new_address); create_signer_for_test(new_address) } } diff --git a/initia_stdlib/sources/any.move b/initia_stdlib/sources/any.move index 43669bf..c5dc3f2 100644 --- a/initia_stdlib/sources/any.move +++ b/initia_stdlib/sources/any.move @@ -55,6 +55,9 @@ module initia_std::any { #[test] fun test_any() { assert!(unpack(pack(22)) == 22, 1); - assert!(unpack(pack(S { x: 22 })) == S { x: 22 }, 2); + assert!( + unpack(pack(S { x: 22 })) == S { x: 22 }, + 2 + ); } } diff --git a/initia_stdlib/sources/bigdecimal.move b/initia_stdlib/sources/bigdecimal.move index eac9d72..52fd5b2 100644 --- a/initia_stdlib/sources/bigdecimal.move +++ b/initia_stdlib/sources/bigdecimal.move @@ -77,7 +77,8 @@ module initia_std::bigdecimal { public fun from_ratio(numerator: BigUint, denominator: BigUint): BigDecimal { assert!( - !biguint::is_zero(denominator), error::invalid_argument(EDIVISION_BY_ZERO) + !biguint::is_zero(denominator), + error::invalid_argument(EDIVISION_BY_ZERO) ); let numerator = biguint::mul(numerator, f()); @@ -259,7 +260,8 @@ module initia_std::bigdecimal { public fun div(num1: BigDecimal, num2: BigDecimal): BigDecimal { assert!( - !biguint::is_zero(num2.scaled), error::invalid_argument(EDIVISION_BY_ZERO) + !biguint::is_zero(num2.scaled), + error::invalid_argument(EDIVISION_BY_ZERO) ); BigDecimal { @@ -349,7 +351,10 @@ module initia_std::bigdecimal { let num4 = add(num1, num3); assert!( - eq(num4, from_ratio(biguint::from_u64(5), biguint::from_u64(6))), + eq( + num4, + from_ratio(biguint::from_u64(5), biguint::from_u64(6)) + ), 4 ); @@ -370,13 +375,19 @@ module initia_std::bigdecimal { let num10 = add_by_u64(num1, 1); assert!( - eq(num10, from_ratio(biguint::from_u64(3), biguint::from_u64(2))), + 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))), + eq( + num11, + from_ratio(biguint::from_u64(1), biguint::from_u64(2)) + ), 11 ); @@ -385,7 +396,10 @@ module initia_std::bigdecimal { let num13 = div_by_u64(num1, 2); assert!( - eq(num13, from_ratio(biguint::from_u64(1), biguint::from_u64(4))), + eq( + num13, + from_ratio(biguint::from_u64(1), biguint::from_u64(4)) + ), 13 ); } diff --git a/initia_stdlib/sources/biguint.move b/initia_stdlib/sources/biguint.move index 50a2bf6..5f9dc42 100644 --- a/initia_stdlib/sources/biguint.move +++ b/initia_stdlib/sources/biguint.move @@ -213,20 +213,35 @@ module initia_std::biguint { let num1 = from_u128(18446744073709551615u128 * 2u128); let num2 = from_u128(18446744073709551615u128 * 2u128); let num3 = add(num1, num2); - assert!(to_u128(num3) == 18446744073709551615u128 * 4u128, 1); + 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); + 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); + assert!( + to_u128(num7) == 18446744073709551615u128 * 2u128 + 1u128, + 4 + ); let num8 = sub_by_u128(num1, 1); - assert!(to_u128(num8) == 18446744073709551615u128 * 2u128 - 1u128, 5); + assert!( + to_u128(num8) == 18446744073709551615u128 * 2u128 - 1u128, + 5 + ); let num9 = mul_by_u128(num1, 2); - assert!(to_u128(num9) == 18446744073709551615u128 * 4u128, 6); + assert!( + to_u128(num9) == 18446744073709551615u128 * 4u128, + 6 + ); let num10 = div_by_u128(num1, 2); assert!(to_u128(num10) == 18446744073709551615u128, 7); } @@ -236,11 +251,17 @@ module initia_std::biguint { let num1 = from_u256(340282366920938463463374607431768211455u256 * 2u256); let num2 = from_u256(340282366920938463463374607431768211455u256 * 2u256); let num3 = add(num1, num2); - assert!(to_u256(num3) == 340282366920938463463374607431768211455u256 * 4u256, 1); + 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); + assert!( + to_u256(num5) == 340282366920938463463374607431768211455u256 * 4u256, + 2 + ); let num6 = div(num1, from_u256(2)); assert!(to_u256(num6) == 340282366920938463463374607431768211455u256, 3); @@ -257,7 +278,10 @@ module initia_std::biguint { 5 ); let num9 = mul_by_u256(num1, 2); - assert!(to_u256(num9) == 340282366920938463463374607431768211455u256 * 4u256, 6); + assert!( + to_u256(num9) == 340282366920938463463374607431768211455u256 * 4u256, + 6 + ); let num10 = div_by_u256(num1, 2); assert!(to_u256(num10) == 340282366920938463463374607431768211455u256, 7); } diff --git a/initia_stdlib/sources/code.move b/initia_stdlib/sources/code.move index 57127a0..312f501 100644 --- a/initia_stdlib/sources/code.move +++ b/initia_stdlib/sources/code.move @@ -115,6 +115,20 @@ module initia_std::code { ) } + fun assert_no_duplication(module_ids: &vector) { + let module_ids_set = simple_map::create(); + 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); + } + ); + } + public entry fun init_genesis( chain: &signer, module_ids: vector, allowed_publishers: vector
) acquires ModuleStore { @@ -122,6 +136,7 @@ module initia_std::code { signer::address_of(chain) == @initia_std, error::permission_denied(EINVALID_CHAIN_OPERATOR) ); + assert_no_duplication(&module_ids); let metadata_table = table::new(); vector::for_each_ref( @@ -172,7 +187,10 @@ module initia_std::code { let registry = borrow_global_mut(code_object_addr); let iter = table::iter_mut( - &mut registry.metadata, option::none(), option::none(), 1 + &mut registry.metadata, + option::none(), + option::none(), + 1 ); loop { if (!table::prepare_mut(iter)) { break }; @@ -195,23 +213,7 @@ module initia_std::code { vector::length(&code) == vector::length(&module_ids), error::invalid_argument(EINVALID_ARGUMENTS) ); - - // duplication check - let module_ids_set = simple_map::create(); - 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 - ); - } - ); + assert_no_duplication(&module_ids); // Check whether arbitrary publish is allowed or not. let module_store = borrow_global_mut(@initia_std); @@ -225,13 +227,11 @@ module initia_std::code { assert_allowed(&module_store.allowed_publishers, addr); if (!exists(addr)) { - move_to( - owner, - MetadataStore { metadata: table::new() } - ); + move_to(owner, MetadataStore { metadata: table::new() }); }; // Check upgradability + let new_modules = 0; let metadata_table = &mut borrow_global_mut(addr).metadata; vector::for_each_ref( &module_ids, @@ -247,8 +247,7 @@ module initia_std::code { ); assert!( can_change_upgrade_policy_to( - metadata.upgrade_policy, - upgrade_policy + metadata.upgrade_policy, upgrade_policy ), error::invalid_argument(EUPGRADE_WEAKER_POLICY) ); @@ -260,6 +259,7 @@ module initia_std::code { *module_id, ModuleMetadata { upgrade_policy } ); + new_modules = new_modules + 1; }; event::emit( @@ -268,8 +268,11 @@ module initia_std::code { } ); + if (new_modules > 0) { + increase_total_modules(new_modules) + }; + // Request publish - increase_total_modules(vector::length(&module_ids)); request_publish(addr, module_ids, code) } diff --git a/initia_stdlib/sources/coin.move b/initia_stdlib/sources/coin.move index 62ba20e..126778a 100644 --- a/initia_stdlib/sources/coin.move +++ b/initia_stdlib/sources/coin.move @@ -121,10 +121,7 @@ module initia_std::coin { ): (MintCapability, BurnCapability, FreezeCapability, ExtendRef) { // create object for fungible asset metadata let constructor_ref = - &object::create_named_object( - creator, - *string::bytes(&symbol) - ); + &object::create_named_object(creator, *string::bytes(&symbol)); primary_fungible_store::create_primary_store_enabled_fungible_asset( constructor_ref, @@ -238,11 +235,7 @@ module initia_std::coin { ); let refs = borrow_global(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) } /// Unfreeze the primary store of an account. @@ -258,11 +251,7 @@ module initia_std::coin { ); let refs = borrow_global(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) } // @@ -341,6 +330,12 @@ module initia_std::coin { public fun metadata_to_denom(metadata: Object): String { let metadata_addr = object::object_address(&metadata); let symbol = symbol(metadata); + + // we need to revert the conversion in fungible_asset::metadata() + if (object::is_owner(metadata, @initia_std) && symbol == string::utf8(b"INIT")) { + symbol = string::utf8(b"uinit") + }; + let std_metadata_addr = metadata_address(@initia_std, symbol); if (std_metadata_addr == metadata_addr) { diff --git a/initia_stdlib/sources/copyable_any.move b/initia_stdlib/sources/copyable_any.move index 68bdc8c..c7b4367 100644 --- a/initia_stdlib/sources/copyable_any.move +++ b/initia_stdlib/sources/copyable_any.move @@ -45,6 +45,9 @@ module initia_std::copyable_any { #[test] fun test_any() { assert!(unpack(pack(22)) == 22, 1); - assert!(unpack(pack(S { x: 22 })) == S { x: 22 }, 2); + assert!( + unpack(pack(S { x: 22 })) == S { x: 22 }, + 2 + ); } } diff --git a/initia_stdlib/sources/cosmos.move b/initia_stdlib/sources/cosmos.move index 35e3dcc..8490922 100644 --- a/initia_stdlib/sources/cosmos.move +++ b/initia_stdlib/sources/cosmos.move @@ -7,9 +7,14 @@ module initia_std::cosmos { use std::object::Object; use std::fungible_asset::Metadata; use std::collection::{Collection}; + use std::error; use initia_std::json; + // Error codes + const EINVALID_CALLBACK_ID: u64 = 1; + const EINVALID_CALLBACK_FID: u64 = 2; + struct VoteRequest has copy, drop { _type_: String, proposal_id: u64, @@ -40,7 +45,27 @@ module initia_std::cosmos { } public entry fun stargate(sender: &signer, data: vector) { - stargate_internal(signer::address_of(sender), data) + stargate_internal(signer::address_of(sender), data, disallow_failure()) + } + + /// Stargate message with options + /// + /// Options: + /// - allow_failure() + /// - disallow_failure() + /// - allow_failure_with_callback(id: u64, fid: String) + /// - disallow_failure_with_callback(id: u64, fid: String) + /// + /// The callback function should be defined with the following signature: + /// ```rust + /// public fun callback(id: u64, success: bool); + /// public fun callback(sender: &signer, id: u64, success: bool); + /// ``` + /// + public fun stargate_with_options( + sender: &signer, data: vector, options: Options + ) { + stargate_internal(signer::address_of(sender), data, options) } public entry fun move_execute( @@ -128,11 +153,7 @@ module initia_std::cosmos { public entry fun fund_community_pool( sender: &signer, metadata: Object, amount: u64 ) { - fund_community_pool_internal( - signer::address_of(sender), - &metadata, - amount - ) + fund_community_pool_internal(signer::address_of(sender), &metadata, amount) } /// ICS20 ibc transfer @@ -217,7 +238,9 @@ module initia_std::cosmos { ) } - native fun stargate_internal(sender: address, data: vector); + native fun stargate_internal( + sender: address, data: vector, option: Options + ); native fun move_execute_internal( sender: address, @@ -285,4 +308,70 @@ module initia_std::cosmos { timeout_fee_metadata: &Object, timeout_fee_amount: u64 ); + + // ================================================== Options ================================================= + + /// Options for stargate message + struct Options has copy, drop { + allow_failure: bool, + + /// callback_id is the unique identifier for this message execution. + callback_id: u64, + /// function identifier which will be called after the message execution. + /// The function should be defined with the following signature: + /// ```rust + /// public fun callback(id: u64, success: bool); + /// public fun callback(sender: &signer, id: u64, success: bool); + /// ``` + /// + /// Ex) 0xaddr::test_module::callback + /// where callback is the function name defined in the test_module of the 0xaddr address. + callback_fid: vector + } + + public fun allow_failure(): Options { + Options { + allow_failure: true, + callback_id: 0, + callback_fid: vector::empty() + } + } + + public fun disallow_failure(): Options { + Options { + allow_failure: false, + callback_id: 0, + callback_fid: vector::empty() + } + } + + /// Ex) fid: 0xaddr::test_module::callback + /// where callback is the function name defined in the test_module of the 0xaddr address. + public fun allow_failure_with_callback(id: u64, fid: String): Options { + assert!(id > 0, error::invalid_argument(EINVALID_CALLBACK_ID)); + assert!( + !string::is_empty(&fid), error::invalid_argument(EINVALID_CALLBACK_FID) + ); + + Options { + allow_failure: true, + callback_id: id, + callback_fid: *string::bytes(&fid) + } + } + + /// Ex) fid: 0xaddr::test_module::callback + /// where callback is the function name defined in the test_module of the 0xaddr address. + public fun disallow_failure_with_callback(id: u64, fid: String): Options { + assert!(id > 0, error::invalid_argument(EINVALID_CALLBACK_ID)); + assert!( + !string::is_empty(&fid), error::invalid_argument(EINVALID_CALLBACK_FID) + ); + + Options { + allow_failure: false, + callback_id: id, + callback_fid: *string::bytes(&fid) + } + } } diff --git a/initia_stdlib/sources/crypto/ed25519.move b/initia_stdlib/sources/crypto/ed25519.move index b73d75f..2143079 100644 --- a/initia_stdlib/sources/crypto/ed25519.move +++ b/initia_stdlib/sources/crypto/ed25519.move @@ -72,11 +72,7 @@ module initia_std::ed25519 { public fun verify( message: vector, public_key: &PublicKey, signature: &Signature ): bool { - verify_internal( - message, - public_key.bytes, - signature.bytes - ) + verify_internal(message, public_key.bytes, signature.bytes) } /// Performs batch Ed25519 signature verification. diff --git a/initia_stdlib/sources/crypto/secp256k1.move b/initia_stdlib/sources/crypto/secp256k1.move index 3ac1333..afe4c4f 100644 --- a/initia_stdlib/sources/crypto/secp256k1.move +++ b/initia_stdlib/sources/crypto/secp256k1.move @@ -102,11 +102,7 @@ module initia_std::secp256k1 { std::error::invalid_argument(E_DESERIALIZE) ); - return verify_internal( - message, - public_key.bytes, - signature.bytes - ) + 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 @@ -124,12 +120,7 @@ module initia_std::secp256k1 { ); let (pk, success) = - recover_public_key_internal( - recovery_id, - message, - signature.bytes, - false - ); + recover_public_key_internal(recovery_id, message, signature.bytes, false); if (success) { std::option::some(ecdsa_raw_public_key_from_bytes(pk)) } else { @@ -152,12 +143,7 @@ module initia_std::secp256k1 { ); let (pk, success) = - recover_public_key_internal( - recovery_id, - message, - signature.bytes, - true - ); + recover_public_key_internal(recovery_id, message, signature.bytes, true); if (success) { std::option::some(ecdsa_compressed_public_key_from_bytes(pk)) } else { @@ -171,14 +157,12 @@ module initia_std::secp256k1 { /// 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 + message: vector, public_key: vector, signature: vector ): bool; /// Returns `(public_key, true)` if `signature` verifies on `message` under the recovered `public_key` diff --git a/initia_stdlib/sources/debug.move b/initia_stdlib/sources/debug.move index d829fdf..56d1e7a 100644 --- a/initia_stdlib/sources/debug.move +++ b/initia_stdlib/sources/debug.move @@ -258,16 +258,10 @@ module initia_std::debug { assert_equal(&v_u64, b"[\n [ 64, 65 ],\n [ 66, 67 ]\n]"); let v_u128 = vector[vector[128u128, 129u128], vector[130u128, 131u128]]; - assert_equal( - &v_u128, - b"[\n [ 128, 129 ],\n [ 130, 131 ]\n]" - ); + assert_equal(&v_u128, 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]" - ); + assert_equal(&v_u256, b"[\n [ 256, 257 ],\n [ 258, 259 ]\n]"); let v_bool = vector[vector[true, false], vector[false, true]]; assert_equal( diff --git a/initia_stdlib/sources/dex.move b/initia_stdlib/sources/dex.move index 2910bed..d116976 100644 --- a/initia_stdlib/sources/dex.move +++ b/initia_stdlib/sources/dex.move @@ -370,9 +370,7 @@ module initia_std::dex { #[view] public fun get_provide_simulation( - pair: Object, - coin_a_amount_in: u64, - coin_b_amount_in: u64 + 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); @@ -477,7 +475,9 @@ 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 { @@ -738,16 +738,8 @@ module initia_std::dex { 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( @@ -803,16 +795,8 @@ module initia_std::dex { } }; - 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( @@ -985,18 +969,12 @@ module initia_std::dex { offer_coin_amount: u64, min_return: Option ) 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 - ), + || *option::borrow(&min_return) <= fungible_asset::amount(&return_coin), error::invalid_state(EMIN_RETURN) ); @@ -1196,18 +1174,10 @@ module initia_std::dex { 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 - ) + 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 - ) + fungible_asset::withdraw(pair_signer, pool.coin_a_store, return_amount) }; // emit events @@ -1299,10 +1269,7 @@ module initia_std::dex { 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 } - ); + move_to(pair_signer, Pool { coin_a_store, coin_b_store }); move_to( pair_signer, @@ -1400,10 +1367,7 @@ module initia_std::dex { let liquidity = calculate_provide_liquidity_return_amount( - pool, - pair, - coin_a_amount_in, - coin_b_amount_in + pool, pair, coin_a_amount_in, coin_b_amount_in ); assert!( @@ -1598,17 +1562,11 @@ module initia_std::dex { // 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 - ), + bigdecimal::sub(bigdecimal::one(), normalized_weight), amount_in ); let fee_amount = - calculate_fee_with_minimum( - config.swap_fee_rate, - adjusted_swap_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; @@ -1861,16 +1819,8 @@ module initia_std::dex { let init_metadata = coin::metadata(chain_addr, string::utf8(b"INIT")); let usdc_metadata = coin::metadata(chain_addr, string::utf8(b"USDC")); - coin::mint_to( - &initia_mint_cap, - chain_addr, - 100000000 - ); - coin::mint_to( - &usdc_mint_cap, - chain_addr, - 100000000 - ); + coin::mint_to(&initia_mint_cap, chain_addr, 100000000); + coin::mint_to(&usdc_mint_cap, chain_addr, 100000000); // spot price is 1 create_pair_script( @@ -2016,16 +1966,8 @@ module initia_std::dex { let init_metadata = coin::metadata(chain_addr, string::utf8(b"INIT")); let usdc_metadata = coin::metadata(chain_addr, string::utf8(b"USDC")); - coin::mint_to( - &initia_mint_cap, - chain_addr, - 100000000 - ); - coin::mint_to( - &usdc_mint_cap, - chain_addr, - 100000000 - ); + coin::mint_to(&initia_mint_cap, chain_addr, 100000000); + coin::mint_to(&usdc_mint_cap, chain_addr, 100000000); set_block_info(10, 1000); @@ -2203,21 +2145,9 @@ module initia_std::dex { let b_addr = object::object_address(&b_metadata); let c_addr = object::object_address(&c_metadata); - coin::mint_to( - &coin_a_mint_cap, - chain_addr, - 100000000 - ); - coin::mint_to( - &coin_b_mint_cap, - chain_addr, - 100000000 - ); - coin::mint_to( - &coin_c_mint_cap, - chain_addr, - 100000000 - ); + coin::mint_to(&coin_a_mint_cap, chain_addr, 100000000); + coin::mint_to(&coin_b_mint_cap, chain_addr, 100000000); + coin::mint_to(&coin_c_mint_cap, chain_addr, 100000000); create_pair_script( &chain, @@ -2417,12 +2347,7 @@ module initia_std::dex { 2 ); - let res = get_pairs( - a_addr, - b_addr, - option::none(), - 10 - ); + let res = get_pairs(a_addr, b_addr, option::none(), 10); assert!( res == vector[ @@ -2444,12 +2369,7 @@ module initia_std::dex { 3 ); - let res = get_pairs( - a_addr, - b_addr, - option::some(pair_1_addr), - 10 - ); + let res = get_pairs(a_addr, b_addr, option::some(pair_1_addr), 10); assert!( res == vector[ diff --git a/initia_stdlib/sources/fa/dispatchable_fungible_asset.move b/initia_stdlib/sources/fa/dispatchable_fungible_asset.move index 89900c4..8059b34 100644 --- a/initia_stdlib/sources/fa/dispatchable_fungible_asset.move +++ b/initia_stdlib/sources/fa/dispatchable_fungible_asset.move @@ -102,12 +102,7 @@ module initia_std::dispatchable_fungible_asset { 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 - ) + dispatchable_deposit(store, fa, borrow_transfer_ref(store), func) } else { fungible_asset::deposit_internal(object::object_address(&store), fa) } @@ -139,7 +134,10 @@ module initia_std::dispatchable_fungible_asset { let fa = withdraw(sender, from, amount); deposit(to, fa); let end = fungible_asset::balance(to); - assert!(end - start >= expected, error::aborted(EAMOUNT_MISMATCH)); + assert!( + end - start >= expected, + error::aborted(EAMOUNT_MISMATCH) + ); } #[view] diff --git a/initia_stdlib/sources/fa/fungible_asset.move b/initia_stdlib/sources/fa/fungible_asset.move index 3618fed..3417911 100644 --- a/initia_stdlib/sources/fa/fungible_asset.move +++ b/initia_stdlib/sources/fa/fungible_asset.move @@ -369,8 +369,7 @@ module initia_std::fungible_asset { // 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 + &function_info, supply_function ), error::invalid_argument( EDERIVED_SUPPLY_FUNCTION_SIGNATURE_MISMATCH @@ -482,13 +481,7 @@ 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 { - 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 + metadata(metadata).symbol } #[view] @@ -506,19 +499,20 @@ module initia_std::fungible_asset { #[view] /// Get the metadata struct from the `metadata` object. public fun metadata(metadata: Object): Metadata acquires Metadata { - *borrow_fungible_metadata(&metadata) + let md = *borrow_fungible_metadata(&metadata); + if (object::is_owner(metadata, @initia_std) + && md.symbol == string::utf8(b"uinit")) { + md.symbol = string::utf8(b"INIT"); + md.decimals = 6; + }; + + md } #[view] /// Get the decimals from the `metadata` object. public fun decimals(metadata: Object): u8 acquires Metadata { - let md = borrow_fungible_metadata(&metadata); - if (object::is_owner(metadata, @initia_std) - && md.symbol == string::utf8(b"uinit")) { - return 6 - }; - - md.decimals + metadata(metadata).decimals } #[view] @@ -1131,9 +1125,7 @@ module initia_std::fungible_asset { string::utf8(b"TEST"), string::utf8(b"@@"), 0, - string::utf8( - b"http://www.example.com/favicon.ico" - ), + string::utf8(b"http://www.example.com/favicon.ico"), string::utf8(b"http://www.example.com") ); let mint_ref = generate_mint_ref(constructor_ref); @@ -1220,12 +1212,7 @@ module initia_std::fungible_asset { burn_from(&burn_ref, aaron_store, 30); assert!(supply(test_token) == option::some(70), 4); // Transfer - transfer( - creator, - creator_store, - aaron_store, - 10 - ); + transfer(creator, creator_store, aaron_store, 10); assert!(balance(creator_store) == 10, 5); assert!(balance(aaron_store) == 60, 6); @@ -1248,7 +1235,10 @@ module initia_std::fungible_asset { icon_uri(metadata) == string::utf8(b"http://www.example.com/favicon.ico"), 11 ); - assert!(project_uri(metadata) == string::utf8(b"http://www.example.com"), 12); + assert!( + project_uri(metadata) == string::utf8(b"http://www.example.com"), + 12 + ); } #[test(creator = @0xcafe)] @@ -1275,12 +1265,7 @@ module initia_std::fungible_asset { set_frozen_flag(&transfer_ref, creator_store, true); set_frozen_flag(&transfer_ref, aaron_store, true); deposit_with_ref(&transfer_ref, creator_store, fa); - transfer_with_ref( - &transfer_ref, - creator_store, - aaron_store, - 80 - ); + transfer_with_ref(&transfer_ref, creator_store, aaron_store, 80); assert!(balance(creator_store) == 20, 1); assert!(balance(aaron_store) == 80, 2); assert!(!!is_frozen(creator_store), 3); @@ -1332,19 +1317,9 @@ module initia_std::fungible_asset { let metadata = mint_ref.metadata; let module_acc_store = create_test_store(module_acc, metadata); - account::set_account_info( - signer::address_of(module_acc), - 10, - 0, - 3, - false - ); + account::set_account_info(signer::address_of(module_acc), 10, 0, 3, false); - set_frozen_flag( - &transfer_ref, - module_acc_store, - true - ); + set_frozen_flag(&transfer_ref, module_acc_store, true); } #[test(creator = @0xcafe, module_acc = @0x123)] @@ -1357,13 +1332,7 @@ module initia_std::fungible_asset { let metadata = mint_ref.metadata; let module_acc_store = create_test_store(module_acc, metadata); - account::set_account_info( - signer::address_of(module_acc), - 10, - 0, - 3, - false - ); + account::set_account_info(signer::address_of(module_acc), 10, 0, 3, false); let fa = mint(&mint_ref, 100); deposit(module_acc_store, fa); @@ -1380,13 +1349,7 @@ module initia_std::fungible_asset { let metadata = mint_ref.metadata; let module_acc_store = create_test_store(module_acc, metadata); - account::set_account_info( - signer::address_of(module_acc), - 10, - 0, - 3, - false - ); + account::set_account_info(signer::address_of(module_acc), 10, 0, 3, false); let fa = mint(&mint_ref, 100); deposit(module_acc_store, fa); @@ -1404,13 +1367,7 @@ module initia_std::fungible_asset { let metadata = mint_ref.metadata; let blocked_acc_store = create_test_store(blocked_acc, metadata); - account::set_account_info( - signer::address_of(blocked_acc), - 10, - 0, - 3, - true - ); + account::set_account_info(signer::address_of(blocked_acc), 10, 0, 3, true); let fa = mint(&mint_ref, 100); deposit(blocked_acc_store, fa); @@ -1426,13 +1383,7 @@ module initia_std::fungible_asset { let metadata = mint_ref.metadata; let blocked_acc_store = create_test_store(blocked_acc, metadata); - account::set_account_info( - signer::address_of(blocked_acc), - 10, - 0, - 3, - true - ); + account::set_account_info(signer::address_of(blocked_acc), 10, 0, 3, true); let fa = mint(&mint_ref, 100); deposit_with_ref(&transfer_ref, blocked_acc_store, fa); diff --git a/initia_stdlib/sources/fa/primary_fungible_store.move b/initia_stdlib/sources/fa/primary_fungible_store.move index 88343af..8a7438a 100644 --- a/initia_stdlib/sources/fa/primary_fungible_store.move +++ b/initia_stdlib/sources/fa/primary_fungible_store.move @@ -137,10 +137,7 @@ module initia_std::primary_fungible_store { // record owner store to table for cosmos side query if (exists(@initia_std)) { let module_store = borrow_global_mut(@initia_std); - if (!table::contains( - &module_store.user_stores, - owner_addr - )) { + if (!table::contains(&module_store.user_stores, owner_addr)) { table::add( &mut module_store.user_stores, owner_addr, @@ -148,13 +145,11 @@ module initia_std::primary_fungible_store { ); }; - 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 ); + + table::add(user_stores, metadata_addr, store_addr); }; // emit store created event @@ -220,12 +215,7 @@ module initia_std::primary_fungible_store { ): (vector>, vector) acquires ModuleStore { let module_store = borrow_global(@initia_std); let account_stores = table::borrow(&module_store.user_stores, account); - let iter = table::iter( - account_stores, - option::none(), - start_after, - 2 - ); + let iter = table::iter(account_stores, option::none(), start_after, 2); let metadata_vec: vector> = vector[]; let balance_vec: vector = vector[]; @@ -274,12 +264,7 @@ module initia_std::primary_fungible_store { 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 - ); + fungible_asset::sudo_transfer(sender, sender_store, recipient_store, amount); } /// Withdraw `amount` of fungible asset from the given account's primary store. @@ -394,11 +379,7 @@ module initia_std::primary_fungible_store { owner, fungible_asset::transfer_ref_metadata(transfer_ref) ); - fungible_asset::withdraw_with_ref( - transfer_ref, - from_primary_store, - amount - ) + fungible_asset::withdraw_with_ref(transfer_ref, from_primary_store, amount) } /// Deposit from the primary store of `owner` ignoring frozen flag. diff --git a/initia_stdlib/sources/fixed_point64.move b/initia_stdlib/sources/fixed_point64.move index 6cff2d2..3bd209c 100644 --- a/initia_stdlib/sources/fixed_point64.move +++ b/initia_stdlib/sources/fixed_point64.move @@ -223,7 +223,10 @@ 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); diff --git a/initia_stdlib/sources/json.move b/initia_stdlib/sources/json.move index 0aa2a8a..5c9f55f 100644 --- a/initia_stdlib/sources/json.move +++ b/initia_stdlib/sources/json.move @@ -2,7 +2,7 @@ module initia_std::json { 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 @@ -26,19 +26,25 @@ module initia_std::json { /// 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) - }) + 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 - }); + let (found, idx) = vector::find( + &obj.elems, + |elem| { + use_elem(elem); + elem.key == *key_bytes + } + ); if (!found) { return option::none() @@ -49,18 +55,23 @@ module initia_std::json { } /// Set or overwrite the element in the JSON object. - public fun set_elem(obj: &mut JSONObject, key: String, value: &T) { + 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 - }); + 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) - }); + 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); @@ -154,9 +165,7 @@ module initia_std::json { b: true, c: vector[1, 2, 3], d: @0x1, - e: option::some( - TestObject2 { a: 42, b: true, c: vector[1, 2, 3] } - ), + e: option::some(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"), @@ -187,15 +196,44 @@ module initia_std::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); + 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); + 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); + 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/managed_coin.move b/initia_stdlib/sources/managed_coin.move index 6a90072..9dcb7ce 100644 --- a/initia_stdlib/sources/managed_coin.move +++ b/initia_stdlib/sources/managed_coin.move @@ -202,18 +202,8 @@ module initia_std::managed_coin { let metadata = test_metadata(); assert!(coin::is_coin(object::object_address(&metadata)), 0); - mint_to( - &mod_account, - source_addr, - metadata, - 50 - ); - mint_to( - &mod_account, - destination_addr, - metadata, - 10 - ); + mint_to(&mod_account, source_addr, metadata, 50); + mint_to(&mod_account, destination_addr, metadata, 10); assert!(coin::balance(source_addr, metadata) == 50, 1); assert!( coin::balance(destination_addr, metadata) == 10, @@ -223,12 +213,7 @@ module initia_std::managed_coin { let supply = coin::supply(metadata); assert!(supply == option::some(60), 2); - coin::transfer( - &source, - destination_addr, - metadata, - 10 - ); + coin::transfer(&source, destination_addr, metadata, 10); assert!(coin::balance(source_addr, metadata) == 40, 3); assert!( coin::balance(destination_addr, metadata) == 20, @@ -269,12 +254,7 @@ module initia_std::managed_coin { ); let metadata = test_metadata(); - mint_to( - &destination, - source_addr, - metadata, - 100 - ); + mint_to(&destination, source_addr, metadata, 100); } #[test(source = @0xa11ce, destination = @0xb0b, mod_account = @0x1)] @@ -297,12 +277,7 @@ module initia_std::managed_coin { ); let metadata = test_metadata(); - mint_to( - &mod_account, - source_addr, - metadata, - 100 - ); + mint_to(&mod_account, source_addr, metadata, 100); burn(&destination, metadata, 10); } } diff --git a/initia_stdlib/sources/math128.move b/initia_stdlib/sources/math128.move index 5fdf088..00e62ef 100644 --- a/initia_stdlib/sources/math128.move +++ b/initia_stdlib/sources/math128.move @@ -165,10 +165,8 @@ module initia_std::math128 { // No overflow assert!( - ceil_div( - (((1u256 << 128) - 9) as u128), - 11 - ) == 30934760629176223951215873402888019223, + ceil_div((((1u256 << 128) - 9) as u128), 11) + == 30934760629176223951215873402888019223, 0 ); } diff --git a/initia_stdlib/sources/math64.move b/initia_stdlib/sources/math64.move index 4e92276..c3d5eb3 100644 --- a/initia_stdlib/sources/math64.move +++ b/initia_stdlib/sources/math64.move @@ -138,10 +138,7 @@ module initia_std::math64 { // No overflow assert!( - ceil_div( - (((1u128 << 64) - 9) as u64), - 11 - ) == 1676976733973595601, + ceil_div((((1u128 << 64) - 9) as u64), 11) == 1676976733973595601, 0 ); } diff --git a/initia_stdlib/sources/minitswap.move b/initia_stdlib/sources/minitswap.move index b1091c8..c3bdcd8 100644 --- a/initia_stdlib/sources/minitswap.move +++ b/initia_stdlib/sources/minitswap.move @@ -406,11 +406,7 @@ module initia_std::minitswap { offer_amount: u64 ): (u64, u64) acquires ModuleStore, VirtualPool { let (return_amount, fee_amount) = - safe_swap_simulation( - offer_metadata, - return_metadata, - offer_amount - ); + safe_swap_simulation(offer_metadata, return_metadata, offer_amount); assert!( return_amount != 0, error::invalid_state(EIBC_OP_INIT_PRICE_TOO_LOW) @@ -443,11 +439,7 @@ module initia_std::minitswap { ): (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) } #[view] @@ -510,10 +502,7 @@ module initia_std::minitswap { 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 - ) + generate_unbond_key(account, *option::borrow(&start_after) + 1) } else { generate_unbond_key(account, 0) }; @@ -1152,15 +1141,9 @@ module initia_std::minitswap { let change_rate = if (new_pool_size > pool.pool_size) { - bigdecimal::from_ratio_u64( - new_pool_size - pool.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 - ) + bigdecimal::from_ratio_u64(pool.pool_size - new_pool_size, pool.pool_size) }; assert!( @@ -1191,8 +1174,7 @@ module initia_std::minitswap { ratio, pool.init_pool_amount ); pool.ibc_op_init_pool_amount = bigdecimal::mul_by_u64_truncate( - ratio, - pool.ibc_op_init_pool_amount + ratio, pool.ibc_op_init_pool_amount ); pool.pool_size = new_pool_size; @@ -1406,11 +1388,7 @@ module initia_std::minitswap { public entry fun unbond(account: &signer, amount: u64) acquires ModuleStore { let share_token = - primary_fungible_store::withdraw( - account, - share_token_metadata(), - amount - ); + primary_fungible_store::withdraw(account, share_token_metadata(), amount); unbond_internal(account, share_token); } @@ -1464,11 +1442,7 @@ module initia_std::minitswap { min_return_amount: Option ) acquires ModuleStore, VirtualPool { let offer_asset = - primary_fungible_store::withdraw( - account, - offer_asset_metadata, - amount - ); + 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); @@ -1624,11 +1598,7 @@ module initia_std::minitswap { string::append(&mut symbol, ibc_denom); let coins: vector = vector[ - coin::withdraw( - account, - init_metadata(), - init_amount - ), + coin::withdraw(account, init_metadata(), init_amount), coin::withdraw( account, ibc_op_init_metadata, @@ -1867,11 +1837,7 @@ module initia_std::minitswap { }; // check arb - check_arb( - module_store, - pool, - ibc_op_init_metadata - ); + check_arb(module_store, pool, ibc_op_init_metadata); event::emit( SwapEvent { @@ -2019,9 +1985,7 @@ module initia_std::minitswap { ); // Peg keeper swap let r_fr = get_fully_recovered_ratio( - imbalance, - pool.max_ratio, - pool.recover_param + imbalance, pool.max_ratio, pool.recover_param ); let current_ratio = bigdecimal::from_ratio_u64( @@ -2098,8 +2062,7 @@ module initia_std::minitswap { // take swap fee let swap_fee_amount = bigdecimal::mul_by_u64_ceil( - module_store.swap_fee_rate, - return_amount + module_store.swap_fee_rate, return_amount ); return_amount = return_amount - swap_fee_amount; @@ -2109,8 +2072,7 @@ module initia_std::minitswap { return_amount - offer_amount } else { 0 }; arb_fee_amount = bigdecimal::mul_by_u64_ceil( - module_store.arb_fee_rate, - arb_profit + module_store.arb_fee_rate, arb_profit ); return_amount = return_amount - arb_fee_amount; let total_fee_amount = swap_fee_amount + arb_fee_amount; @@ -2134,9 +2096,7 @@ module initia_std::minitswap { ( primary_fungible_store::withdraw( - &pool_signer, - return_metadata, - return_amount + &pool_signer, return_metadata, return_amount ), swap_fee_amount, depositor_return_amount @@ -2160,8 +2120,7 @@ module initia_std::minitswap { // take swap fee let swap_fee_amount = bigdecimal::mul_by_u64_ceil( - module_store.swap_fee_rate, - return_amount + module_store.swap_fee_rate, return_amount ); let return_amount = return_amount - swap_fee_amount; @@ -2292,10 +2251,7 @@ module initia_std::minitswap { ibc_channel: String ): &mut Pools { if (table::contains(&module_store.pools, ibc_op_init_metadata)) { - table::borrow_mut( - &mut module_store.pools, - ibc_op_init_metadata - ) + table::borrow_mut(&mut module_store.pools, ibc_op_init_metadata) } else { table::add( &mut module_store.pools, @@ -2308,10 +2264,7 @@ module initia_std::minitswap { } ); - table::borrow_mut( - &mut module_store.pools, - ibc_op_init_metadata - ) + table::borrow_mut(&mut module_store.pools, ibc_op_init_metadata) } } @@ -2850,8 +2803,7 @@ module initia_std::minitswap { // take swap fee let swap_fee_amount = bigdecimal::mul_by_u64_ceil( - module_store.swap_fee_rate, - return_amount + module_store.swap_fee_rate, return_amount ); // take arb fee @@ -2860,10 +2812,7 @@ module initia_std::minitswap { 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 - ); + 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) @@ -2878,8 +2827,7 @@ module initia_std::minitswap { ); let fee_amount = bigdecimal::mul_by_u64_ceil( - module_store.swap_fee_rate, - return_amount + module_store.swap_fee_rate, return_amount ); (return_amount, fee_amount) @@ -2928,7 +2876,9 @@ module initia_std::minitswap { bigdecimal::truncate_u64( bigdecimal::div( bigdecimal::from_u64(return_amount), - bigdecimal::sub(bigdecimal::one(), module_store.swap_fee_rate) + bigdecimal::sub( + bigdecimal::one(), module_store.swap_fee_rate + ) ) ); if (ibc_op_init_pool_amount - return_amount_before_swap_fee < pool_size) { @@ -2952,10 +2902,7 @@ module initia_std::minitswap { return_amount - offer_amount } else { 0 }; let arb_fee_amount = - bigdecimal::mul_by_u64_ceil( - 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 let actual_return_amount = return_amount - arb_fee_amount; @@ -2990,8 +2937,7 @@ module initia_std::minitswap { 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 + module_store.arb_fee_rate, arb_profit ); actual_return_amount = return_amount_before_swap_fee - swap_fee_amount - arb_fee_amount; @@ -3008,7 +2954,9 @@ module initia_std::minitswap { bigdecimal::truncate_u64( bigdecimal::div( bigdecimal::from_u64(return_amount), - bigdecimal::sub(bigdecimal::one(), module_store.swap_fee_rate) + bigdecimal::sub( + bigdecimal::one(), module_store.swap_fee_rate + ) ) ); let fee_amount = return_amount_ - return_amount; @@ -3177,16 +3125,8 @@ module initia_std::minitswap { b"ibc/82EB1C694C571F954E68BFD68CFCFCD6123B0EBB69AAA8BAB7A082939B45E802" ) ); - coin::mint_to( - &initia_mint_cap, - chain_addr, - 1000000000 - ); - coin::mint_to( - &ibc_op_init_mint_cap, - chain_addr, - 1000000000 - ); + coin::mint_to(&initia_mint_cap, chain_addr, 1000000000); + coin::mint_to(&ibc_op_init_mint_cap, chain_addr, 1000000000); provide(&chain, 15000000, option::none()); create_pool( @@ -3294,11 +3234,7 @@ module initia_std::minitswap { ) ); - coin::mint_to( - &initia_mint_cap, - chain_addr, - 100000000 - ); + coin::mint_to(&initia_mint_cap, chain_addr, 100000000); coin::mint_to( &ibc_op_init_1_mint_cap, chain_addr, @@ -3373,11 +3309,7 @@ module initia_std::minitswap { // swap init to ibc op init let (return_amount, _) = - swap_simulation( - init_metadata, - ibc_op_init_1_metadata, - 500000 - ); + swap_simulation(init_metadata, ibc_op_init_1_metadata, 500000); assert!(return_amount == 504224, 0); let balance_before = coin::balance(chain_addr, ibc_op_init_1_metadata); @@ -3394,11 +3326,7 @@ module initia_std::minitswap { 0 ); - change_pool_size( - &chain, - ibc_op_init_1_metadata, - 9000000 - ); + change_pool_size(&chain, ibc_op_init_1_metadata, 9000000); } #[test] diff --git a/initia_stdlib/sources/multisig.move b/initia_stdlib/sources/multisig.move index 81b5f81..d5451d7 100644 --- a/initia_stdlib/sources/multisig.move +++ b/initia_stdlib/sources/multisig.move @@ -317,10 +317,7 @@ module initia_std::multisig { assert_member(&multisig_wallet.members, &voter); assert!( - table::contains( - &multisig_wallet.proposals, - proposal_id - ), + table::contains(&multisig_wallet.proposals, proposal_id), error::invalid_argument(EPROPOSAL_NOT_FOUND) ); let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id); @@ -344,10 +341,7 @@ module initia_std::multisig { assert_member(&multisig_wallet.members, &executor); assert!( - table::contains( - &multisig_wallet.proposals, - proposal_id - ), + table::contains(&multisig_wallet.proposals, proposal_id), error::invalid_argument(EPROPOSAL_NOT_FOUND) ); let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id); @@ -357,10 +351,8 @@ module initia_std::multisig { // check passed assert!( - yes_vote_count( - &proposal.votes, - &multisig_wallet.members - ) >= multisig_wallet.threshold, + yes_vote_count(&proposal.votes, &multisig_wallet.members) + >= multisig_wallet.threshold, error::invalid_state(ENOT_PASS) ); diff --git a/initia_stdlib/sources/multisig_v2.move b/initia_stdlib/sources/multisig_v2.move new file mode 100644 index 0000000..0547661 --- /dev/null +++ b/initia_stdlib/sources/multisig_v2.move @@ -0,0 +1,2465 @@ +module initia_std::multisig_v2 { + use std::error; + use std::option::{Self, Option}; + use std::signer; + use std::string::{Self, String}; + use std::vector; + use std::event; + + use initia_std::block::get_block_info; + use initia_std::cosmos::{move_execute, move_execute_with_json}; + use initia_std::object::{Self, ExtendRef}; + use initia_std::simple_map::{Self, SimpleMap}; + use initia_std::table::{Self, Table}; + use initia_std::type_info; + + // errors + + const EINVALID_THRESHOLD: u64 = 1; + + const ENOT_MEMBER: u64 = 2; + + const EINVALID_PROPOSAL_STATUS: u64 = 3; + + const EPROPOSAL_EXPIRED: u64 = 4; + + const ENOT_PASS: u64 = 5; + + const EPROPOSAL_NOT_FOUND: u64 = 6; + + const EINVALID_TIERS_LENGTH: u64 = 7; + + const EINVALID_MEMBERS_LENGTH: u64 = 8; + + const EINVALID_MEMBER_TIERS: u64 = 9; + + const EINVALID_EXPIRY_TIMESTAMP: u64 = 10; + + const EMULTISIG_NAME_TOO_LONG: u64 = 11; + + const EINVALID_PROPOSAL_MESSAGE_LENGTH: u64 = 12; + + // constants + + const STATUS: vector> = vector[b"voting", b"executed", b"expired"]; + + const MAX_LIMIT: u8 = 30; + + const MAX_MULTISIG_NAME_LENGTH: u64 = 64; + + // structs + + struct Tier has copy, drop, store { + name: String, + weight: u64 + } + + struct Member has copy, drop, store { + address: address, + tier: Option + } + + struct MultisigWallet has key { + extend_ref: ExtendRef, + name: String, + weighted: bool, // if true -> tiers should be present + tiers: Option>, + members: vector, // members of multisig account + threshold: u64, // require weight to pass + proposals: Table + } + + struct ExecuteMessage has copy, drop, store { + module_address: address, + module_name: String, + function_name: String, + type_args: vector, + args: vector>, + json_args: vector + } + + struct Proposal has store { + proposer: Member, + proposed_timestamp: u64, + proposed_height: u64, + expiry_timestamp: Option, + votes: SimpleMap, + threshold: u64, + total_weight: u64, + status: u8, + is_json: bool, + execute_messages: vector + } + + // events + + #[event] + struct CreateMultisigAccountEvent has drop, store { + multisig_addr: address, + name: String, + weighted: bool, + members: vector, + threshold: u64 + } + + #[event] + struct CreateProposalEvent has drop, store { + multisig_addr: address, + proposal_id: u64, + proposer: Member, + execute_messages: vector + } + + #[event] + struct VoteProposalEvent has drop, store { + multisig_addr: address, + proposal_id: u64, + voter: Member, + vote_yes: bool + } + + #[event] + struct ExecuteProposalEvent has drop, store { + multisig_addr: address, + proposal_id: u64, + executor: Member + } + + #[event] + struct UpdateConfigEvent has drop, store { + multisig_addr: address, + members: vector, + tiers: Option>, + threshold: u64 + } + + // view function response struct + + struct ProposalResponse has drop { + multisig_addr: address, + proposal_id: u64, + votes: SimpleMap, + proposer: Member, + proposed_height: u64, + proposed_timestamp: u64, + expiry_timestamp: Option, + threshold: u64, + total_weight: u64, + yes_vote_score: u64, + status: String, + is_json: bool, + execute_messages: vector + } + + struct MultisigResponse has drop { + multisig_addr: address, + name: String, + members: vector, + threshold: u64, + tiers: Option> + } + + // view functions + + #[view] + public fun is_exist(creator_addr: address, name: String): bool { + let seed = create_multisig_seed(&name); + let multisig_addr = object::create_object_address(&creator_addr, seed); + object::object_exists(multisig_addr) + } + + #[view] + public fun get_multisig(multisig_addr: address): MultisigResponse acquires MultisigWallet { + let multisig_wallet = borrow_global(multisig_addr); + + MultisigResponse { + multisig_addr, + name: multisig_wallet.name, + tiers: multisig_wallet.tiers, + members: multisig_wallet.members, + threshold: multisig_wallet.threshold + } + } + + #[view] + 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 + ) + } + + #[view] + public fun get_proposals( + multisig_addr: address, start_after: Option, limit: u8 + ): vector acquires MultisigWallet { + if (limit > MAX_LIMIT) { + limit = MAX_LIMIT + }; + let res: vector = vector[]; + let multisig_wallet = borrow_global(multisig_addr); + let iter = table::iter( + &multisig_wallet.proposals, + option::none(), + start_after, + 2 + ); + + while (vector::length(&res) < (limit as u64) + && table::prepare(iter)) { + let (proposal_id, proposal) = table::next(iter); + vector::push_back( + &mut res, + proposal_to_proposal_response( + multisig_wallet, + multisig_addr, + proposal_id, + proposal + ) + ); + }; + + res + } + + // entry functions + + /// Create new non weighted multisig account + public entry fun create_non_weighted_multisig_account( + account: &signer, + name: String, // name for make deterministic multisig address (account_addr + name) + members: vector
, + threshold: u64 + ) { + assert_member(&members, &signer::address_of(account)); + assert!( + vector::length(&members) >= threshold, + error::invalid_argument(EINVALID_THRESHOLD) + ); + assert!( + threshold > 0, + error::invalid_argument(EINVALID_THRESHOLD) + ); + + let constructor_ref = + object::create_named_object(account, create_multisig_seed(&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); + + assert_uniqueness(members); + + let members = vector::map( + members, + |member| Member { address: member, tier: option::none() } + ); + + move_to( + &multisig_signer, + MultisigWallet { + extend_ref, + name, + members, + weighted: false, + tiers: option::none(), + threshold, + proposals: table::new() + } + ); + + event::emit( + CreateMultisigAccountEvent { + multisig_addr, + name, + weighted: false, + members, + threshold + } + ) + } + + /// Create new weighted multisig account + public entry fun create_weighted_multisig_account( + account: &signer, + name: String, // name for make deterministic multisig address (account_addr + name) + tiers: vector, + tier_weights: vector, + members: vector
, + member_tiers: vector, + threshold: u64 + ) { + assert_member(&members, &signer::address_of(account)); + assert_uniqueness(members); + assert_tier_config(tiers, tier_weights, &members, member_tiers); + assert_uniqueness(tiers); + + // check threshold computed from each member weights + let total_weight = vector::fold( + member_tiers, + 0u64, + |acc, tier| { + let (_, index) = vector::index_of(&tiers, &tier); + acc + *vector::borrow(&tier_weights, index) + } + ); + assert!( + total_weight >= threshold, + error::invalid_argument(EINVALID_THRESHOLD) + ); + assert!( + threshold > 0, + error::invalid_argument(EINVALID_THRESHOLD) + ); + + let constructor_ref = + object::create_named_object(account, create_multisig_seed(&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 tiers = vector::map( + tiers, + |tier| { + let (_, index) = vector::index_of(&tiers, &tier); + Tier { name: tier, weight: *vector::borrow(&tier_weights, index) } + } + ); + + let members = construct_members_with_tiers(members, member_tiers, tiers); + + move_to( + &multisig_signer, + MultisigWallet { + extend_ref, + name, + members, + weighted: true, + tiers: option::some(tiers), + threshold, + proposals: table::new() + } + ); + + event::emit( + CreateMultisigAccountEvent { + multisig_addr, + weighted: true, + name, + members, + threshold + } + ) + } + + fun total_weight(members: &vector): u64 { + vector::fold( + *members, + 0u64, + |acc, member| { + let m: Member = member; + acc + + if (option::is_some(&m.tier)) { + let tier = *option::borrow(&m.tier); + tier.weight + } else { 1u64 } + } + ) + } + + /// Create new proposal + public entry fun create_proposal( + account: &signer, + multisig_addr: address, + module_address_list: vector
, + module_name_list: vector, + function_name_list: vector, + type_args_list: vector>, + args_list: vector>>, + expiry_duration: Option + ) acquires MultisigWallet { + assert!( + vector::length(&module_address_list) == vector::length(&module_name_list) + && vector::length(&module_name_list) + == vector::length(&function_name_list) + && vector::length(&function_name_list) + == vector::length(&type_args_list) + && vector::length(&type_args_list) == vector::length(&args_list), + error::invalid_argument(EINVALID_PROPOSAL_MESSAGE_LENGTH) + ); + + let index = 0; + let execute_messages = vector::map( + module_address_list, + |module_address| { + let module_name = *vector::borrow(&module_name_list, index); + let function_name = *vector::borrow(&function_name_list, index); + let type_args = *vector::borrow(&type_args_list, index); + let args = *vector::borrow(&args_list, index); + index = index + 1; + + ExecuteMessage { + module_address, + module_name, + function_name, + type_args, + args, + json_args: vector[] + } + } + ); + + create_proposal_internal( + account, + multisig_addr, + false, + execute_messages, + expiry_duration + ) + } + + /// Create new proposal + public entry fun create_proposal_with_json( + account: &signer, + multisig_addr: address, + module_address_list: vector
, + module_name_list: vector, + function_name_list: vector, + type_args_list: vector>, + args_list: vector>, + expiry_duration: Option + ) acquires MultisigWallet { + assert!( + vector::length(&module_address_list) == vector::length(&module_name_list) + && vector::length(&module_name_list) + == vector::length(&function_name_list) + && vector::length(&function_name_list) + == vector::length(&type_args_list) + && vector::length(&type_args_list) == vector::length(&args_list), + error::invalid_argument(EINVALID_PROPOSAL_MESSAGE_LENGTH) + ); + + let index = 0; + let execute_messages = vector::map( + module_address_list, + |module_address| { + let module_name = *vector::borrow(&module_name_list, index); + let function_name = *vector::borrow(&function_name_list, index); + let type_args = *vector::borrow(&type_args_list, index); + let json_args = *vector::borrow(&args_list, index); + index = index + 1; + + ExecuteMessage { + module_address, + module_name, + function_name, + type_args, + args: vector[], + json_args + } + } + ); + + create_proposal_internal( + account, + multisig_addr, + true, + execute_messages, + expiry_duration + ) + } + + /// Vote proposal + public entry fun vote_proposal( + account: &signer, + multisig_addr: address, + proposal_id: u64, + vote_yes: bool + ) acquires MultisigWallet { + let voter_address = signer::address_of(account); + let multisig_wallet = borrow_global_mut(multisig_addr); + assert_multisig_member(&multisig_wallet.members, &voter_address); + + 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_proposal(proposal); + + let voter = get_member_by_address(multisig_wallet.members, voter_address); + vote(&mut proposal.votes, voter, vote_yes); + + event::emit( + VoteProposalEvent { multisig_addr, proposal_id, voter, vote_yes } + ) + } + + /// Execute proposal + public entry fun execute_proposal( + account: &signer, multisig_addr: address, proposal_id: u64 + ) acquires MultisigWallet { + let executor_address = signer::address_of(account); + let multisig_wallet = borrow_global_mut(multisig_addr); + let executor = get_member_by_address(multisig_wallet.members, executor_address); + assert_multisig_member(&multisig_wallet.members, &executor_address); + + 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_proposal(proposal); + + // check passed + assert!( + yes_vote_score(&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); + + proposal.status = 1; // change the status first in case of updating config + + if (!proposal.is_json) { + vector::for_each( + proposal.execute_messages, + |execute_message| { + let m: ExecuteMessage = execute_message; + move_execute( + multisig_signer, + m.module_address, + m.module_name, + m.function_name, + m.type_args, + m.args + ) + } + ) + } else { + vector::for_each( + proposal.execute_messages, + |execute_message| { + let m: ExecuteMessage = execute_message; + move_execute_with_json( + multisig_signer, + m.module_address, + m.module_name, + m.function_name, + m.type_args, + m.json_args + ) + } + ) + }; + + event::emit( + ExecuteProposalEvent { multisig_addr, proposal_id, executor } + ) + } + + /// Update config. Only execute by multisig wallet itself + public entry fun update_config( + account: &signer, + new_members: vector
, + new_tiers: Option>, + new_tier_weights: Option>, + new_member_tiers: Option>, + new_threshold: u64 + ) acquires MultisigWallet { + let multisig_addr = signer::address_of(account); + let multisig_wallet = borrow_global_mut(multisig_addr); + + assert_uniqueness(new_members); + + let removed_members = vector::filter( + multisig_wallet.members, + |member| { + let m: &Member = member; + !vector::contains(&new_members, &m.address) + } + ); + + if (multisig_wallet.weighted) { + let new_tiers = *option::borrow(&new_tiers); + let new_tier_weights = *option::borrow(&new_tier_weights); + let new_member_tiers = *option::borrow(&new_member_tiers); + + assert_tier_config( + new_tiers, + new_tier_weights, + &new_members, + new_member_tiers + ); + assert_uniqueness(new_tiers); + + // check threshold computed from each member weights + let total_weight = vector::fold( + new_member_tiers, + 0u64, + |acc, tier| { + let (_, index) = vector::index_of(&new_tiers, &tier); + acc + *vector::borrow(&new_tier_weights, index) + } + ); + + assert!( + total_weight >= new_threshold, + error::invalid_argument(EINVALID_THRESHOLD) + ); + assert!( + new_threshold > 0, + error::invalid_argument(EINVALID_THRESHOLD) + ); + + let tiers = vector::map( + new_tiers, + |tier| { + let (_, index) = vector::index_of(&new_tiers, &tier); + Tier { name: tier, weight: *vector::borrow(&new_tier_weights, index) } + } + ); + + multisig_wallet.threshold = new_threshold; + multisig_wallet.tiers = option::some(tiers); + multisig_wallet.members = construct_members_with_tiers( + new_members, new_member_tiers, tiers + ); + } else { + assert!( + vector::length(&new_members) >= new_threshold, + error::invalid_argument(EINVALID_THRESHOLD) + ); + + multisig_wallet.threshold = new_threshold; + multisig_wallet.members = vector::map( + new_members, + |member| Member { address: member, tier: option::none() } + ); + }; + + // remove votes of the removed members from active proposals + let iter = + table::iter_mut( + &mut multisig_wallet.proposals, + option::none(), + option::none(), + 2 + ); + while (table::prepare(iter)) { + let (_, proposal) = table::next_mut(iter); + // only cares about active proposals + if (proposal.status != 0 || is_proposal_expired(proposal)) { + continue + }; + + proposal.threshold = new_threshold; + proposal.total_weight = total_weight(&multisig_wallet.members); + + // remove removed_members votes + vector::for_each( + removed_members, + |member| { + let m: Member = member; + if (simple_map::contains_key(&proposal.votes, &m)) { + simple_map::remove(&mut proposal.votes, &m); + } + } + ); + }; + + event::emit( + UpdateConfigEvent { + multisig_addr, + members: multisig_wallet.members, + tiers: multisig_wallet.tiers, + threshold: multisig_wallet.threshold + } + ) + } + + // public functions + + public fun create_multisig_seed(name: &String): vector { + assert!( + string::length(name) <= MAX_MULTISIG_NAME_LENGTH, + error::out_of_range(EMULTISIG_NAME_TOO_LONG) + ); + + let type_name = type_info::type_name(); + let seed = *string::bytes(&type_name); + vector::append(&mut seed, *string::bytes(name)); + seed + } + + // private functions + + fun construct_members_with_tiers( + members: vector
, member_tiers: vector, tiers: vector + ): vector { + let index = 0; + vector::map( + members, + |member| { + let tier_name = *vector::borrow(&member_tiers, index); + index = index + 1; + + // find tier with tier_name in tiers + let (found, tier_index) = vector::find( + &tiers, + |t| { + let tt: &Tier = t; + tt.name == tier_name + } + ); + + assert!(found, error::invalid_argument(EINVALID_MEMBER_TIERS)); + + let tier = *vector::borrow(&tiers, tier_index); + + Member { address: member, tier: option::some(tier) } + } + ) + } + + fun get_member_by_address(members: vector, address: address): Member { + let (found, index) = vector::find( + &members, + |member| { + let m: &Member = member; + m.address == address + } + ); + + assert!(found, error::permission_denied(ENOT_MEMBER)); + + *vector::borrow(&members, index) + } + + fun create_proposal_internal( + account: &signer, + multisig_addr: address, + is_json: bool, + execute_messages: vector, + expiry_duration: Option + ) acquires MultisigWallet { + let addr = signer::address_of(account); + let multisig_wallet = borrow_global_mut(multisig_addr); + assert_multisig_member(&multisig_wallet.members, &addr); + + let (height, timestamp) = get_block_info(); + + let expiry_timestamp = + if (option::is_some(&expiry_duration)) { + let time_until_expired = *option::borrow(&expiry_duration); + option::some(timestamp + time_until_expired) + } else { + option::none() + }; + + // proposer votes yes on proposal creation + let votes = simple_map::create(); + let proposer = get_member_by_address(multisig_wallet.members, addr); + simple_map::add(&mut votes, proposer, true); + + let proposal = Proposal { + proposer, + proposed_height: height, + proposed_timestamp: timestamp, + expiry_timestamp, + threshold: multisig_wallet.threshold, + total_weight: total_weight(&multisig_wallet.members), + votes, + status: 0, // in voting period + is_json, + execute_messages + }; + + let proposal_id = table::length(&multisig_wallet.proposals) + 1; + table::add( + &mut multisig_wallet.proposals, + proposal_id, + proposal + ); + + event::emit( + CreateProposalEvent { multisig_addr, proposal_id, proposer, execute_messages } + ) + } + + fun is_proposal_expired(proposal: &Proposal): bool { + let (_, timestamp) = get_block_info(); + + if (option::is_none(&proposal.expiry_timestamp)) { + return false + }; + + let expiry = *option::borrow(&proposal.expiry_timestamp); + + return timestamp >= expiry + } + + fun vote( + votes: &mut SimpleMap, + voter: Member, + 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); + }; + } + + fun yes_vote_score( + votes: &SimpleMap, members: &vector + ): u64 { + vector::fold( + *members, + 0u64, + |acc, member| { + let m: Member = member; + let weight = + if (option::is_some(&m.tier)) { + let tier = *option::borrow(&m.tier); + tier.weight + } else { 1u64 }; + if (simple_map::contains_key(votes, &m) + && *simple_map::borrow(votes, &m)) { + acc + weight + } else { acc } + } + ) + } + + 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(proposal); + let yes_vote_score = yes_vote_score(&proposal.votes, &multisig_wallet.members); + if (status_index == 0 && is_expired) { + status_index = 2 + }; + + ProposalResponse { + multisig_addr, + proposal_id, + proposer: proposal.proposer, + proposed_height: proposal.proposed_height, + proposed_timestamp: proposal.proposed_timestamp, + expiry_timestamp: proposal.expiry_timestamp, + votes: proposal.votes, + threshold: proposal.threshold, + total_weight: proposal.total_weight, + yes_vote_score, + status: string::utf8(*vector::borrow(&STATUS, (status_index as u64))), + is_json: proposal.is_json, + execute_messages: proposal.execute_messages + } + } + + inline fun assert_uniqueness(vec: vector) { + let m = simple_map::create(); + vector::for_each(vec, |elem| simple_map::add(&mut m, elem, true)) + } + + inline fun assert_member(members: &vector
, member: &address) { + assert!( + vector::contains(members, member), + error::permission_denied(ENOT_MEMBER) + ) + } + + inline fun assert_multisig_member( + multisig_members: &vector, member: &address + ) { + let member_addresses = vector::map_ref( + multisig_members, + |multisig_member| { + let m: &Member = multisig_member; + m.address + } + ); + + assert_member(&member_addresses, member) + } + + inline fun assert_proposal(proposal: &Proposal) { + assert!( + proposal.status == 0, + error::invalid_state(EINVALID_PROPOSAL_STATUS) + ); + assert!( + !is_proposal_expired(proposal), + error::invalid_state(EPROPOSAL_EXPIRED) + ); + } + + inline fun assert_tier_config( + tiers: vector, + tier_weights: vector, + members: &vector
, + member_tiers: vector + ) { + assert!( + vector::length(&tiers) == vector::length(&tier_weights), + error::invalid_argument(EINVALID_TIERS_LENGTH) + ); + + assert!( + vector::length(members) == vector::length(&member_tiers), + error::invalid_argument(EINVALID_MEMBERS_LENGTH) + ); + + vector::for_each( + member_tiers, + |tier| assert!( + vector::contains(&tiers, &tier), + error::invalid_argument(EINVALID_MEMBER_TIERS) + ) + ); + } + + #[test_only] + use initia_std::address; + #[test_only] + use initia_std::block::set_block_info; + + #[test_only] + fun get_multisig_address(creator: &address, name: &String): address { + let seed = address::to_string(@initia_std); + string::append(&mut seed, string::utf8(b"::multisig_v2::MultisigWallet")); + string::append(&mut seed, *name); + + object::create_object_address(creator, *string::bytes(&seed)) + } + + // create test_only function for create votes map + #[test_only] + fun create_votes_map(members: vector, votes: vector): + SimpleMap { + let votes_map = simple_map::create(); + let index = 0; + vector::for_each( + members, + |member| { + let vote = *vector::borrow(&votes, index); + index = index + 1; + + simple_map::add(&mut votes_map, member, vote) + } + ); + + votes_map + } + + // view functions tests + + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + fun is_exist_test( + account1: signer, account2: signer, account3: signer + ) { + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + let name = string::utf8(b"multisig wallet"); + + assert!(!is_exist(addr1, name), 1); + + create_non_weighted_multisig_account( + &account1, name, vector[addr1, addr2, addr3], 2 + ); + + assert!(is_exist(addr1, name), 1) + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x50002, location = Self)] + fun create_non_weighted_wallet_by_other( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account4, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + } + + // test multisig wallet name too long + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + #[expected_failure(abort_code = 0x2000b, location = Self)] + fun wallet_name_too_long( + account1: signer, account2: signer, account3: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8( + b"multimultimultimultimultimultimultimultimultimultimultimultimulti" + ), // 64 letters + vector[addr1, addr2, addr3], + 2 + ); + } + + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + #[expected_failure(abort_code = 0x10001, location = Self)] + fun non_weighted_invalid_threshold( + account1: signer, account2: signer, account3: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 4 + ); + } + + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + #[expected_failure(abort_code = 0x10001, location = simple_map)] + fun non_weighted_duplicate_members( + account1: signer, account2: signer, account3: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr1, addr2, addr3], + 3 + ); + } + + // test create weight multisig wallet successfully, check keys in object + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + fun create_non_weighted_wallet_success( + account1: signer, account2: signer, account3: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 3 + ); + + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + let multisig_wallet = borrow_global(multisig_addr); + assert!( + vector::length(&multisig_wallet.members) == 3, + error::invalid_state(EINVALID_MEMBERS_LENGTH) + ); + + // assert each member tier is correct + vector::for_each_ref( + &multisig_wallet.members, + |member| { + let m: &Member = member; + assert!(option::is_none(&m.tier), 1) + } + ); + + assert!( + multisig_wallet.threshold == 3, + error::invalid_state(EINVALID_THRESHOLD) + ); + + assert!( + !multisig_wallet.weighted, + error::invalid_state(1) + ); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x50002, location = Self)] + fun create_weighted_wallet_by_other( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_weighted_multisig_account( + &account4, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2, 1], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ], + 2 + ); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x10007, location = Self)] + fun weighted_invalid_tiers_length( + account1: signer, account2: signer, account3: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ], + 2 + ); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x10008, location = Self)] + fun weighted_invalid_members_length( + account1: signer, account2: signer, account3: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2, 1], + vector[addr1, addr2, addr3], + vector[string::utf8(b"admin"), string::utf8(b"member")], + 2 + ); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x10009, location = Self)] + fun weighted_invalid_members_tiers( + account1: signer, account2: signer, account3: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2, 1], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"god") + ], + 2 + ); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x10001, location = Self)] + fun weighted_invalid_threshold( + account1: signer, account2: signer, account3: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[10, 1], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"admin"), + string::utf8(b"member") + ], + 22 + ); + } + + // test create weight multisig wallet successfully, check keys in object + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + fun create_weighted_wallet_success( + account1: signer, account2: signer, account3: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + let member_tiers = vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ]; + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2, 1], + vector[addr1, addr2, addr3], + member_tiers, + 2 + ); + + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + let multisig_wallet = borrow_global(multisig_addr); + assert!( + vector::length(&multisig_wallet.members) == 3, + error::invalid_state(EINVALID_MEMBERS_LENGTH) + ); + + // assert each member tier is correct + let index = 0; + vector::for_each_ref( + &multisig_wallet.members, + |member| { + let tier_name = *vector::borrow(&member_tiers, index); + index = index + 1; + + let m: &Member = member; + let tier = option::borrow(&m.tier); + assert!(tier_name == tier.name, 1) + } + ); + + // assert if multisig_wallet.tiers is not none and length is 2 + let tiers = option::borrow(&multisig_wallet.tiers); + assert!( + vector::length(tiers) == 2, + error::invalid_state(EINVALID_TIERS_LENGTH) + ); + + assert!( + multisig_wallet.threshold == 2, + error::invalid_state(EINVALID_THRESHOLD) + ); + + assert!( + multisig_wallet.weighted, + error::invalid_state(1) + ); + } + + // test total_weight(members) + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + fun total_weight_test( + account1: signer, account2: signer, account3: signer + ) acquires MultisigWallet { + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2, 1], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ], + 2 + ); + + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + let multisig_wallet = borrow_global(multisig_addr); + + let total_weight = total_weight(&multisig_wallet.members); + assert!(total_weight == 4, 1); + } + + #[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 + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal( + &account4, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::none() + ); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x1000c, location = Self)] + fun invalid_list_create_proposal( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal( + &account4, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2"), string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::none() + ); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + fun create_proposal_successfully( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + set_block_info(100, 100); + + create_proposal( + &account1, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + // borrow proposal from multisig wallet + let multisig_wallet = borrow_global(multisig_addr); + let proposal = table::borrow(&multisig_wallet.proposals, 1); + + let expected_votes = simple_map::create(); + simple_map::add( + &mut expected_votes, + get_member_by_address(multisig_wallet.members, addr1), + true + ); + + assert!( + proposal.proposer == get_member_by_address(multisig_wallet.members, addr1), + 1 + ); + assert!(proposal.proposed_height == 100, 1); + assert!(proposal.proposed_timestamp == 100, 1); + assert!( + *option::borrow(&proposal.expiry_timestamp) == 199, + 1 + ); + assert!(proposal.status == 0, 1); + assert!(proposal.is_json == false, 1); + + let execute_message = vector::borrow(&proposal.execute_messages, 0); + assert!(vector::length(&execute_message.json_args) == 0, 1); + assert!( + &execute_message.args + == &vector[ + 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()) + ], + 1 + ); + + assert!(vector::length(&execute_message.type_args) == 0, 1); + assert!(execute_message.module_address == @initia_std, 1); + assert!( + execute_message.module_name == string::utf8(b"multisig_v2"), + 1 + ); + assert!( + execute_message.function_name == string::utf8(b"update_config"), + 1 + ); + assert!( + proposal.threshold == multisig_wallet.threshold, + 1 + ); + assert!(proposal.total_weight == 3, 1); + assert!( + yes_vote_score(&proposal.votes, &multisig_wallet.members) == 1, + 1 + ); + } + + // test proposal_to_proposal_response for weight multisig wallet + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + fun proposal_to_proposal_response_weighted( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2, 1], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + set_block_info(100, 100); + + create_proposal( + &account1, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + let multisig_wallet = borrow_global(multisig_addr); + let proposal = table::borrow(&multisig_wallet.proposals, 1); + + let proposal_response = + proposal_to_proposal_response(multisig_wallet, multisig_addr, 1, proposal); + + let expected_proposal_response = ProposalResponse { + multisig_addr, + proposal_id: 1, + proposer: get_member_by_address(multisig_wallet.members, addr1), + proposed_height: 100, + proposed_timestamp: 100, + expiry_timestamp: option::some(199), + votes: proposal.votes, + threshold: 2, + total_weight: 4, + yes_vote_score: 2, + status: string::utf8(b"voting"), + is_json: false, + execute_messages: vector[ + ExecuteMessage { + module_address: @initia_std, + module_name: string::utf8(b"multisig_v2"), + function_name: string::utf8(b"update_config"), + type_args: vector[], + args: vector[ + 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()) + ], + json_args: vector[] + } + ] + }; + + assert!( + proposal_response == expected_proposal_response, + 1 + ); + } + + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + fun proposal_with_json( + account1: signer, account2: signer, account3: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal_with_json( + &account1, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + string::utf8(b"[\"0x101\", \"0x102\", \"0x104\"]"), + string::utf8(b"\"3\""), + string::utf8(b""), + string::utf8(b"") + ] + ], + option::some(99) + ); + + let proposal = get_proposal(multisig_addr, 1); + let execute_message = vector::borrow(&proposal.execute_messages, 0); + + assert!(execute_message.module_address == @initia_std, 0); + assert!( + execute_message.module_name == string::utf8(b"multisig_v2"), + 1 + ); + assert!( + execute_message.function_name == string::utf8(b"update_config"), + 2 + ); + assert!(execute_message.type_args == vector[], 3); + assert!( + execute_message.json_args + == vector[ + string::utf8(b"[\"0x101\", \"0x102\", \"0x104\"]"), + string::utf8(b"\"3\""), + string::utf8(b""), + string::utf8(b"") + ], + 4 + ); + assert!(execute_message.args == vector[], 5); + } + + #[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 + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + set_block_info(100, 100); + create_proposal( + &account1, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + vote_proposal(&account4, multisig_addr, 1, true); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x30004, location = Self)] + fun vote_after_proposal_expired( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + set_block_info(100, 100); + create_proposal( + &account1, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + set_block_info(100, 199); + vote_proposal(&account2, multisig_addr, 1, true); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + fun vote_proposal_of_non_weighted_multisig_successfully( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + set_block_info(100, 100); + create_proposal( + &account1, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + vote_proposal(&account1, multisig_addr, 1, true); + vote_proposal(&account2, multisig_addr, 1, false); + vote_proposal(&account3, multisig_addr, 1, true); + + let multisig_wallet = borrow_global(multisig_addr); + let proposal = table::borrow(&multisig_wallet.proposals, 1); + let proposal_response = + proposal_to_proposal_response(multisig_wallet, multisig_addr, 1, proposal); + + let expected_votes = + create_votes_map( + multisig_wallet.members, + vector[true, false, true] + ); + + assert!(proposal_response.votes == expected_votes, 1); + + assert!(proposal_response.yes_vote_score == 2, 1); + + assert!(proposal_response.total_weight == 3, 1); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + fun vote_proposal_of_weighted_multisig_successfully( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2, 1], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + set_block_info(100, 100); + create_proposal( + &account1, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + vote_proposal(&account1, multisig_addr, 1, true); + vote_proposal(&account2, multisig_addr, 1, false); + vote_proposal(&account3, multisig_addr, 1, true); + + let multisig_wallet = borrow_global(multisig_addr); + let proposal = table::borrow(&multisig_wallet.proposals, 1); + let proposal_response = + proposal_to_proposal_response(multisig_wallet, multisig_addr, 1, proposal); + + let expected_votes = + create_votes_map( + multisig_wallet.members, + vector[true, false, true] + ); + + assert!(proposal_response.votes == expected_votes, 1); + + assert!(proposal_response.yes_vote_score == 3, 1); + + assert!(proposal_response.total_weight == 4, 1); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x50002, location = Self)] + fun execute_by_others( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal( + &account1, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + vote_proposal(&account1, multisig_addr, 1, true); + vote_proposal(&account2, multisig_addr, 1, false); + vote_proposal(&account3, multisig_addr, 1, false); + + execute_proposal(&account4, multisig_addr, 1); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x10006, location = Self)] + fun execute_on_a_non_existing_proposal( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal( + &account1, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + execute_proposal(&account1, multisig_addr, 2); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x30005, location = Self)] + fun non_weighted_multisig_execute_not_pass( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal( + &account1, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + vote_proposal(&account1, multisig_addr, 1, true); + vote_proposal(&account2, multisig_addr, 1, false); + vote_proposal(&account3, multisig_addr, 1, false); + + execute_proposal(&account1, multisig_addr, 1); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x30005, location = Self)] + fun weighted_multisig_execute_not_pass( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[3, 2], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ], + 6 + ); + + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal( + &account1, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + vote_proposal(&account1, multisig_addr, 1, true); + vote_proposal(&account2, multisig_addr, 1, false); + vote_proposal(&account3, multisig_addr, 1, true); + + execute_proposal(&account1, multisig_addr, 1); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + fun execute_pass_successfully( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[3, 2], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ], + 5 + ); + + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal( + &account1, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + vote_proposal(&account1, multisig_addr, 1, true); + vote_proposal(&account2, multisig_addr, 1, false); + vote_proposal(&account3, multisig_addr, 1, true); + + execute_proposal(&account1, multisig_addr, 1); + } + + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + #[expected_failure(abort_code = 0x10001, location = simple_map)] + fun update_config_duplicate_members( + account1: signer, account2: signer, account3: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + let multisig_wallet = borrow_global(multisig_addr); + let multisig_signer = + &object::generate_signer_for_extending(&multisig_wallet.extend_ref); + + update_config( + multisig_signer, + vector[addr1, addr2, addr3, addr3], + option::none(), + option::none(), + option::none(), + 3 + ); + } + + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + #[expected_failure(abort_code = 0x10001, location = Self)] + fun update_config_non_weighted_invalid_threshold( + account1: signer, account2: signer, account3: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 4 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + let multisig_wallet = borrow_global(multisig_addr); + let multisig_signer = + &object::generate_signer_for_extending(&multisig_wallet.extend_ref); + + update_config( + multisig_signer, + vector[addr1, addr2, addr3, addr3], + option::none(), + option::none(), + option::none(), + 3 + ); + } + + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + fun update_config_non_weighted_successfully( + account1: signer, account2: signer, account3: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + set_block_info(100, 100); + + // proposal 1 : active proposal with votes from addr1, addr2, addr3 + create_proposal( + &account1, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + std::bcs::to_bytes(&vector[addr1, addr2, addr3]), std::bcs::to_bytes( + &3u64 + ), std::bcs::to_bytes(&option::none()), std::bcs::to_bytes( + &option::none() + ), std::bcs::to_bytes(&option::none()) + ] + ], + option::some(99) + ); + + // vote on proposal 1 without execution + vote_proposal(&account1, multisig_addr, 1, true); + vote_proposal(&account2, multisig_addr, 1, false); + vote_proposal(&account3, multisig_addr, 1, true); + + // proposal 2 : expired proposal with votes from addr1, addr2, addr3 + create_proposal( + &account1, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + std::bcs::to_bytes(&vector[addr1, addr2, addr3]), + std::bcs::to_bytes(&3u64), + std::bcs::to_bytes(&option::none()), + std::bcs::to_bytes(&option::none()) + ] + ], + option::some(1) + ); + + // vote on proposal 2 without execution + vote_proposal(&account1, multisig_addr, 2, false); + vote_proposal(&account2, multisig_addr, 2, false); + vote_proposal(&account3, multisig_addr, 2, true); + + // proposal 2 is now expired + set_block_info(100, 110); + + // proposal 3 : executed proposal with votes from addr1, addr2, addr3 + create_proposal( + &account1, + multisig_addr, + vector[@initia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + std::bcs::to_bytes(&vector[addr1, addr2, addr3]), + std::bcs::to_bytes(&3u64), + std::bcs::to_bytes(&option::none()), + std::bcs::to_bytes(&option::none()) + ] + ], + option::some(99) + ); + + // vote on proposal 3 with execution + vote_proposal(&account1, multisig_addr, 3, true); + vote_proposal(&account2, multisig_addr, 3, false); + vote_proposal(&account3, multisig_addr, 3, true); + execute_proposal(&account1, multisig_addr, 3); + + // update_config + let multisig_wallet = borrow_global(multisig_addr); + let multisig_signer = + &object::generate_signer_for_extending(&multisig_wallet.extend_ref); + update_config( + multisig_signer, + vector[addr2, addr3], + option::none(), + option::none(), + option::none(), + 1 + ); + + // check if multisig wallet is updated + let updated_multisig_wallet = borrow_global(multisig_addr); + assert!( + updated_multisig_wallet.members + == vector::map( + vector[addr2, addr3], + |addr| Member { address: addr, tier: option::none() } + ), + 1 + ); + assert!(updated_multisig_wallet.threshold == 1, 1); + + // proposal 1 details changed accordingly + let updated_proposal1 = get_proposal(multisig_addr, 1); + assert!(updated_proposal1.threshold == 1, 1); + assert!(updated_proposal1.total_weight == 2, 1); + assert!( + !simple_map::contains_key( + &updated_proposal1.votes, &Member { address: addr1, tier: option::none() } + ), + 1 + ); + assert!( + simple_map::contains_key( + &updated_proposal1.votes, &Member { address: addr2, tier: option::none() } + ), + 1 + ); + assert!( + simple_map::contains_key( + &updated_proposal1.votes, &Member { address: addr3, tier: option::none() } + ), + 1 + ); + + // proposal 2 (expired) details remain unchanged + let updated_proposal2 = get_proposal(multisig_addr, 2); + assert!(updated_proposal2.threshold == 2, 1); + assert!(updated_proposal2.total_weight == 3, 1); + assert!( + simple_map::contains_key( + &updated_proposal2.votes, &Member { address: addr1, tier: option::none() } + ), + 1 + ); + assert!( + simple_map::contains_key( + &updated_proposal2.votes, &Member { address: addr2, tier: option::none() } + ), + 1 + ); + assert!( + simple_map::contains_key( + &updated_proposal2.votes, &Member { address: addr3, tier: option::none() } + ), + 1 + ); + + // proposal 3 (executed) details remain unchanged + let updated_proposal3 = get_proposal(multisig_addr, 3); + assert!(updated_proposal3.threshold == 2, 1); + assert!(updated_proposal3.total_weight == 3, 1); + assert!( + simple_map::contains_key( + &updated_proposal3.votes, &Member { address: addr1, tier: option::none() } + ), + 1 + ); + assert!( + simple_map::contains_key( + &updated_proposal3.votes, &Member { address: addr2, tier: option::none() } + ), + 1 + ); + assert!( + simple_map::contains_key( + &updated_proposal3.votes, &Member { address: addr3, tier: option::none() } + ), + 1 + ); + } +} diff --git a/initia_stdlib/sources/object.move b/initia_stdlib/sources/object.move index 779e242..c503e27 100644 --- a/initia_stdlib/sources/object.move +++ b/initia_stdlib/sources/object.move @@ -261,11 +261,7 @@ module initia_std::object { ): 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 - ) + create_object_internal(creator_address, obj_addr, can_delete) } /// Create a new object by generating a random unique address based on transaction hash. @@ -274,11 +270,7 @@ module initia_std::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 - ) + create_object_internal(owner_address, unique_address, can_delete) } fun create_object_internal( @@ -663,11 +655,7 @@ module initia_std::object { public fun hero_unequip( owner: &signer, hero: Object, weapon: Object ) acquires Hero, ObjectCore { - transfer( - owner, - weapon, - signer::address_of(owner) - ); + transfer(owner, weapon, signer::address_of(owner)); let hero = borrow_global_mut(object_address(&hero)); option::extract(&mut hero.weapon); event::emit(HeroEquipEvent { weapon_id: option::none() }); diff --git a/initia_stdlib/sources/simple_map.move b/initia_stdlib/sources/simple_map.move index 6cf6275..39752f4 100644 --- a/initia_stdlib/sources/simple_map.move +++ b/initia_stdlib/sources/simple_map.move @@ -87,7 +87,9 @@ module initia_std::simple_map { value: Value ) { let maybe_idx = find(self, &key); - assert!(option::is_none(&maybe_idx), error::invalid_argument(EKEY_ALREADY_EXISTS)); + assert!( + option::is_none(&maybe_idx), error::invalid_argument(EKEY_ALREADY_EXISTS) + ); vector::push_back(&mut self.data, Element { key, value }); } diff --git a/initia_stdlib/sources/stableswap.move b/initia_stdlib/sources/stableswap.move index b0d07a0..7c5a136 100644 --- a/initia_stdlib/sources/stableswap.move +++ b/initia_stdlib/sources/stableswap.move @@ -224,11 +224,7 @@ module initia_std::stableswap { pool_obj: Object, coin_amounts: vector ): u64 acquires Pool { let (liquidity_amount, _) = - imbalance_withdraw_simulation( - pool_obj, - coin_amounts, - option::none() - ); + imbalance_withdraw_simulation(pool_obj, coin_amounts, option::none()); liquidity_amount } @@ -247,11 +243,7 @@ module initia_std::stableswap { assert!(found, error::invalid_argument(ECOIN_TYPE)); let (liquidity_amount, _) = - single_asset_withdraw_simulation( - pool_obj, - liquidity_amount, - return_index - ); + single_asset_withdraw_simulation(pool_obj, liquidity_amount, return_index); liquidity_amount } @@ -394,12 +386,7 @@ module initia_std::stableswap { }; let liquidity_token = create_pool( - creator, - name, - symbol, - swap_fee_rate, - coins, - ann + creator, name, symbol, swap_fee_rate, coins, ann ); primary_fungible_store::deposit(signer::address_of(creator), liquidity_token); } @@ -494,11 +481,7 @@ module initia_std::stableswap { max_liquidity: Option ) acquires Pool { let (liquidity_amount, fee_amounts) = - imbalance_withdraw_simulation( - pool_obj, - coin_amounts, - max_liquidity - ); + 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); @@ -555,11 +538,7 @@ module initia_std::stableswap { min_return_amount: Option ) acquires Pool { let offer_coin = - primary_fungible_store::withdraw( - account, - offer_coin_metadata, - offer_amount - ); + primary_fungible_store::withdraw(account, offer_coin_metadata, offer_amount); let return_coin = swap( pool_obj, @@ -657,11 +636,7 @@ module initia_std::stableswap { let module_store = borrow_global_mut(@initia_std); module_store.pool_count = module_store.pool_count + 1; - table::add( - &mut module_store.pools, - pool_address, - true - ); + table::add(&mut module_store.pools, pool_address, true); // emit create pool event event::emit( @@ -764,9 +739,7 @@ module initia_std::stableswap { vector::push_back( &mut return_coins, primary_fungible_store::withdraw( - &pool_signer, - coin_metadata, - return_amount + &pool_signer, coin_metadata, return_amount ) ); i = i + 1; @@ -816,11 +789,7 @@ module initia_std::stableswap { // calculate amount of returning asset let (return_amount, fee) = - single_asset_withdraw_simulation( - pool_obj, - liquidity_amount, - return_index - ); + single_asset_withdraw_simulation(pool_obj, liquidity_amount, return_index); assert!( option::is_none(&min_return_amount) || *option::borrow(&min_return_amount) <= return_amount, @@ -965,7 +934,9 @@ module initia_std::stableswap { let i = 0; while (i < len) { let metadata = vector::borrow(coin_metadata, i); - let metadata_ = fungible_asset::metadata_from_asset(vector::borrow(coins, i)); + let metadata_ = fungible_asset::metadata_from_asset( + vector::borrow(coins, i) + ); assert!( *metadata == metadata_, error::invalid_argument(ECOIN_TYPE) @@ -1164,12 +1135,7 @@ module initia_std::stableswap { ) as u64 ); - let y_without_fee = get_y_with_given_d( - pool_amounts, - return_index, - ann, - d_after - ); + 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; @@ -1363,11 +1329,11 @@ module initia_std::stableswap { 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 pool_amount_after = vector::borrow_mut( + &mut pool_amounts_after, i + ); let ideal_balance = mul_div_u64( - d_ideal, - pool_amount_before, - d_before + d_ideal, pool_amount_before, d_before ); let diff = if (ideal_balance > *pool_amount_after) { @@ -1589,12 +1555,7 @@ module initia_std::stableswap { ); let offer_coin = coin::withdraw(&chain, metadata_a, 1000000); - let return_coin = swap( - pool, - offer_coin, - metadata_b, - option::none() - ); + let return_coin = swap(pool, offer_coin, metadata_b, option::none()); let return_amount = fungible_asset::amount(&return_coin); assert!(return_amount == 999177, 3); diff --git a/initia_stdlib/sources/staking.move b/initia_stdlib/sources/staking.move index 36d8a96..beafa08 100644 --- a/initia_stdlib/sources/staking.move +++ b/initia_stdlib/sources/staking.move @@ -412,12 +412,7 @@ module initia_std::staking { let delegation_store = borrow_global(addr); let delegations = table::borrow(&delegation_store.delegations, metadata); - let delegations_iter = table::iter( - delegations, - option::none(), - start_after, - 2 - ); + let delegations_iter = table::iter(delegations, option::none(), start_after, 2); let prepare = table::prepare(delegations_iter); let res: vector = vector[]; @@ -511,12 +506,7 @@ module initia_std::staking { option::none() }; - let unbondings_iter = table::iter( - unbondings, - option::none(), - start_after, - 2 - ); + let unbondings_iter = table::iter(unbondings, option::none(), start_after, 2); let res: vector = vector[]; while (vector::length(&res) < (limit as u64) @@ -614,10 +604,7 @@ module initia_std::staking { let module_store = borrow_global_mut(@initia_std); assert!( - !table::contains( - &module_store.staking_states, - metadata - ), + !table::contains(&module_store.staking_states, metadata), error::already_exists(ESTAKING_STATE_ALREADY_EXISTS) ); table::add( @@ -649,9 +636,7 @@ module initia_std::staking { if (slash_amount > 0) { let unbonding_coin_store_signer = - &object::generate_signer_for_extending( - &state.unbonding_coin_store_ref - ); + &object::generate_signer_for_extending(&state.unbonding_coin_store_ref); let slash_coin = fungible_asset::withdraw( unbonding_coin_store_signer, @@ -665,11 +650,7 @@ module initia_std::staking { 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); } } @@ -707,7 +688,9 @@ module initia_std::staking { if (total_unbonding_amount == 0) { bigdecimal::one() } else { - bigdecimal::div_by_u64(state.unbonding_share, total_unbonding_amount) + bigdecimal::div_by_u64( + state.unbonding_share, total_unbonding_amount + ) }; let share_diff = @@ -717,10 +700,7 @@ module initia_std::staking { 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; } @@ -761,7 +741,9 @@ module initia_std::staking { ); state.reward_index = bigdecimal::add( state.reward_index, - bigdecimal::rev(bigdecimal::div_by_u64(state.total_share, reward_amount)) + bigdecimal::rev( + bigdecimal::div_by_u64(state.total_share, reward_amount) + ) ); fungible_asset::deposit(state.reward_coin_store, reward); @@ -827,10 +809,7 @@ module initia_std::staking { let metadata = fungible_asset::asset_metadata(&fa); assert!( - table::contains( - &module_store.staking_states, - metadata - ), + 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); @@ -843,16 +822,14 @@ module initia_std::staking { 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() + 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 + unbonding_coin_store_address, metadata ); table::add( @@ -918,11 +895,7 @@ module initia_std::staking { 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); @@ -945,11 +918,7 @@ module initia_std::staking { let metadata = delegation.metadata; let (unbonding_amount, release_time) = - undelegate_internal( - *string::bytes(&validator), - &metadata, - &share - ); + undelegate_internal(*string::bytes(&validator), &metadata, &share); let reward = destroy_delegation_and_extract_reward(delegation); let module_store = borrow_global_mut(@initia_std); @@ -967,11 +936,7 @@ module initia_std::staking { state.total_share = bigdecimal::sub(state.total_share, share); let unbonding_share = - unbonding_share_from_amount( - metadata, - validator, - unbonding_amount - ); + unbonding_share_from_amount(metadata, validator, unbonding_amount); let unbonding = Unbonding { metadata, validator, unbonding_share, release_time }; (reward, unbonding) @@ -1149,10 +1114,7 @@ module initia_std::staking { table::add( delegations, validator, - empty_delegation( - delegation.metadata, - delegation.validator - ) + empty_delegation(delegation.metadata, delegation.validator) ); }; @@ -1204,10 +1166,7 @@ module initia_std::staking { // If withdraw all, remove delegation if (delegation.share == share) { let delegations = - table::borrow_mut( - &mut delegation_store.delegations, - metadata - ); + table::borrow_mut(&mut delegation_store.delegations, metadata); table::remove(delegations, validator) // Else extract } else { @@ -1483,8 +1442,7 @@ module initia_std::staking { if (unbonding.unbonding_share == share) { // If withdraw all, remove unbonding let unbondings = table::borrow_mut( - &mut delegation_store.unbondings, - metadata + &mut delegation_store.unbondings, metadata ); table::remove( @@ -1660,11 +1618,7 @@ module initia_std::staking { string::utf8(b"") ); - coin::mint_to( - &mint_cap, - chain_addr, - 100000000000000 - ); + coin::mint_to(&mint_cap, chain_addr, 100000000000000); // initialize reward coin let (mint_cap, _burn_cap, _freeze_cap) = @@ -1678,11 +1632,7 @@ module initia_std::staking { string::utf8(b"") ); - coin::mint_to( - &mint_cap, - chain_addr, - 100000000000000 - ); + coin::mint_to(&mint_cap, chain_addr, 100000000000000); initialize_for_chain(chain, staking_metadata_for_test()); } @@ -1693,11 +1643,7 @@ module initia_std::staking { ) { coin::deposit( receiver, - coin::withdraw( - chain, - staking_metadata_for_test(), - amount - ) + coin::withdraw(chain, staking_metadata_for_test(), amount) ); } @@ -1886,10 +1832,7 @@ module initia_std::staking { let delegation = get_delegation(user_addr, metadata, validator); assert!(bigdecimal::truncate_u64(delegation.share) == 150000, 0); assert!(delegation.validator == validator, 1); - assert!( - coin::balance(user_addr, metadata) == 900000, - 2 - ); + assert!(coin::balance(user_addr, metadata) == 900000, 2); // withdraw delegation let delegation0 = @@ -1910,12 +1853,7 @@ module initia_std::staking { validator, bigdecimal::from_ratio_u64(50000, 1) ); - let delegations = get_delegations( - user_addr, - metadata, - option::none(), - 1 - ); + let delegations = get_delegations(user_addr, metadata, option::none(), 1); assert!(vector::length(&delegations) == 1, 4); assert!( bigdecimal::truncate_u64(vector::borrow(&delegations, 0).share) == 50000, 4 @@ -2034,10 +1972,7 @@ module initia_std::staking { 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 - ); + assert!(coin::balance(user_addr, metadata) == 900000, 2); assert!( coin::balance(user_addr, reward_metadata) == 10000, 3 @@ -2090,22 +2025,11 @@ module initia_std::staking { // deposit unbonding deposit_unbonding(user_addr, unbonding0); - let unbonding = get_unbonding( - user_addr, - metadata, - validator, - release_time - ); + let unbonding = get_unbonding(user_addr, metadata, validator, release_time); assert!(unbonding.unbonding_amount == 20000, 10); // withdraw unbonding - let unbonding = withdraw_unbonding( - user, - metadata, - validator, - release_time, - 10000 - ); + let unbonding = withdraw_unbonding(user, metadata, validator, release_time, 10000); assert!(bigdecimal::truncate_u64(unbonding.unbonding_share) == 10000, 11); // claim unbonding @@ -2115,12 +2039,7 @@ module initia_std::staking { coin::deposit(user_addr, coin); // claim unbonding with script - claim_unbonding_script( - user, - metadata, - validator, - release_time - ); + claim_unbonding_script(user, metadata, validator, release_time); assert!( coin::balance(user_addr, metadata) == 920000, 13 @@ -2427,12 +2346,7 @@ module initia_std::staking { 0 ); - let delegations = get_delegations( - user_addr, - metadata, - option::none(), - 10 - ); + let delegations = get_delegations(user_addr, metadata, option::none(), 10); assert!( delegations == vector[ @@ -2549,7 +2463,12 @@ module initia_std::staking { let metadata = staking_metadata_for_test(); let validator = vector::singleton(1u8); - set_staking_share_ratio(validator, &metadata, &bigdecimal::from_u64(100), 50u64); + set_staking_share_ratio( + validator, + &metadata, + &bigdecimal::from_u64(100), + 50u64 + ); let amount = share_to_amount( @@ -2566,7 +2485,12 @@ module initia_std::staking { let metadata = staking_metadata_for_test(); let validator = vector::singleton(1u8); - set_staking_share_ratio(validator, &metadata, &bigdecimal::from_u64(100), 50u64); + set_staking_share_ratio( + validator, + &metadata, + &bigdecimal::from_u64(100), + 50u64 + ); let share = amount_to_share(validator, &metadata, 1); assert!(bigdecimal::truncate_u64(share) == 2u64, 0); @@ -2618,9 +2542,6 @@ module initia_std::staking { validator, 10000 + 7 * 24 * 60 * 60 ); - assert!( - unbonding_response.unbonding_amount == 9000, - 1 - ); + assert!(unbonding_response.unbonding_amount == 9000, 1); } } diff --git a/initia_stdlib/sources/string_utils.move b/initia_stdlib/sources/string_utils.move index d29064e..86961cb 100644 --- a/initia_stdlib/sources/string_utils.move +++ b/initia_stdlib/sources/string_utils.move @@ -108,10 +108,7 @@ module initia_std::string_utils { #[test] fun test_format() { - assert!( - to_string(&1u64) == std::string::utf8(b"1"), - 1 - ); + assert!(to_string(&1u64) == std::string::utf8(b"1"), 1); assert!( to_string(&false) == std::string::utf8(b"false"), 2 @@ -156,7 +153,13 @@ module initia_std::string_utils { #[test] #[expected_failure(abort_code = EARGS_MISMATCH)] fun test_format_list_to_many_vals() { - format4(&b"a = {} b = {} c = {}", 1, 2, 3, 4); + format4( + &b"a = {} b = {} c = {}", + 1, + 2, + 3, + 4 + ); } #[test] @@ -188,27 +191,44 @@ module initia_std::string_utils { #[test] #[expected_failure(abort_code = EINVALID_FORMAT)] fun test_format_unclosed_braces() { - format3(&b"a = {} b = {} c = {", 1, 2, 3); + format3( + &b"a = {} b = {} c = {", + 1, + 2, + 3 + ); } #[test] #[expected_failure(abort_code = EINVALID_FORMAT)] fun test_format_unclosed_braces_2() { - format3(&b"a = {} b = { c = {}", 1, 2, 3); + format3( + &b"a = {} b = { c = {}", + 1, + 2, + 3 + ); } #[test] #[expected_failure(abort_code = EINVALID_FORMAT)] fun test_format_unopened_braces() { - format3(&b"a = } b = {} c = {}", 1, 2, 3); + format3( + &b"a = } b = {} c = {}", + 1, + 2, + 3 + ); } #[test] fun test_format_escape_braces_works() { - let s = format3(&b"{{a = {} b = {} c = {}}}", 1, 2, 3); - assert!( - s == std::string::utf8(b"{a = 1 b = 2 c = 3}"), - 1 + let s = format3( + &b"{{a = {} b = {} c = {}}}", + 1, + 2, + 3 ); + assert!(s == std::string::utf8(b"{a = 1 b = 2 c = 3}"), 1); } } diff --git a/initia_stdlib/sources/token/collection.move b/initia_stdlib/sources/token/collection.move index 0803ad1..5d2b714 100644 --- a/initia_stdlib/sources/token/collection.move +++ b/initia_stdlib/sources/token/collection.move @@ -248,10 +248,7 @@ module initia_std::collection { move_to(object_signer, collection); if (option::is_some(&supply)) { - move_to( - object_signer, - option::destroy_some(supply) - ); + move_to(object_signer, option::destroy_some(supply)); let collection_addr = signer::address_of(object_signer); event::emit( CreateCollectionEvent { @@ -415,10 +412,7 @@ module initia_std::collection { && vector::length(&res) < (limit as u64)) { let (token_id, nft) = table::next(nfts_iter); - vector::push_back( - &mut res, - NftResponse { token_id, nft: *nft } - ); + vector::push_back(&mut res, NftResponse { token_id, nft: *nft }); }; res @@ -535,7 +529,9 @@ module initia_std::collection { } #[test(creator = @0x123, receipient = @0x456)] - entry fun test_create_and_transfer(creator: &signer, receipient: &signer) { + 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); @@ -618,21 +614,9 @@ module initia_std::collection { ); 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 - ); - increment_supply( - collection, - string::utf8(b"2"), - @0x002 - ); - increment_supply( - collection, - string::utf8(b"3"), - @0x003 - ); + increment_supply(collection, string::utf8(b"1"), @0x001); + increment_supply(collection, string::utf8(b"2"), @0x002); + increment_supply(collection, string::utf8(b"3"), @0x003); let nfts = nfts(collection, option::none(), 5); assert!( diff --git a/initia_stdlib/sources/token/initia_nft.move b/initia_stdlib/sources/token/initia_nft.move index eefe1ea..ea01b62 100644 --- a/initia_stdlib/sources/token/initia_nft.move +++ b/initia_stdlib/sources/token/initia_nft.move @@ -172,11 +172,7 @@ module initia_std::initia_nft { 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)); } } @@ -598,11 +594,7 @@ module initia_std::initia_nft { fun test_set_immutable_collection_description(creator: &signer) acquires InitiaNftCollection { 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"") - ); + set_collection_description(creator, collection, string::utf8(b"")); } #[test(creator = @0x123, noncreator = @0x456)] @@ -612,11 +604,7 @@ module initia_std::initia_nft { ) 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"") - ); + set_collection_description(noncreator, collection, string::utf8(b"")); } #[test(creator = @0x123)] @@ -634,11 +622,7 @@ module initia_std::initia_nft { fun test_set_immutable_collection_uri(creator: &signer) acquires InitiaNftCollection { let collection_name = string::utf8(b"collection name"); let collection = create_collection_helper(creator, collection_name, false); - set_collection_uri( - creator, - collection, - string::utf8(b"") - ); + set_collection_uri(creator, collection, string::utf8(b"")); } #[test(creator = @0x123, noncreator = @0x456)] @@ -648,11 +632,7 @@ module initia_std::initia_nft { ) 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"") - ); + set_collection_uri(noncreator, collection, string::utf8(b"")); } #[test(creator = @0x123)] diff --git a/initia_stdlib/sources/token/nft.move b/initia_stdlib/sources/token/nft.move index bff6566..083f44c 100644 --- a/initia_stdlib/sources/token/nft.move +++ b/initia_stdlib/sources/token/nft.move @@ -391,11 +391,7 @@ module initia_std::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_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); } @@ -409,18 +405,10 @@ module initia_std::nft { 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 - ); + let nft_addr = create_nft_address(creator_address, &collection_name, &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) - ); + object::transfer(creator, nft, signer::address_of(trader)); assert!( object::owner(nft) == signer::address_of(trader), 1 @@ -466,11 +454,7 @@ module initia_std::nft { string::utf8(b"nft uri") ); - let nft_addr = create_nft_address( - creator_address, - &collection_name, - &token_id - ); + let nft_addr = create_nft_address(creator_address, &collection_name, &token_id); let nft = object::address_to_object(nft_addr); assert!( option::some(expected_royalty) == royalty(nft), @@ -501,11 +485,7 @@ module initia_std::nft { ); let creator_address = signer::address_of(creator); - let nft_addr = create_nft_address( - creator_address, - &collection_name, - &token_id - ); + let nft_addr = create_nft_address(creator_address, &collection_name, &token_id); let nft = object::address_to_object(nft_addr); assert!(option::none() == royalty(nft), 0); } @@ -548,7 +528,9 @@ module initia_std::nft { let token_id = string::utf8(b"nft token_id"); create_collection_helper(creator, collection_name, 1); - let mutator_ref = create_nft_with_mutation_ref(creator, collection_name, token_id); + let mutator_ref = create_nft_with_mutation_ref( + creator, collection_name, token_id + ); let nft = object::address_to_object( create_nft_address( @@ -570,7 +552,9 @@ module initia_std::nft { let token_id = string::utf8(b"nft token_id"); create_collection_helper(creator, collection_name, 1); - let mutator_ref = create_nft_with_mutation_ref(creator, collection_name, token_id); + let mutator_ref = create_nft_with_mutation_ref( + creator, collection_name, token_id + ); let nft = object::address_to_object( create_nft_address( diff --git a/initia_stdlib/sources/token/property_map.move b/initia_stdlib/sources/token/property_map.move index 97c4c60..c5c8b28 100644 --- a/initia_stdlib/sources/token/property_map.move +++ b/initia_stdlib/sources/token/property_map.move @@ -439,10 +439,7 @@ module initia_std::property_map { 6 ); assert!( - read_bytes( - object, - &string::utf8(b"vector") - ) == vector[0x01], + read_bytes(object, &string::utf8(b"vector")) == vector[0x01], 7 ); assert!( @@ -455,37 +452,13 @@ module initia_std::property_map { assert!(length(object) == 9, 9); - update_typed( - &mutator, - &string::utf8(b"bool"), - false - ); + update_typed(&mutator, &string::utf8(b"bool"), false); update_typed(&mutator, &string::utf8(b"u8"), 0x21); - update_typed( - &mutator, - &string::utf8(b"u16"), - 0x22 - ); - update_typed( - &mutator, - &string::utf8(b"u32"), - 0x23 - ); - update_typed( - &mutator, - &string::utf8(b"u64"), - 0x24 - ); - update_typed( - &mutator, - &string::utf8(b"u128"), - 0x25 - ); - update_typed( - &mutator, - &string::utf8(b"u256"), - 0x26 - ); + update_typed(&mutator, &string::utf8(b"u16"), 0x22); + update_typed(&mutator, &string::utf8(b"u32"), 0x23); + update_typed(&mutator, &string::utf8(b"u64"), 0x24); + update_typed(&mutator, &string::utf8(b"u128"), 0x25); + update_typed(&mutator, &string::utf8(b"u256"), 0x26); update_typed>( &mutator, &string::utf8(b"vector"), @@ -526,10 +499,7 @@ module initia_std::property_map { 16 ); assert!( - read_bytes( - object, - &string::utf8(b"vector") - ) == vector[0x02], + read_bytes(object, &string::utf8(b"vector")) == vector[0x02], 17 ); assert!( @@ -557,25 +527,13 @@ module initia_std::property_map { assert!(length(object) == 0, 20); - add_typed( - &mutator, - string::utf8(b"bool"), - false - ); + add_typed(&mutator, string::utf8(b"bool"), false); add_typed(&mutator, string::utf8(b"u8"), 0x21); add_typed(&mutator, string::utf8(b"u16"), 0x22); add_typed(&mutator, string::utf8(b"u32"), 0x23); add_typed(&mutator, string::utf8(b"u64"), 0x24); - add_typed( - &mutator, - string::utf8(b"u128"), - 0x25 - ); - add_typed( - &mutator, - string::utf8(b"u256"), - 0x26 - ); + add_typed(&mutator, string::utf8(b"u128"), 0x25); + add_typed(&mutator, string::utf8(b"u256"), 0x26); add_typed>( &mutator, string::utf8(b"vector"), @@ -616,10 +574,7 @@ module initia_std::property_map { 27 ); assert!( - read_bytes( - object, - &string::utf8(b"vector") - ) == vector[0x02], + read_bytes(object, &string::utf8(b"vector")) == vector[0x02], 28 ); assert!( @@ -732,10 +687,7 @@ module initia_std::property_map { 38 ); assert!( - read_bytes( - object, - &string::utf8(b"vector") - ) == vector[0x01], + read_bytes(object, &string::utf8(b"vector")) == vector[0x01], 39 ); assert!( @@ -832,10 +784,7 @@ module initia_std::property_map { 16 ); assert!( - read_bytes( - object, - &string::utf8(b"vector") - ) == vector[0x02], + read_bytes(object, &string::utf8(b"vector")) == vector[0x02], 17 ); assert!( diff --git a/initia_stdlib/sources/token/royalty.move b/initia_stdlib/sources/token/royalty.move index c9ced8f..3a23d3c 100644 --- a/initia_stdlib/sources/token/royalty.move +++ b/initia_stdlib/sources/token/royalty.move @@ -117,10 +117,7 @@ module initia_std::royalty { generate_mutator_ref(object::generate_extend_ref(&constructor_ref)); let update_royalty = create(bigdecimal::from_ratio_u64(2, 5), @0x456); update(&mutator_ref, update_royalty); - assert!( - option::some(update_royalty) == get(object), - 3 - ); + assert!(option::some(update_royalty) == get(object), 3); assert!( royalty(&update_royalty) == bigdecimal::from_ratio_u64(2, 5), 4 @@ -139,10 +136,7 @@ module initia_std::royalty { generate_mutator_ref(object::generate_extend_ref(&constructor_ref)); let update_royalty = create(bigdecimal::from_ratio_u64(1, 5), @0x123); update(&mutator_ref, update_royalty); - assert!( - option::some(update_royalty) == get(object), - 1 - ); + assert!(option::some(update_royalty) == get(object), 1); } #[test] diff --git a/initia_stdlib/sources/token/simple_nft.move b/initia_stdlib/sources/token/simple_nft.move index 66c8e9f..ff933ba 100644 --- a/initia_stdlib/sources/token/simple_nft.move +++ b/initia_stdlib/sources/token/simple_nft.move @@ -126,11 +126,7 @@ module initia_std::simple_nft { 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)); } } @@ -315,11 +311,7 @@ module initia_std::simple_nft { error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); - property_map::update_typed( - &simple_nft.property_mutator_ref, - &key, - value - ); + property_map::update_typed(&simple_nft.property_mutator_ref, &key, value); } // Collection accessors diff --git a/initia_stdlib/sources/token/soul_bound_token.move b/initia_stdlib/sources/token/soul_bound_token.move index 68c957d..813b0b8 100644 --- a/initia_stdlib/sources/token/soul_bound_token.move +++ b/initia_stdlib/sources/token/soul_bound_token.move @@ -567,12 +567,7 @@ module initia_std::soul_bound_token { let nft_name = string::utf8(b"nft name"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); let description = string::utf8(b"not"); assert!(nft::description(nft) != description, 0); @@ -589,12 +584,7 @@ module initia_std::soul_bound_token { let nft_name = string::utf8(b"nft name"); create_collection_helper(creator, collection_name, false); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); set_description(creator, nft, string::utf8(b"")); } @@ -608,12 +598,7 @@ module initia_std::soul_bound_token { let nft_name = string::utf8(b"nft name"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); let description = string::utf8(b"not"); set_description(noncreator, nft, description); @@ -625,12 +610,7 @@ module initia_std::soul_bound_token { let nft_name = string::utf8(b"nft name"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); let uri = string::utf8(b"not"); assert!(nft::uri(nft) != uri, 0); @@ -645,12 +625,7 @@ module initia_std::soul_bound_token { let nft_name = string::utf8(b"nft name"); create_collection_helper(creator, collection_name, false); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); set_uri(creator, nft, string::utf8(b"")); } @@ -664,12 +639,7 @@ module initia_std::soul_bound_token { let nft_name = string::utf8(b"nft name"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); let uri = string::utf8(b"not"); set_uri(noncreator, nft, uri); @@ -698,11 +668,7 @@ module initia_std::soul_bound_token { ) 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"") - ); + set_collection_description(creator, collection, string::utf8(b"")); } #[test(creator = @0x123, noncreator = @0x456)] @@ -712,11 +678,7 @@ module initia_std::soul_bound_token { ) 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"") - ); + set_collection_description(noncreator, collection, string::utf8(b"")); } #[test(creator = @0x123)] @@ -734,11 +696,7 @@ module initia_std::soul_bound_token { fun test_set_immutable_collection_uri(creator: &signer) acquires SoulBoundTokenCollection { let collection_name = string::utf8(b"collection name"); let collection = create_collection_helper(creator, collection_name, false); - set_collection_uri( - creator, - collection, - string::utf8(b"") - ); + set_collection_uri(creator, collection, string::utf8(b"")); } #[test(creator = @0x123, noncreator = @0x456)] @@ -748,11 +706,7 @@ module initia_std::soul_bound_token { ) 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"") - ); + set_collection_uri(noncreator, collection, string::utf8(b"")); } #[test(creator = @0x123)] @@ -763,12 +717,7 @@ module initia_std::soul_bound_token { let property_type = string::utf8(b"u8"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); add_property( creator, nft, @@ -790,12 +739,7 @@ module initia_std::soul_bound_token { let property_name = string::utf8(b"u8"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); add_typed_property(creator, nft, property_name, 0x8); assert!( @@ -812,12 +756,7 @@ module initia_std::soul_bound_token { let property_type = string::utf8(b"bool"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); update_property( creator, nft, @@ -841,12 +780,7 @@ module initia_std::soul_bound_token { let property_name = string::utf8(b"bool"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); update_typed_property(creator, nft, property_name, false); assert!( @@ -862,12 +796,7 @@ module initia_std::soul_bound_token { let property_name = string::utf8(b"bool"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); remove_property(creator, nft, property_name); } @@ -877,12 +806,7 @@ module initia_std::soul_bound_token { let nft_name = string::utf8(b"nft name"); let collection = create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); let royalty_before = option::extract(&mut nft::royalty(nft)); set_collection_royalties_call( diff --git a/initia_stdlib/sources/transaction_context.move b/initia_stdlib/sources/transaction_context.move index 34268c7..8544333 100644 --- a/initia_stdlib/sources/transaction_context.move +++ b/initia_stdlib/sources/transaction_context.move @@ -33,10 +33,7 @@ module initia_std::transaction_context { let count: u64 = 50; while (i < count) { i = i + 1; - vector::push_back( - &mut addrs, - generate_unique_address() - ); + vector::push_back(&mut addrs, generate_unique_address()); }; i = 0; diff --git a/initia_stdlib/tests/deflation_token_tests.move b/initia_stdlib/tests/deflation_token_tests.move index 8a5621a..9b3b8c8 100644 --- a/initia_stdlib/tests/deflation_token_tests.move +++ b/initia_stdlib/tests/deflation_token_tests.move @@ -333,7 +333,10 @@ module 0xcafe::deflation_token_tests { assert!(primary_fungible_store::balance(aaron_address, metadata) == 69, 4); primary_fungible_store::transfer_with_ref( - &transfer_ref, aaron_address, creator_address, 20 + &transfer_ref, + aaron_address, + creator_address, + 20 ); assert!(primary_fungible_store::balance(creator_address, metadata) == 42, 3); diff --git a/initia_stdlib/tests/simple_dispatchable_token_pfs_tests.move b/initia_stdlib/tests/simple_dispatchable_token_pfs_tests.move index 9cc836c..a6e9c22 100644 --- a/initia_stdlib/tests/simple_dispatchable_token_pfs_tests.move +++ b/initia_stdlib/tests/simple_dispatchable_token_pfs_tests.move @@ -62,7 +62,12 @@ module initia_std::simple_token_pfs_tests { assert!(is_frozen(aaron_address, metadata), 5); let fa = withdraw_with_ref(&transfer_ref, aaron_address, 30); deposit_with_ref(&transfer_ref, aaron_address, fa); - transfer_with_ref(&transfer_ref, aaron_address, creator_address, 20); + transfer_with_ref( + &transfer_ref, + aaron_address, + creator_address, + 20 + ); set_frozen_flag(&transfer_ref, aaron_address, false); assert!(!is_frozen(aaron_address, metadata), 6); burn(&burn_ref, aaron_address, 50); diff --git a/initia_stdlib/tests/ten_x_token_tests.move b/initia_stdlib/tests/ten_x_token_tests.move index 329f984..7792176 100644 --- a/initia_stdlib/tests/ten_x_token_tests.move +++ b/initia_stdlib/tests/ten_x_token_tests.move @@ -31,7 +31,8 @@ module initia_std::ten_x_token_tests { // The derived supply is 10x assert!( - dispatchable_fungible_asset::derived_supply(metadata) == option::some(1000), 5 + dispatchable_fungible_asset::derived_supply(metadata) == option::some(1000), + 5 ); } } diff --git a/minitia_stdlib/doc/account.md b/minitia_stdlib/doc/account.md index 43802ef..999c060 100644 --- a/minitia_stdlib/doc/account.md +++ b/minitia_stdlib/doc/account.md @@ -211,11 +211,7 @@ as both cannot have a pubkey, there is no way to use the account externally. error::already_exists(EACCOUNT_ALREADY_EXISTS) ); - request_create_account( - addr, - account_number, - ACCOUNT_TYPE_TABLE - ) + request_create_account(addr, account_number, ACCOUNT_TYPE_TABLE) } @@ -242,11 +238,7 @@ as both cannot have a pubkey, there is no way to use the account externally. // 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 - ) + 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, diff --git a/minitia_stdlib/doc/bigdecimal.md b/minitia_stdlib/doc/bigdecimal.md index 1c35a5e..5de3e7d 100644 --- a/minitia_stdlib/doc/bigdecimal.md +++ b/minitia_stdlib/doc/bigdecimal.md @@ -337,7 +337,8 @@ Create a BigDecimal from a scaled BigUint le_bytes value.
public fun from_ratio(numerator: BigUint, denominator: BigUint): BigDecimal {
     assert!(
-        !biguint::is_zero(denominator), error::invalid_argument(EDIVISION_BY_ZERO)
+        !biguint::is_zero(denominator),
+        error::invalid_argument(EDIVISION_BY_ZERO)
     );
 
     let numerator = biguint::mul(numerator, f());
@@ -1093,7 +1094,8 @@ Create a BigDecimal from a scaled BigUint le_bytes value.
 
 
public fun div(num1: BigDecimal, num2: BigDecimal): BigDecimal {
     assert!(
-        !biguint::is_zero(num2.scaled), error::invalid_argument(EDIVISION_BY_ZERO)
+        !biguint::is_zero(num2.scaled),
+        error::invalid_argument(EDIVISION_BY_ZERO)
     );
 
     BigDecimal {
diff --git a/minitia_stdlib/doc/code.md b/minitia_stdlib/doc/code.md
index c28aa4c..e8afb95 100644
--- a/minitia_stdlib/doc/code.md
+++ b/minitia_stdlib/doc/code.md
@@ -349,6 +349,7 @@ strengthened but not weakened.
         signer::address_of(chain) == @minitia_std,
         error::permission_denied(EINVALID_CHAIN_OPERATOR)
     );
+    assert_no_duplication(&module_ids);
 
     let metadata_table = table::new<String, ModuleMetadata>();
     vector::for_each_ref(
@@ -433,7 +434,10 @@ strengthened but not weakened.
 
     let registry = borrow_global_mut<MetadataStore>(code_object_addr);
     let iter = table::iter_mut(
-        &mut registry.metadata, option::none(), option::none(), 1
+        &mut registry.metadata,
+        option::none(),
+        option::none(),
+        1
     );
     loop {
         if (!table::prepare_mut(iter)) { break };
@@ -473,23 +477,7 @@ package.
         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
-            );
-        }
-    );
+    assert_no_duplication(&module_ids);
 
     // Check whether arbitrary publish is allowed or not.
     let module_store = borrow_global_mut<ModuleStore>(@minitia_std);
@@ -503,13 +491,11 @@ package.
     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 new_modules = 0;
     let metadata_table = &mut borrow_global_mut<MetadataStore>(addr).metadata;
     vector::for_each_ref(
         &module_ids,
@@ -525,8 +511,7 @@ package.
                 );
                 assert!(
                     can_change_upgrade_policy_to(
-                        metadata.upgrade_policy,
-                        upgrade_policy
+                        metadata.upgrade_policy, upgrade_policy
                     ),
                     error::invalid_argument(EUPGRADE_WEAKER_POLICY)
                 );
@@ -538,6 +523,7 @@ package.
                     *module_id,
                     ModuleMetadata { upgrade_policy }
                 );
+                new_modules = new_modules + 1;
             };
 
             event::emit(
@@ -546,8 +532,11 @@ package.
         }
     );
 
+    if (new_modules > 0) {
+        increase_total_modules(new_modules)
+    };
+
     // Request publish
-    increase_total_modules(vector::length(&module_ids));
     request_publish(addr, module_ids, code)
 }
 
diff --git a/minitia_stdlib/doc/coin.md b/minitia_stdlib/doc/coin.md index 02d905f..0650b3a 100644 --- a/minitia_stdlib/doc/coin.md +++ b/minitia_stdlib/doc/coin.md @@ -11,6 +11,7 @@ TODO - make is_module_account or some blacklist from freeze. - [Struct `MintCapability`](#0x1_coin_MintCapability) - [Struct `BurnCapability`](#0x1_coin_BurnCapability) - [Struct `FreezeCapability`](#0x1_coin_FreezeCapability) +- [Struct `Coin`](#0x1_coin_Coin) - [Constants](#@Constants_0) - [Function `sudo_transfer`](#0x1_coin_sudo_transfer) - [Function `sudo_deposit`](#0x1_coin_sudo_deposit) @@ -188,6 +189,30 @@ TODO - make is_module_account or some blacklist from freeze. + + +## Struct `Coin` + + + +
struct Coin<CoinType>
+
+ + + +##### Fields + + +
+
+dummy_field: bool +
+
+ +
+
+ + ## Constants @@ -339,10 +364,7 @@ Only fungible asset metadata owner can make changes. ): (MintCapability, BurnCapability, FreezeCapability, ExtendRef) { // create object for fungible asset metadata let constructor_ref = - &object::create_named_object( - creator, - *string::bytes(&symbol) - ); + &object::create_named_object(creator, *string::bytes(&symbol)); primary_fungible_store::create_primary_store_enabled_fungible_asset( constructor_ref, @@ -571,11 +593,7 @@ Freeze the primary store of an account. ); 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) }
@@ -608,11 +626,7 @@ Unfreeze the primary store of an account. ); 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) } diff --git a/minitia_stdlib/doc/collection.md b/minitia_stdlib/doc/collection.md index 4949e3b..108c7f8 100644 --- a/minitia_stdlib/doc/collection.md +++ b/minitia_stdlib/doc/collection.md @@ -906,10 +906,7 @@ if start_after is not none, seach nfts in range (start_after, ...] && 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 } - ); + vector::push_back(&mut res, NftResponse { token_id, nft: *nft }); }; res diff --git a/minitia_stdlib/doc/cosmos.md b/minitia_stdlib/doc/cosmos.md index 689c9ba..b4eed82 100644 --- a/minitia_stdlib/doc/cosmos.md +++ b/minitia_stdlib/doc/cosmos.md @@ -322,11 +322,7 @@ execution after the move execution finished.
public entry fun fund_community_pool(
     sender: &signer, metadata: Object<Metadata>, amount: u64
 ) {
-    fund_community_pool_internal(
-        signer::address_of(sender),
-        &metadata,
-        amount
-    )
+    fund_community_pool_internal(signer::address_of(sender), &metadata, amount)
 }
 
diff --git a/minitia_stdlib/doc/dex.md b/minitia_stdlib/doc/dex.md index 3022e9a..b8efe0f 100644 --- a/minitia_stdlib/doc/dex.md +++ b/minitia_stdlib/doc/dex.md @@ -34,6 +34,8 @@ - [Function `get_swap_simulation_by_denom`](#0x1_dex_get_swap_simulation_by_denom) - [Function `get_swap_simulation_given_out`](#0x1_dex_get_swap_simulation_given_out) - [Function `get_swap_simulation_given_out_by_denom`](#0x1_dex_get_swap_simulation_given_out_by_denom) +- [Function `get_provide_simulation`](#0x1_dex_get_provide_simulation) +- [Function `get_single_asset_provide_simulation`](#0x1_dex_get_single_asset_provide_simulation) - [Function `get_pool_info`](#0x1_dex_get_pool_info) - [Function `get_pool_info_by_denom`](#0x1_dex_get_pool_info_by_denom) - [Function `get_config`](#0x1_dex_get_config) @@ -1377,6 +1379,67 @@ Return swap simulation result + + +## Function `get_provide_simulation` + + + +
#[view]
+public fun get_provide_simulation(pair: object::Object<dex::Config>, coin_a_amount_in: u64, coin_b_amount_in: u64): u64
+
+ + + +##### Implementation + + +
public fun get_provide_simulation(
+    pair: Object<Config>, 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>(pool_addr);
+
+    calculate_provide_liquidity_return_amount(
+        pool, pair, coin_a_amount_in, coin_b_amount_in
+    )
+}
+
+ + + + + +## Function `get_single_asset_provide_simulation` + + + +
#[view]
+public fun get_single_asset_provide_simulation(pair: object::Object<dex::Config>, offer_asset_metadata: object::Object<fungible_asset::Metadata>, amount_in: u64): u64
+
+ + + +##### Implementation + + +
public fun get_single_asset_provide_simulation(
+    pair: Object<Config>, offer_asset_metadata: Object<Metadata>, amount_in: u64
+): u64 acquires Config, Pool {
+    let pair_addr = object::object_address(&pair);
+    let pool = borrow_global<Pool>(pair_addr);
+
+    let (liquidity_amount, _, _) =
+        calculate_single_asset_provide_liquidity_return_amount(
+            pool, pair, offer_asset_metadata, amount_in
+        );
+
+    liquidity_amount
+}
+
+ + + ## Function `get_pool_info` @@ -1571,7 +1634,9 @@ get config 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 { @@ -2046,16 +2111,8 @@ get config 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( @@ -2128,16 +2185,8 @@ only LP struct owner can initialize } }; - 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( @@ -2391,18 +2440,12 @@ Swap with the coin in the coin store offer_coin_amount: 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 - ), + || *option::borrow(&min_return) <= fungible_asset::amount(&return_coin), error::invalid_state(EMIN_RETURN) ); @@ -2560,86 +2603,24 @@ CONTRACT: not allow until LBP is ended min_liquidity_amount: Option<u64> ): FungibleAsset acquires Config, CoinCapabilities, Pool { 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 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<Pool>(pair_addr); - 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); - - (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 = - 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 + 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 = - 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); + let pair_key = generate_pair_key(pair); // check min liquidity assertion assert!( @@ -2653,9 +2634,9 @@ CONTRACT: not allow until LBP is ended 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 } @@ -2732,18 +2713,10 @@ Swap directly 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 - ) + 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 - ) + fungible_asset::withdraw(pair_signer, pool.coin_a_store, return_amount) }; // emit events @@ -2828,10 +2801,7 @@ Swap directly 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 } - ); + move_to(pair_signer, Pool { coin_a_store, coin_b_store }); move_to( pair_signer, @@ -2942,33 +2912,12 @@ CONTRACT: not allow until LBP is ended 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 = - 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 - ) - } - }; + calculate_provide_liquidity_return_amount( + pool, pair, coin_a_amount_in, coin_b_amount_in + ); assert!( option::is_none(&min_liquidity_amount) diff --git a/minitia_stdlib/doc/dispatchable_fungible_asset.md b/minitia_stdlib/doc/dispatchable_fungible_asset.md index d5d9ac2..04e1caa 100644 --- a/minitia_stdlib/doc/dispatchable_fungible_asset.md +++ b/minitia_stdlib/doc/dispatchable_fungible_asset.md @@ -242,12 +242,7 @@ The semantics of deposit will be governed by the function specified in DispatchF 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 - ) + dispatchable_deposit(store, fa, borrow_transfer_ref(store), func) } else { fungible_asset::deposit_internal(object::object_address(&store), fa) } @@ -313,7 +308,10 @@ Note: it does not move the underlying object. let fa = withdraw(sender, from, amount); deposit(to, fa); let end = fungible_asset::balance(to); - assert!(end - start >= expected, error::aborted(EAMOUNT_MISMATCH)); + assert!( + end - start >= expected, + error::aborted(EAMOUNT_MISMATCH) + ); } diff --git a/minitia_stdlib/doc/ed25519.md b/minitia_stdlib/doc/ed25519.md index 21787aa..84d3fcf 100644 --- a/minitia_stdlib/doc/ed25519.md +++ b/minitia_stdlib/doc/ed25519.md @@ -243,11 +243,7 @@ Verifies a Ed25519 signature under an public_key on th
public fun verify(
     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)
 }
 
diff --git a/minitia_stdlib/doc/fixed_point64.md b/minitia_stdlib/doc/fixed_point64.md index 9da9a36..7c7ee5e 100644 --- a/minitia_stdlib/doc/fixed_point64.md +++ b/minitia_stdlib/doc/fixed_point64.md @@ -613,7 +613,10 @@ rounding, e.g., 0.0125 will round down to 0.012 instead of up to 0.013. 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); diff --git a/minitia_stdlib/doc/fungible_asset.md b/minitia_stdlib/doc/fungible_asset.md index df55d5d..e45cb39 100644 --- a/minitia_stdlib/doc/fungible_asset.md +++ b/minitia_stdlib/doc/fungible_asset.md @@ -1172,8 +1172,7 @@ Define the derived supply dispatch with the provided function. // 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 + &function_info, supply_function ), error::invalid_argument( EDERIVED_SUPPLY_FUNCTION_SIGNATURE_MISMATCH diff --git a/minitia_stdlib/doc/initia_nft.md b/minitia_stdlib/doc/initia_nft.md index 1985614..bf5f709 100644 --- a/minitia_stdlib/doc/initia_nft.md +++ b/minitia_stdlib/doc/initia_nft.md @@ -181,22 +181,22 @@ The provided signer is not the creator - + -The NFT is not allowed to burn +The provided signer is not the owner -
const ECAN_NOT_BURN: u64 = 6;
+
const ENOT_OWNER: u64 = 5;
 
- + -The provided signer is not the owner +The NFT is not allowed to burn -
const ENOT_OWNER: u64 = 5;
+
const ECAN_NOT_BURN: u64 = 6;
 
@@ -366,11 +366,7 @@ With an existing collection, directly mint a viable nft into the creators accoun 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)); } }
diff --git a/minitia_stdlib/doc/json.md b/minitia_stdlib/doc/json.md index 9d4de2a..59d0ff2 100644 --- a/minitia_stdlib/doc/json.md +++ b/minitia_stdlib/doc/json.md @@ -5,12 +5,228 @@ +- [Struct `JSONValue`](#0x1_json_JSONValue) +- [Struct `JSONObject`](#0x1_json_JSONObject) +- [Struct `Element`](#0x1_json_Element) +- [Function `unmarshal_json_value`](#0x1_json_unmarshal_json_value) +- [Function `keys`](#0x1_json_keys) +- [Function `get_elem`](#0x1_json_get_elem) +- [Function `set_elem`](#0x1_json_set_elem) - [Function `marshal`](#0x1_json_marshal) - [Function `marshal_to_string`](#0x1_json_marshal_to_string) - [Function `unmarshal`](#0x1_json_unmarshal) -
use 0x1::string;
+
use 0x1::option;
+use 0x1::string;
+
+ + + + + +## Struct `JSONValue` + +JSONValue is a struct to hold any JSON value which is unknown at compile time. + + +
struct JSONValue has copy, drop
+
+ + + +##### Fields + + +
+
+value: vector<u8> +
+
+ +
+
+ + + + +## Struct `JSONObject` + +JSONObject is a struct to hold any json object which is unknown at compile time. + + +
struct JSONObject has copy, drop
+
+ + + +##### Fields + + +
+
+elems: vector<json::Element> +
+
+ +
+
+ + + + +## Struct `Element` + +Element is a struct to hold key-value pair in JSON object. + + +
struct Element has copy, drop
+
+ + + +##### Fields + + +
+
+key: vector<u8> +
+
+ +
+
+value: vector<u8> +
+
+ +
+
+ + + + +## Function `unmarshal_json_value` + +Unmarshal JSON value to the given type. + + +
public fun unmarshal_json_value<T: drop>(json_value: json::JSONValue): T
+
+ + + +##### Implementation + + +
public fun unmarshal_json_value<T: drop>(json_value: JSONValue): T {
+    unmarshal(json_value.value)
+}
+
+ + + + + +## Function `keys` + +Get the list of keys from the JSON object. + + +
public fun keys(obj: &json::JSONObject): vector<string::String>
+
+ + + +##### Implementation + + +
public fun keys(obj: &JSONObject): vector<String> {
+    vector::map_ref(
+        &obj.elems,
+        |elem| {
+            use_elem(elem);
+            string::utf8(elem.key)
+        }
+    )
+}
+
+ + + + + +## Function `get_elem` + +Get the value of the given key from the JSON object. + + +
public fun get_elem<T: drop>(obj: &json::JSONObject, key: string::String): option::Option<T>
+
+ + + +##### Implementation + + +
public fun get_elem<T: drop>(obj: &JSONObject, key: String): Option<T> {
+    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<T>(elem.value))
+}
+
+ + + + + +## Function `set_elem` + +Set or overwrite the element in the JSON object. + + +
public fun set_elem<T: drop>(obj: &mut json::JSONObject, key: string::String, value: &T)
+
+ + + +##### Implementation + + +
public fun set_elem<T: drop>(
+    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);
+    }
+}
 
diff --git a/minitia_stdlib/doc/multisig.md b/minitia_stdlib/doc/multisig.md index 0a881a7..e035a82 100644 --- a/minitia_stdlib/doc/multisig.md +++ b/minitia_stdlib/doc/multisig.md @@ -992,10 +992,7 @@ Vote proposal assert_member(&multisig_wallet.members, &voter); assert!( - table::contains( - &multisig_wallet.proposals, - proposal_id - ), + table::contains(&multisig_wallet.proposals, proposal_id), error::invalid_argument(EPROPOSAL_NOT_FOUND) ); let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id); @@ -1036,10 +1033,7 @@ Execute proposal assert_member(&multisig_wallet.members, &executor); assert!( - table::contains( - &multisig_wallet.proposals, - proposal_id - ), + table::contains(&multisig_wallet.proposals, proposal_id), error::invalid_argument(EPROPOSAL_NOT_FOUND) ); let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id); @@ -1049,10 +1043,8 @@ Execute proposal // check passed assert!( - yes_vote_count( - &proposal.votes, - &multisig_wallet.members - ) >= multisig_wallet.threshold, + yes_vote_count(&proposal.votes, &multisig_wallet.members) + >= multisig_wallet.threshold, error::invalid_state(ENOT_PASS) ); diff --git a/minitia_stdlib/doc/nft.md b/minitia_stdlib/doc/nft.md index 0216b6b..58b733f 100644 --- a/minitia_stdlib/doc/nft.md +++ b/minitia_stdlib/doc/nft.md @@ -328,6 +328,16 @@ The provided signer is not the creator + + +The calling signer is not the owner + + +
const ENOT_OWNER: u64 = 10;
+
+ + + The query length is over the maximum length @@ -364,7 +374,7 @@ Creates a new nft object from a nft name and returns the ConstructorRef for additional specialization. -
public fun create(creator: &signer, collection_name: string::String, description: string::String, token_id: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
+
public fun create(owner: &signer, collection: object::Object<collection::Collection>, description: string::String, token_id: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
 
@@ -373,21 +383,24 @@ additional specialization.
public fun create(
-    creator: &signer,
-    collection_name: String,
+    owner: &signer,
+    collection: Object<Collection>,
     description: String,
     token_id: String,
     royalty: Option<Royalty>,
     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,
diff --git a/minitia_stdlib/doc/object.md b/minitia_stdlib/doc/object.md
index 94710a9..438abc3 100644
--- a/minitia_stdlib/doc/object.md
+++ b/minitia_stdlib/doc/object.md
@@ -43,6 +43,7 @@ make it so that a reference to a global object can be returned from a function.
 -  [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_nft_object`](#0x1_object_create_nft_object)
 -  [Function `create_user_derived_object`](#0x1_object_create_user_derived_object)
 -  [Function `create_object`](#0x1_object_create_object)
 -  [Function `generate_delete_ref`](#0x1_object_generate_delete_ref)
@@ -858,6 +859,33 @@ Named objects can be queried globally by knowing the user generated seed used to
 
 
 
+
+
+## Function `create_nft_object`
+
+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<u8>): object::ConstructorRef
+
+ + + +##### Implementation + + +
public(friend) fun create_nft_object(
+    owner: address, creator: address, seed: vector<u8>
+): ConstructorRef acquires Tombstone {
+    let obj_addr = create_object_address(&creator, seed);
+    create_object_internal(owner, obj_addr, true)
+}
+
+ + + ## Function `create_user_derived_object` @@ -879,11 +907,7 @@ Derivde objects, similar to named objects, cannot be deleted. ): 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 - ) + create_object_internal(creator_address, obj_addr, can_delete) }
@@ -909,11 +933,7 @@ The unique address is computed sha3_256([transaction hash | auid counter | 0xFB] 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 - ) + create_object_internal(owner_address, unique_address, can_delete) }
diff --git a/minitia_stdlib/doc/primary_fungible_store.md b/minitia_stdlib/doc/primary_fungible_store.md index e6d87c9..c751789 100644 --- a/minitia_stdlib/doc/primary_fungible_store.md +++ b/minitia_stdlib/doc/primary_fungible_store.md @@ -274,10 +274,7 @@ Create a primary store object to hold fungible asset for the given address. // 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 - )) { + if (!table::contains(&module_store.user_stores, owner_addr)) { table::add( &mut module_store.user_stores, owner_addr, @@ -285,12 +282,10 @@ Create a primary store object to hold fungible asset for the given address. ); }; - 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 ); + table::add(user_stores, metadata_addr, store_addr); }; // emit store created event @@ -475,12 +470,7 @@ Get the balances of account's ): (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 - ); + let iter = table::iter(account_stores, option::none(), start_after, 2); let metadata_vec: vector<Object<Metadata>> = vector[]; let balance_vec: vector<u64> = vector[]; @@ -563,12 +553,7 @@ This function is only callable by the chain. 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 - ); + fungible_asset::sudo_transfer(sender, sender_store, recipient_store, amount); }
@@ -819,11 +804,7 @@ Withdraw from the primary store of owner ignoring frozen flag. owner, fungible_asset::transfer_ref_metadata(transfer_ref) ); - fungible_asset::withdraw_with_ref( - transfer_ref, - from_primary_store, - amount - ) + fungible_asset::withdraw_with_ref(transfer_ref, from_primary_store, amount) }
diff --git a/minitia_stdlib/doc/score.md b/minitia_stdlib/doc/score.md index ee00d0f..e4b0f2b 100644 --- a/minitia_stdlib/doc/score.md +++ b/minitia_stdlib/doc/score.md @@ -700,11 +700,7 @@ Decrease a score of an account. !simple_map::contains_key(&module_store.deployers, &deployer), error::invalid_argument(EDEPLOYER_ALREADY_ADDED) ); - simple_map::add( - &mut module_store.deployers, - deployer, - true - ); + simple_map::add(&mut module_store.deployers, deployer, true); event::emit(DeployerAddedEvent { deployer: deployer }) } diff --git a/minitia_stdlib/doc/secp256k1.md b/minitia_stdlib/doc/secp256k1.md index d66c72a..c7c678c 100644 --- a/minitia_stdlib/doc/secp256k1.md +++ b/minitia_stdlib/doc/secp256k1.md @@ -17,6 +17,7 @@ This module implements ECDSA signatures based on the prime-order secp256k1 ellpt - [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 `verify`](#0x1_secp256k1_verify) - [Function `ecdsa_recover`](#0x1_secp256k1_ecdsa_recover) - [Function `ecdsa_recover_compressed`](#0x1_secp256k1_ecdsa_recover_compressed) @@ -326,6 +327,37 @@ Serializes an ECDSASignature struct to 64-bytes. + + +## Function `verify` + +Returns true if the signature can verify the public key on the message + + +
public fun verify(message: vector<u8>, public_key: &secp256k1::ECDSACompressedPublicKey, signature: &secp256k1::ECDSASignature): bool
+
+ + + +##### Implementation + + +
public fun verify(
+    message: vector<u8>,
+    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)
+}
+
+ + + ## Function `ecdsa_recover` @@ -355,12 +387,7 @@ public key (or its hash) is known beforehand. ); let (pk, success) = - recover_public_key_internal( - recovery_id, - message, - signature.bytes, - false - ); + recover_public_key_internal(recovery_id, message, signature.bytes, false); if (success) { std::option::some(ecdsa_raw_public_key_from_bytes(pk)) } else { @@ -400,12 +427,7 @@ public key (or its hash) is known beforehand. ); let (pk, success) = - recover_public_key_internal( - recovery_id, - message, - signature.bytes, - true - ); + recover_public_key_internal(recovery_id, message, signature.bytes, true); if (success) { std::option::some(ecdsa_compressed_public_key_from_bytes(pk)) } else { diff --git a/minitia_stdlib/doc/simple_map.md b/minitia_stdlib/doc/simple_map.md index d3a714b..f1158b9 100644 --- a/minitia_stdlib/doc/simple_map.md +++ b/minitia_stdlib/doc/simple_map.md @@ -332,7 +332,9 @@ Add a key/value pair to the map. The key must not already exist. value: Value ) { let maybe_idx = find(self, &key); - assert!(option::is_none(&maybe_idx), error::invalid_argument(EKEY_ALREADY_EXISTS)); + assert!( + option::is_none(&maybe_idx), error::invalid_argument(EKEY_ALREADY_EXISTS) + ); vector::push_back(&mut self.data, Element { key, value }); } diff --git a/minitia_stdlib/doc/simple_nft.md b/minitia_stdlib/doc/simple_nft.md index 418409e..c611f72 100644 --- a/minitia_stdlib/doc/simple_nft.md +++ b/minitia_stdlib/doc/simple_nft.md @@ -293,11 +293,7 @@ With an existing collection, directly mint a viable nft into the creators accoun 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)); } } @@ -625,11 +621,7 @@ Mint a nft into an existing collection, and retrieve the object / address of the error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); - property_map::update_typed( - &simple_nft.property_mutator_ref, - &key, - value - ); + property_map::update_typed(&simple_nft.property_mutator_ref, &key, value); } diff --git a/minitia_stdlib/sources/account.move b/minitia_stdlib/sources/account.move index fab31b7..129a34b 100644 --- a/minitia_stdlib/sources/account.move +++ b/minitia_stdlib/sources/account.move @@ -49,11 +49,7 @@ module minitia_std::account { error::already_exists(EACCOUNT_ALREADY_EXISTS) ); - request_create_account( - addr, - account_number, - ACCOUNT_TYPE_TABLE - ) + request_create_account(addr, account_number, ACCOUNT_TYPE_TABLE) } /// ObjectAccount is similar to CosmosSDK's ModuleAccount in concept, @@ -63,11 +59,7 @@ module minitia_std::account { // 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 - ) + 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, @@ -315,13 +307,7 @@ module minitia_std::account { assert!(exists_at(new_address), 2); // set base account with 0 sequence - set_account_info( - new_address2, - 100, - 0, - ACCOUNT_TYPE_BASE, - false - ); + set_account_info(new_address2, 100, 0, ACCOUNT_TYPE_BASE, false); let table_account_num = create_table_account(new_address2); assert!( table_account_num == get_account_number(new_address2), @@ -341,13 +327,7 @@ module minitia_std::account { assert!(exists_at(new_address3), 5); // set base account with 0 sequence - set_account_info( - new_address4, - 200, - 0, - ACCOUNT_TYPE_BASE, - false - ); + set_account_info(new_address4, 200, 0, ACCOUNT_TYPE_BASE, false); let object_account_num = create_object_account(new_address4); assert!( object_account_num == get_account_number(new_address4), @@ -363,22 +343,10 @@ module minitia_std::account { public fun test_blocked_address( new_address: address, new_address2: address ) { - set_account_info( - new_address, - 200, - 0, - ACCOUNT_TYPE_BASE, - true - ); + set_account_info(new_address, 200, 0, ACCOUNT_TYPE_BASE, true); assert!(is_blocked(new_address), 1); - set_account_info( - new_address2, - 100, - 0, - ACCOUNT_TYPE_BASE, - false - ); + set_account_info(new_address2, 100, 0, ACCOUNT_TYPE_BASE, false); assert!(!is_blocked(new_address2), 2); } @@ -411,6 +379,7 @@ module minitia_std::account { #[test_only] public fun create_account_for_test(new_address: address): signer { + create_account(new_address); create_signer_for_test(new_address) } } diff --git a/minitia_stdlib/sources/any.move b/minitia_stdlib/sources/any.move index d6a3b65..aed0f48 100644 --- a/minitia_stdlib/sources/any.move +++ b/minitia_stdlib/sources/any.move @@ -55,6 +55,9 @@ module minitia_std::any { #[test] fun test_any() { assert!(unpack(pack(22)) == 22, 1); - assert!(unpack(pack(S { x: 22 })) == S { x: 22 }, 2); + assert!( + unpack(pack(S { x: 22 })) == S { x: 22 }, + 2 + ); } } diff --git a/minitia_stdlib/sources/bigdecimal.move b/minitia_stdlib/sources/bigdecimal.move index c911fc2..ee53b63 100644 --- a/minitia_stdlib/sources/bigdecimal.move +++ b/minitia_stdlib/sources/bigdecimal.move @@ -77,7 +77,8 @@ module minitia_std::bigdecimal { public fun from_ratio(numerator: BigUint, denominator: BigUint): BigDecimal { assert!( - !biguint::is_zero(denominator), error::invalid_argument(EDIVISION_BY_ZERO) + !biguint::is_zero(denominator), + error::invalid_argument(EDIVISION_BY_ZERO) ); let numerator = biguint::mul(numerator, f()); @@ -259,7 +260,8 @@ module minitia_std::bigdecimal { public fun div(num1: BigDecimal, num2: BigDecimal): BigDecimal { assert!( - !biguint::is_zero(num2.scaled), error::invalid_argument(EDIVISION_BY_ZERO) + !biguint::is_zero(num2.scaled), + error::invalid_argument(EDIVISION_BY_ZERO) ); BigDecimal { @@ -349,7 +351,10 @@ module minitia_std::bigdecimal { let num4 = add(num1, num3); assert!( - eq(num4, from_ratio(biguint::from_u64(5), biguint::from_u64(6))), + eq( + num4, + from_ratio(biguint::from_u64(5), biguint::from_u64(6)) + ), 4 ); @@ -370,13 +375,19 @@ module minitia_std::bigdecimal { let num10 = add_by_u64(num1, 1); assert!( - eq(num10, from_ratio(biguint::from_u64(3), biguint::from_u64(2))), + 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))), + eq( + num11, + from_ratio(biguint::from_u64(1), biguint::from_u64(2)) + ), 11 ); @@ -385,7 +396,10 @@ module minitia_std::bigdecimal { let num13 = div_by_u64(num1, 2); assert!( - eq(num13, from_ratio(biguint::from_u64(1), biguint::from_u64(4))), + eq( + num13, + from_ratio(biguint::from_u64(1), biguint::from_u64(4)) + ), 13 ); } diff --git a/minitia_stdlib/sources/biguint.move b/minitia_stdlib/sources/biguint.move index 93bf024..33f82cb 100644 --- a/minitia_stdlib/sources/biguint.move +++ b/minitia_stdlib/sources/biguint.move @@ -213,20 +213,35 @@ module minitia_std::biguint { let num1 = from_u128(18446744073709551615u128 * 2u128); let num2 = from_u128(18446744073709551615u128 * 2u128); let num3 = add(num1, num2); - assert!(to_u128(num3) == 18446744073709551615u128 * 4u128, 1); + 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); + 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); + assert!( + to_u128(num7) == 18446744073709551615u128 * 2u128 + 1u128, + 4 + ); let num8 = sub_by_u128(num1, 1); - assert!(to_u128(num8) == 18446744073709551615u128 * 2u128 - 1u128, 5); + assert!( + to_u128(num8) == 18446744073709551615u128 * 2u128 - 1u128, + 5 + ); let num9 = mul_by_u128(num1, 2); - assert!(to_u128(num9) == 18446744073709551615u128 * 4u128, 6); + assert!( + to_u128(num9) == 18446744073709551615u128 * 4u128, + 6 + ); let num10 = div_by_u128(num1, 2); assert!(to_u128(num10) == 18446744073709551615u128, 7); } @@ -236,11 +251,17 @@ module minitia_std::biguint { let num1 = from_u256(340282366920938463463374607431768211455u256 * 2u256); let num2 = from_u256(340282366920938463463374607431768211455u256 * 2u256); let num3 = add(num1, num2); - assert!(to_u256(num3) == 340282366920938463463374607431768211455u256 * 4u256, 1); + 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); + assert!( + to_u256(num5) == 340282366920938463463374607431768211455u256 * 4u256, + 2 + ); let num6 = div(num1, from_u256(2)); assert!(to_u256(num6) == 340282366920938463463374607431768211455u256, 3); @@ -257,7 +278,10 @@ module minitia_std::biguint { 5 ); let num9 = mul_by_u256(num1, 2); - assert!(to_u256(num9) == 340282366920938463463374607431768211455u256 * 4u256, 6); + assert!( + to_u256(num9) == 340282366920938463463374607431768211455u256 * 4u256, + 6 + ); let num10 = div_by_u256(num1, 2); assert!(to_u256(num10) == 340282366920938463463374607431768211455u256, 7); } diff --git a/minitia_stdlib/sources/code.move b/minitia_stdlib/sources/code.move index 34bc7d9..351cd85 100644 --- a/minitia_stdlib/sources/code.move +++ b/minitia_stdlib/sources/code.move @@ -115,6 +115,20 @@ module minitia_std::code { ) } + fun assert_no_duplication(module_ids: &vector) { + let module_ids_set = simple_map::create(); + 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); + } + ); + } + public entry fun init_genesis( chain: &signer, module_ids: vector, allowed_publishers: vector
) acquires ModuleStore { @@ -122,6 +136,7 @@ module minitia_std::code { signer::address_of(chain) == @minitia_std, error::permission_denied(EINVALID_CHAIN_OPERATOR) ); + assert_no_duplication(&module_ids); let metadata_table = table::new(); vector::for_each_ref( @@ -172,7 +187,10 @@ module minitia_std::code { let registry = borrow_global_mut(code_object_addr); let iter = table::iter_mut( - &mut registry.metadata, option::none(), option::none(), 1 + &mut registry.metadata, + option::none(), + option::none(), + 1 ); loop { if (!table::prepare_mut(iter)) { break }; @@ -195,23 +213,7 @@ module minitia_std::code { vector::length(&code) == vector::length(&module_ids), error::invalid_argument(EINVALID_ARGUMENTS) ); - - // duplication check - let module_ids_set = simple_map::create(); - 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 - ); - } - ); + assert_no_duplication(&module_ids); // Check whether arbitrary publish is allowed or not. let module_store = borrow_global_mut(@minitia_std); @@ -225,13 +227,11 @@ module minitia_std::code { assert_allowed(&module_store.allowed_publishers, addr); if (!exists(addr)) { - move_to( - owner, - MetadataStore { metadata: table::new() } - ); + move_to(owner, MetadataStore { metadata: table::new() }); }; // Check upgradability + let new_modules = 0; let metadata_table = &mut borrow_global_mut(addr).metadata; vector::for_each_ref( &module_ids, @@ -247,8 +247,7 @@ module minitia_std::code { ); assert!( can_change_upgrade_policy_to( - metadata.upgrade_policy, - upgrade_policy + metadata.upgrade_policy, upgrade_policy ), error::invalid_argument(EUPGRADE_WEAKER_POLICY) ); @@ -260,6 +259,7 @@ module minitia_std::code { *module_id, ModuleMetadata { upgrade_policy } ); + new_modules = new_modules + 1; }; event::emit( @@ -268,8 +268,11 @@ module minitia_std::code { } ); + if (new_modules > 0) { + increase_total_modules(new_modules) + }; + // Request publish - increase_total_modules(vector::length(&module_ids)); request_publish(addr, module_ids, code) } diff --git a/minitia_stdlib/sources/coin.move b/minitia_stdlib/sources/coin.move index 73052bb..c950062 100644 --- a/minitia_stdlib/sources/coin.move +++ b/minitia_stdlib/sources/coin.move @@ -120,10 +120,7 @@ module minitia_std::coin { ): (MintCapability, BurnCapability, FreezeCapability, ExtendRef) { // create object for fungible asset metadata let constructor_ref = - &object::create_named_object( - creator, - *string::bytes(&symbol) - ); + &object::create_named_object(creator, *string::bytes(&symbol)); primary_fungible_store::create_primary_store_enabled_fungible_asset( constructor_ref, @@ -237,11 +234,7 @@ module minitia_std::coin { ); let refs = borrow_global(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) } /// Unfreeze the primary store of an account. @@ -257,11 +250,7 @@ module minitia_std::coin { ); let refs = borrow_global(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) } // diff --git a/minitia_stdlib/sources/copyable_any.move b/minitia_stdlib/sources/copyable_any.move index 6739db7..1adaeb7 100644 --- a/minitia_stdlib/sources/copyable_any.move +++ b/minitia_stdlib/sources/copyable_any.move @@ -45,6 +45,9 @@ module minitia_std::copyable_any { #[test] fun test_any() { assert!(unpack(pack(22)) == 22, 1); - assert!(unpack(pack(S { x: 22 })) == S { x: 22 }, 2); + assert!( + unpack(pack(S { x: 22 })) == S { x: 22 }, + 2 + ); } } diff --git a/minitia_stdlib/sources/cosmos.move b/minitia_stdlib/sources/cosmos.move index fd37bbf..bc78d77 100644 --- a/minitia_stdlib/sources/cosmos.move +++ b/minitia_stdlib/sources/cosmos.move @@ -7,9 +7,14 @@ module minitia_std::cosmos { use std::object::Object; use std::fungible_asset::Metadata; use std::collection::{Collection}; + use std::error; use minitia_std::json; + // Error codes + const EINVALID_CALLBACK_ID: u64 = 1; + const EINVALID_CALLBACK_FID: u64 = 2; + struct VoteRequest has copy, drop { _type_: String, proposal_id: u64, @@ -40,7 +45,27 @@ module minitia_std::cosmos { } public entry fun stargate(sender: &signer, data: vector) { - stargate_internal(signer::address_of(sender), data) + stargate_internal(signer::address_of(sender), data, disallow_failure()) + } + + /// Stargate message with options + /// + /// Options: + /// - allow_failure() + /// - disallow_failure() + /// - allow_failure_with_callback(id: u64, fid: String) + /// - disallow_failure_with_callback(id: u64, fid: String) + /// + /// The callback function should be defined with the following signature: + /// ```rust + /// public fun callback(id: u64, success: bool); + /// public fun callback(sender: &signer, id: u64, success: bool); + /// ``` + /// + public fun stargate_with_options( + sender: &signer, data: vector, options: Options + ) { + stargate_internal(signer::address_of(sender), data, options) } public entry fun move_execute( @@ -128,11 +153,7 @@ module minitia_std::cosmos { public entry fun fund_community_pool( sender: &signer, metadata: Object, amount: u64 ) { - fund_community_pool_internal( - signer::address_of(sender), - &metadata, - amount - ) + fund_community_pool_internal(signer::address_of(sender), &metadata, amount) } /// ICS20 ibc transfer @@ -217,7 +238,9 @@ module minitia_std::cosmos { ) } - native fun stargate_internal(sender: address, data: vector); + native fun stargate_internal( + sender: address, data: vector, option: Options + ); native fun move_execute_internal( sender: address, @@ -285,4 +308,70 @@ module minitia_std::cosmos { timeout_fee_metadata: &Object, timeout_fee_amount: u64 ); + + // ================================================== Options ================================================= + + /// Options for stargate message + struct Options has copy, drop { + allow_failure: bool, + + /// callback_id is the unique identifier for this message execution. + callback_id: u64, + /// function identifier which will be called after the message execution. + /// The function should be defined with the following signature: + /// ```rust + /// public fun callback(id: u64, success: bool); + /// public fun callback(sender: &signer, id: u64, success: bool); + /// ``` + /// + /// Ex) 0xaddr::test_module::callback + /// where callback is the function name defined in the test_module of the 0xaddr address. + callback_fid: vector + } + + public fun allow_failure(): Options { + Options { + allow_failure: true, + callback_id: 0, + callback_fid: vector::empty() + } + } + + public fun disallow_failure(): Options { + Options { + allow_failure: false, + callback_id: 0, + callback_fid: vector::empty() + } + } + + /// Ex) fid: 0xaddr::test_module::callback + /// where callback is the function name defined in the test_module of the 0xaddr address. + public fun allow_failure_with_callback(id: u64, fid: String): Options { + assert!(id > 0, error::invalid_argument(EINVALID_CALLBACK_ID)); + assert!( + !string::is_empty(&fid), error::invalid_argument(EINVALID_CALLBACK_FID) + ); + + Options { + allow_failure: true, + callback_id: id, + callback_fid: *string::bytes(&fid) + } + } + + /// Ex) fid: 0xaddr::test_module::callback + /// where callback is the function name defined in the test_module of the 0xaddr address. + public fun disallow_failure_with_callback(id: u64, fid: String): Options { + assert!(id > 0, error::invalid_argument(EINVALID_CALLBACK_ID)); + assert!( + !string::is_empty(&fid), error::invalid_argument(EINVALID_CALLBACK_FID) + ); + + Options { + allow_failure: false, + callback_id: id, + callback_fid: *string::bytes(&fid) + } + } } diff --git a/minitia_stdlib/sources/crypto/ed25519.move b/minitia_stdlib/sources/crypto/ed25519.move index c8c8629..1ef5213 100644 --- a/minitia_stdlib/sources/crypto/ed25519.move +++ b/minitia_stdlib/sources/crypto/ed25519.move @@ -72,11 +72,7 @@ module minitia_std::ed25519 { public fun verify( message: vector, public_key: &PublicKey, signature: &Signature ): bool { - verify_internal( - message, - public_key.bytes, - signature.bytes - ) + verify_internal(message, public_key.bytes, signature.bytes) } /// Performs batch Ed25519 signature verification. diff --git a/minitia_stdlib/sources/crypto/secp256k1.move b/minitia_stdlib/sources/crypto/secp256k1.move index c493245..fd24a7b 100644 --- a/minitia_stdlib/sources/crypto/secp256k1.move +++ b/minitia_stdlib/sources/crypto/secp256k1.move @@ -102,11 +102,7 @@ module minitia_std::secp256k1 { std::error::invalid_argument(E_DESERIALIZE) ); - return verify_internal( - message, - public_key.bytes, - signature.bytes - ) + 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 @@ -124,12 +120,7 @@ module minitia_std::secp256k1 { ); let (pk, success) = - recover_public_key_internal( - recovery_id, - message, - signature.bytes, - false - ); + recover_public_key_internal(recovery_id, message, signature.bytes, false); if (success) { std::option::some(ecdsa_raw_public_key_from_bytes(pk)) } else { @@ -152,12 +143,7 @@ module minitia_std::secp256k1 { ); let (pk, success) = - recover_public_key_internal( - recovery_id, - message, - signature.bytes, - true - ); + recover_public_key_internal(recovery_id, message, signature.bytes, true); if (success) { std::option::some(ecdsa_compressed_public_key_from_bytes(pk)) } else { @@ -176,9 +162,7 @@ module minitia_std::secp256k1 { /// - `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 + message: vector, public_key: vector, signature: vector ): bool; /// Returns `(public_key, true)` if `signature` verifies on `message` under the recovered `public_key` diff --git a/minitia_stdlib/sources/debug.move b/minitia_stdlib/sources/debug.move index 3dcda84..e7b4e15 100644 --- a/minitia_stdlib/sources/debug.move +++ b/minitia_stdlib/sources/debug.move @@ -258,16 +258,10 @@ module minitia_std::debug { assert_equal(&v_u64, b"[\n [ 64, 65 ],\n [ 66, 67 ]\n]"); let v_u128 = vector[vector[128u128, 129u128], vector[130u128, 131u128]]; - assert_equal( - &v_u128, - b"[\n [ 128, 129 ],\n [ 130, 131 ]\n]" - ); + assert_equal(&v_u128, 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]" - ); + assert_equal(&v_u256, b"[\n [ 256, 257 ],\n [ 258, 259 ]\n]"); let v_bool = vector[vector[true, false], vector[false, true]]; assert_equal( diff --git a/minitia_stdlib/sources/dex.move b/minitia_stdlib/sources/dex.move index 1e90d09..f79f42c 100644 --- a/minitia_stdlib/sources/dex.move +++ b/minitia_stdlib/sources/dex.move @@ -370,9 +370,7 @@ module minitia_std::dex { #[view] public fun get_provide_simulation( - pair: Object, - coin_a_amount_in: u64, - coin_b_amount_in: u64 + 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); @@ -477,7 +475,9 @@ 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 { @@ -738,16 +738,8 @@ module minitia_std::dex { 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( @@ -803,16 +795,8 @@ module minitia_std::dex { } }; - 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( @@ -985,18 +969,12 @@ module minitia_std::dex { offer_coin_amount: u64, min_return: Option ) 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 - ), + || *option::borrow(&min_return) <= fungible_asset::amount(&return_coin), error::invalid_state(EMIN_RETURN) ); @@ -1196,18 +1174,10 @@ module minitia_std::dex { 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 - ) + 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 - ) + fungible_asset::withdraw(pair_signer, pool.coin_a_store, return_amount) }; // emit events @@ -1299,10 +1269,7 @@ module minitia_std::dex { 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 } - ); + move_to(pair_signer, Pool { coin_a_store, coin_b_store }); move_to( pair_signer, @@ -1400,10 +1367,7 @@ module minitia_std::dex { let liquidity = calculate_provide_liquidity_return_amount( - pool, - pair, - coin_a_amount_in, - coin_b_amount_in + pool, pair, coin_a_amount_in, coin_b_amount_in ); assert!( @@ -1598,17 +1562,11 @@ module minitia_std::dex { // 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 - ), + bigdecimal::sub(bigdecimal::one(), normalized_weight), amount_in ); let fee_amount = - calculate_fee_with_minimum( - config.swap_fee_rate, - adjusted_swap_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; @@ -1861,16 +1819,8 @@ module minitia_std::dex { let init_metadata = coin::metadata(chain_addr, string::utf8(b"INIT")); let usdc_metadata = coin::metadata(chain_addr, string::utf8(b"USDC")); - coin::mint_to( - &initia_mint_cap, - chain_addr, - 100000000 - ); - coin::mint_to( - &usdc_mint_cap, - chain_addr, - 100000000 - ); + coin::mint_to(&initia_mint_cap, chain_addr, 100000000); + coin::mint_to(&usdc_mint_cap, chain_addr, 100000000); // spot price is 1 create_pair_script( @@ -2016,16 +1966,8 @@ module minitia_std::dex { let init_metadata = coin::metadata(chain_addr, string::utf8(b"INIT")); let usdc_metadata = coin::metadata(chain_addr, string::utf8(b"USDC")); - coin::mint_to( - &initia_mint_cap, - chain_addr, - 100000000 - ); - coin::mint_to( - &usdc_mint_cap, - chain_addr, - 100000000 - ); + coin::mint_to(&initia_mint_cap, chain_addr, 100000000); + coin::mint_to(&usdc_mint_cap, chain_addr, 100000000); set_block_info(10, 1000); @@ -2203,21 +2145,9 @@ module minitia_std::dex { let b_addr = object::object_address(&b_metadata); let c_addr = object::object_address(&c_metadata); - coin::mint_to( - &coin_a_mint_cap, - chain_addr, - 100000000 - ); - coin::mint_to( - &coin_b_mint_cap, - chain_addr, - 100000000 - ); - coin::mint_to( - &coin_c_mint_cap, - chain_addr, - 100000000 - ); + coin::mint_to(&coin_a_mint_cap, chain_addr, 100000000); + coin::mint_to(&coin_b_mint_cap, chain_addr, 100000000); + coin::mint_to(&coin_c_mint_cap, chain_addr, 100000000); create_pair_script( &chain, @@ -2417,12 +2347,7 @@ module minitia_std::dex { 2 ); - let res = get_pairs( - a_addr, - b_addr, - option::none(), - 10 - ); + let res = get_pairs(a_addr, b_addr, option::none(), 10); assert!( res == vector[ @@ -2444,12 +2369,7 @@ module minitia_std::dex { 3 ); - let res = get_pairs( - a_addr, - b_addr, - option::some(pair_1_addr), - 10 - ); + let res = get_pairs(a_addr, b_addr, option::some(pair_1_addr), 10); assert!( res == vector[ diff --git a/minitia_stdlib/sources/fa/dispatchable_fungible_asset.move b/minitia_stdlib/sources/fa/dispatchable_fungible_asset.move index 105529e..a1c7b2f 100644 --- a/minitia_stdlib/sources/fa/dispatchable_fungible_asset.move +++ b/minitia_stdlib/sources/fa/dispatchable_fungible_asset.move @@ -102,12 +102,7 @@ module minitia_std::dispatchable_fungible_asset { 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 - ) + dispatchable_deposit(store, fa, borrow_transfer_ref(store), func) } else { fungible_asset::deposit_internal(object::object_address(&store), fa) } @@ -139,7 +134,10 @@ module minitia_std::dispatchable_fungible_asset { let fa = withdraw(sender, from, amount); deposit(to, fa); let end = fungible_asset::balance(to); - assert!(end - start >= expected, error::aborted(EAMOUNT_MISMATCH)); + assert!( + end - start >= expected, + error::aborted(EAMOUNT_MISMATCH) + ); } #[view] diff --git a/minitia_stdlib/sources/fa/fungible_asset.move b/minitia_stdlib/sources/fa/fungible_asset.move index f3f6bcc..160dce1 100644 --- a/minitia_stdlib/sources/fa/fungible_asset.move +++ b/minitia_stdlib/sources/fa/fungible_asset.move @@ -369,8 +369,7 @@ module minitia_std::fungible_asset { // 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 + &function_info, supply_function ), error::invalid_argument( EDERIVED_SUPPLY_FUNCTION_SIGNATURE_MISMATCH @@ -1119,9 +1118,7 @@ module minitia_std::fungible_asset { string::utf8(b"TEST"), string::utf8(b"@@"), 0, - string::utf8( - b"http://www.example.com/favicon.ico" - ), + string::utf8(b"http://www.example.com/favicon.ico"), string::utf8(b"http://www.example.com") ); let mint_ref = generate_mint_ref(constructor_ref); @@ -1208,12 +1205,7 @@ module minitia_std::fungible_asset { burn_from(&burn_ref, aaron_store, 30); assert!(supply(test_token) == option::some(70), 4); // Transfer - transfer( - creator, - creator_store, - aaron_store, - 10 - ); + transfer(creator, creator_store, aaron_store, 10); assert!(balance(creator_store) == 10, 5); assert!(balance(aaron_store) == 60, 6); @@ -1236,7 +1228,10 @@ module minitia_std::fungible_asset { icon_uri(metadata) == string::utf8(b"http://www.example.com/favicon.ico"), 11 ); - assert!(project_uri(metadata) == string::utf8(b"http://www.example.com"), 12); + assert!( + project_uri(metadata) == string::utf8(b"http://www.example.com"), + 12 + ); } #[test(creator = @0xcafe)] @@ -1263,12 +1258,7 @@ module minitia_std::fungible_asset { set_frozen_flag(&transfer_ref, creator_store, true); set_frozen_flag(&transfer_ref, aaron_store, true); deposit_with_ref(&transfer_ref, creator_store, fa); - transfer_with_ref( - &transfer_ref, - creator_store, - aaron_store, - 80 - ); + transfer_with_ref(&transfer_ref, creator_store, aaron_store, 80); assert!(balance(creator_store) == 20, 1); assert!(balance(aaron_store) == 80, 2); assert!(!!is_frozen(creator_store), 3); @@ -1320,19 +1310,9 @@ module minitia_std::fungible_asset { let metadata = mint_ref.metadata; let module_acc_store = create_test_store(module_acc, metadata); - account::set_account_info( - signer::address_of(module_acc), - 10, - 0, - 3, - false - ); + account::set_account_info(signer::address_of(module_acc), 10, 0, 3, false); - set_frozen_flag( - &transfer_ref, - module_acc_store, - true - ); + set_frozen_flag(&transfer_ref, module_acc_store, true); } #[test(creator = @0xcafe, module_acc = @0x123)] @@ -1345,13 +1325,7 @@ module minitia_std::fungible_asset { let metadata = mint_ref.metadata; let module_acc_store = create_test_store(module_acc, metadata); - account::set_account_info( - signer::address_of(module_acc), - 10, - 0, - 3, - false - ); + account::set_account_info(signer::address_of(module_acc), 10, 0, 3, false); let fa = mint(&mint_ref, 100); deposit(module_acc_store, fa); @@ -1368,13 +1342,7 @@ module minitia_std::fungible_asset { let metadata = mint_ref.metadata; let module_acc_store = create_test_store(module_acc, metadata); - account::set_account_info( - signer::address_of(module_acc), - 10, - 0, - 3, - false - ); + account::set_account_info(signer::address_of(module_acc), 10, 0, 3, false); let fa = mint(&mint_ref, 100); deposit(module_acc_store, fa); @@ -1392,13 +1360,7 @@ module minitia_std::fungible_asset { let metadata = mint_ref.metadata; let blocked_acc_store = create_test_store(blocked_acc, metadata); - account::set_account_info( - signer::address_of(blocked_acc), - 10, - 0, - 3, - true - ); + account::set_account_info(signer::address_of(blocked_acc), 10, 0, 3, true); let fa = mint(&mint_ref, 100); deposit(blocked_acc_store, fa); @@ -1414,13 +1376,7 @@ module minitia_std::fungible_asset { let metadata = mint_ref.metadata; let blocked_acc_store = create_test_store(blocked_acc, metadata); - account::set_account_info( - signer::address_of(blocked_acc), - 10, - 0, - 3, - true - ); + account::set_account_info(signer::address_of(blocked_acc), 10, 0, 3, true); let fa = mint(&mint_ref, 100); deposit_with_ref(&transfer_ref, blocked_acc_store, fa); diff --git a/minitia_stdlib/sources/fa/primary_fungible_store.move b/minitia_stdlib/sources/fa/primary_fungible_store.move index ce227d7..a128615 100644 --- a/minitia_stdlib/sources/fa/primary_fungible_store.move +++ b/minitia_stdlib/sources/fa/primary_fungible_store.move @@ -137,10 +137,7 @@ module minitia_std::primary_fungible_store { // record owner store to table for cosmos side query if (exists(@minitia_std)) { let module_store = borrow_global_mut(@minitia_std); - if (!table::contains( - &module_store.user_stores, - owner_addr - )) { + if (!table::contains(&module_store.user_stores, owner_addr)) { table::add( &mut module_store.user_stores, owner_addr, @@ -148,12 +145,10 @@ module minitia_std::primary_fungible_store { ); }; - 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 ); + table::add(user_stores, metadata_addr, store_addr); }; // emit store created event @@ -219,12 +214,7 @@ module minitia_std::primary_fungible_store { ): (vector>, vector) acquires ModuleStore { let module_store = borrow_global(@minitia_std); let account_stores = table::borrow(&module_store.user_stores, account); - let iter = table::iter( - account_stores, - option::none(), - start_after, - 2 - ); + let iter = table::iter(account_stores, option::none(), start_after, 2); let metadata_vec: vector> = vector[]; let balance_vec: vector = vector[]; @@ -273,12 +263,7 @@ module minitia_std::primary_fungible_store { 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 - ); + fungible_asset::sudo_transfer(sender, sender_store, recipient_store, amount); } /// Withdraw `amount` of fungible asset from the given account's primary store. @@ -393,11 +378,7 @@ module minitia_std::primary_fungible_store { owner, fungible_asset::transfer_ref_metadata(transfer_ref) ); - fungible_asset::withdraw_with_ref( - transfer_ref, - from_primary_store, - amount - ) + fungible_asset::withdraw_with_ref(transfer_ref, from_primary_store, amount) } /// Deposit from the primary store of `owner` ignoring frozen flag. diff --git a/minitia_stdlib/sources/fixed_point64.move b/minitia_stdlib/sources/fixed_point64.move index af2e0bf..66924e4 100644 --- a/minitia_stdlib/sources/fixed_point64.move +++ b/minitia_stdlib/sources/fixed_point64.move @@ -223,7 +223,10 @@ 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); diff --git a/minitia_stdlib/sources/json.move b/minitia_stdlib/sources/json.move index e8166eb..6e80327 100644 --- a/minitia_stdlib/sources/json.move +++ b/minitia_stdlib/sources/json.move @@ -2,7 +2,7 @@ module minitia_std::json { 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 @@ -26,19 +26,25 @@ module minitia_std::json { /// 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) - }) + 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 - }); + let (found, idx) = vector::find( + &obj.elems, + |elem| { + use_elem(elem); + elem.key == *key_bytes + } + ); if (!found) { return option::none() @@ -49,18 +55,23 @@ module minitia_std::json { } /// Set or overwrite the element in the JSON object. - public fun set_elem(obj: &mut JSONObject, key: String, value: &T) { + 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 - }); + 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) - }); + 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); @@ -154,9 +165,7 @@ module minitia_std::json { b: true, c: vector[1, 2, 3], d: @0x1, - e: option::some( - TestObject2 { a: 42, b: true, c: vector[1, 2, 3] } - ), + e: option::some(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"), @@ -187,15 +196,44 @@ module minitia_std::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); + 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); + 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); + 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/managed_coin.move b/minitia_stdlib/sources/managed_coin.move index f3c86c8..963bf8b 100644 --- a/minitia_stdlib/sources/managed_coin.move +++ b/minitia_stdlib/sources/managed_coin.move @@ -202,18 +202,8 @@ module minitia_std::managed_coin { let metadata = test_metadata(); assert!(coin::is_coin(object::object_address(&metadata)), 0); - mint_to( - &mod_account, - source_addr, - metadata, - 50 - ); - mint_to( - &mod_account, - destination_addr, - metadata, - 10 - ); + mint_to(&mod_account, source_addr, metadata, 50); + mint_to(&mod_account, destination_addr, metadata, 10); assert!(coin::balance(source_addr, metadata) == 50, 1); assert!( coin::balance(destination_addr, metadata) == 10, @@ -223,12 +213,7 @@ module minitia_std::managed_coin { let supply = coin::supply(metadata); assert!(supply == option::some(60), 2); - coin::transfer( - &source, - destination_addr, - metadata, - 10 - ); + coin::transfer(&source, destination_addr, metadata, 10); assert!(coin::balance(source_addr, metadata) == 40, 3); assert!( coin::balance(destination_addr, metadata) == 20, @@ -269,12 +254,7 @@ module minitia_std::managed_coin { ); let metadata = test_metadata(); - mint_to( - &destination, - source_addr, - metadata, - 100 - ); + mint_to(&destination, source_addr, metadata, 100); } #[test(source = @0xa11ce, destination = @0xb0b, mod_account = @0x1)] @@ -297,12 +277,7 @@ module minitia_std::managed_coin { ); let metadata = test_metadata(); - mint_to( - &mod_account, - source_addr, - metadata, - 100 - ); + mint_to(&mod_account, source_addr, metadata, 100); burn(&destination, metadata, 10); } } diff --git a/minitia_stdlib/sources/math128.move b/minitia_stdlib/sources/math128.move index 40ca3b6..7ec7c3d 100644 --- a/minitia_stdlib/sources/math128.move +++ b/minitia_stdlib/sources/math128.move @@ -165,10 +165,8 @@ module minitia_std::math128 { // No overflow assert!( - ceil_div( - (((1u256 << 128) - 9) as u128), - 11 - ) == 30934760629176223951215873402888019223, + ceil_div((((1u256 << 128) - 9) as u128), 11) + == 30934760629176223951215873402888019223, 0 ); } diff --git a/minitia_stdlib/sources/math64.move b/minitia_stdlib/sources/math64.move index f0e8eb9..99a85e0 100644 --- a/minitia_stdlib/sources/math64.move +++ b/minitia_stdlib/sources/math64.move @@ -138,10 +138,7 @@ module minitia_std::math64 { // No overflow assert!( - ceil_div( - (((1u128 << 64) - 9) as u64), - 11 - ) == 1676976733973595601, + ceil_div((((1u128 << 64) - 9) as u64), 11) == 1676976733973595601, 0 ); } diff --git a/minitia_stdlib/sources/multisig.move b/minitia_stdlib/sources/multisig.move index e1919c3..e020708 100644 --- a/minitia_stdlib/sources/multisig.move +++ b/minitia_stdlib/sources/multisig.move @@ -317,10 +317,7 @@ module minitia_std::multisig { assert_member(&multisig_wallet.members, &voter); assert!( - table::contains( - &multisig_wallet.proposals, - proposal_id - ), + table::contains(&multisig_wallet.proposals, proposal_id), error::invalid_argument(EPROPOSAL_NOT_FOUND) ); let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id); @@ -344,10 +341,7 @@ module minitia_std::multisig { assert_member(&multisig_wallet.members, &executor); assert!( - table::contains( - &multisig_wallet.proposals, - proposal_id - ), + table::contains(&multisig_wallet.proposals, proposal_id), error::invalid_argument(EPROPOSAL_NOT_FOUND) ); let proposal = table::borrow_mut(&mut multisig_wallet.proposals, proposal_id); @@ -357,10 +351,8 @@ module minitia_std::multisig { // check passed assert!( - yes_vote_count( - &proposal.votes, - &multisig_wallet.members - ) >= multisig_wallet.threshold, + yes_vote_count(&proposal.votes, &multisig_wallet.members) + >= multisig_wallet.threshold, error::invalid_state(ENOT_PASS) ); diff --git a/minitia_stdlib/sources/multisig_v2.move b/minitia_stdlib/sources/multisig_v2.move new file mode 100644 index 0000000..a60bfa1 --- /dev/null +++ b/minitia_stdlib/sources/multisig_v2.move @@ -0,0 +1,2465 @@ +module minitia_std::multisig_v2 { + use std::error; + use std::option::{Self, Option}; + use std::signer; + use std::string::{Self, String}; + use std::vector; + use std::event; + + use minitia_std::block::get_block_info; + use minitia_std::cosmos::{move_execute, move_execute_with_json}; + use minitia_std::object::{Self, ExtendRef}; + use minitia_std::simple_map::{Self, SimpleMap}; + use minitia_std::table::{Self, Table}; + use minitia_std::type_info; + + // errors + + const EINVALID_THRESHOLD: u64 = 1; + + const ENOT_MEMBER: u64 = 2; + + const EINVALID_PROPOSAL_STATUS: u64 = 3; + + const EPROPOSAL_EXPIRED: u64 = 4; + + const ENOT_PASS: u64 = 5; + + const EPROPOSAL_NOT_FOUND: u64 = 6; + + const EINVALID_TIERS_LENGTH: u64 = 7; + + const EINVALID_MEMBERS_LENGTH: u64 = 8; + + const EINVALID_MEMBER_TIERS: u64 = 9; + + const EINVALID_EXPIRY_TIMESTAMP: u64 = 10; + + const EMULTISIG_NAME_TOO_LONG: u64 = 11; + + const EINVALID_PROPOSAL_MESSAGE_LENGTH: u64 = 12; + + // constants + + const STATUS: vector> = vector[b"voting", b"executed", b"expired"]; + + const MAX_LIMIT: u8 = 30; + + const MAX_MULTISIG_NAME_LENGTH: u64 = 64; + + // structs + + struct Tier has copy, drop, store { + name: String, + weight: u64 + } + + struct Member has copy, drop, store { + address: address, + tier: Option + } + + struct MultisigWallet has key { + extend_ref: ExtendRef, + name: String, + weighted: bool, // if true -> tiers should be present + tiers: Option>, + members: vector, // members of multisig account + threshold: u64, // require weight to pass + proposals: Table + } + + struct ExecuteMessage has copy, drop, store { + module_address: address, + module_name: String, + function_name: String, + type_args: vector, + args: vector>, + json_args: vector + } + + struct Proposal has store { + proposer: Member, + proposed_timestamp: u64, + proposed_height: u64, + expiry_timestamp: Option, + votes: SimpleMap, + threshold: u64, + total_weight: u64, + status: u8, + is_json: bool, + execute_messages: vector + } + + // events + + #[event] + struct CreateMultisigAccountEvent has drop, store { + multisig_addr: address, + name: String, + weighted: bool, + members: vector, + threshold: u64 + } + + #[event] + struct CreateProposalEvent has drop, store { + multisig_addr: address, + proposal_id: u64, + proposer: Member, + execute_messages: vector + } + + #[event] + struct VoteProposalEvent has drop, store { + multisig_addr: address, + proposal_id: u64, + voter: Member, + vote_yes: bool + } + + #[event] + struct ExecuteProposalEvent has drop, store { + multisig_addr: address, + proposal_id: u64, + executor: Member + } + + #[event] + struct UpdateConfigEvent has drop, store { + multisig_addr: address, + members: vector, + tiers: Option>, + threshold: u64 + } + + // view function response struct + + struct ProposalResponse has drop { + multisig_addr: address, + proposal_id: u64, + votes: SimpleMap, + proposer: Member, + proposed_height: u64, + proposed_timestamp: u64, + expiry_timestamp: Option, + threshold: u64, + total_weight: u64, + yes_vote_score: u64, + status: String, + is_json: bool, + execute_messages: vector + } + + struct MultisigResponse has drop { + multisig_addr: address, + name: String, + members: vector, + threshold: u64, + tiers: Option> + } + + // view functions + + #[view] + public fun is_exist(creator_addr: address, name: String): bool { + let seed = create_multisig_seed(&name); + let multisig_addr = object::create_object_address(&creator_addr, seed); + object::object_exists(multisig_addr) + } + + #[view] + public fun get_multisig(multisig_addr: address): MultisigResponse acquires MultisigWallet { + let multisig_wallet = borrow_global(multisig_addr); + + MultisigResponse { + multisig_addr, + name: multisig_wallet.name, + tiers: multisig_wallet.tiers, + members: multisig_wallet.members, + threshold: multisig_wallet.threshold + } + } + + #[view] + 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 + ) + } + + #[view] + public fun get_proposals( + multisig_addr: address, start_after: Option, limit: u8 + ): vector acquires MultisigWallet { + if (limit > MAX_LIMIT) { + limit = MAX_LIMIT + }; + let res: vector = vector[]; + let multisig_wallet = borrow_global(multisig_addr); + let iter = table::iter( + &multisig_wallet.proposals, + option::none(), + start_after, + 2 + ); + + while (vector::length(&res) < (limit as u64) + && table::prepare(iter)) { + let (proposal_id, proposal) = table::next(iter); + vector::push_back( + &mut res, + proposal_to_proposal_response( + multisig_wallet, + multisig_addr, + proposal_id, + proposal + ) + ); + }; + + res + } + + // entry functions + + /// Create new non weighted multisig account + public entry fun create_non_weighted_multisig_account( + account: &signer, + name: String, // name for make deterministic multisig address (account_addr + name) + members: vector
, + threshold: u64 + ) { + assert_member(&members, &signer::address_of(account)); + assert!( + vector::length(&members) >= threshold, + error::invalid_argument(EINVALID_THRESHOLD) + ); + assert!( + threshold > 0, + error::invalid_argument(EINVALID_THRESHOLD) + ); + + let constructor_ref = + object::create_named_object(account, create_multisig_seed(&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); + + assert_uniqueness(members); + + let members = vector::map( + members, + |member| Member { address: member, tier: option::none() } + ); + + move_to( + &multisig_signer, + MultisigWallet { + extend_ref, + name, + members, + weighted: false, + tiers: option::none(), + threshold, + proposals: table::new() + } + ); + + event::emit( + CreateMultisigAccountEvent { + multisig_addr, + name, + weighted: false, + members, + threshold + } + ) + } + + /// Create new weighted multisig account + public entry fun create_weighted_multisig_account( + account: &signer, + name: String, // name for make deterministic multisig address (account_addr + name) + tiers: vector, + tier_weights: vector, + members: vector
, + member_tiers: vector, + threshold: u64 + ) { + assert_member(&members, &signer::address_of(account)); + assert_uniqueness(members); + assert_tier_config(tiers, tier_weights, &members, member_tiers); + assert_uniqueness(tiers); + + // check threshold computed from each member weights + let total_weight = vector::fold( + member_tiers, + 0u64, + |acc, tier| { + let (_, index) = vector::index_of(&tiers, &tier); + acc + *vector::borrow(&tier_weights, index) + } + ); + assert!( + total_weight >= threshold, + error::invalid_argument(EINVALID_THRESHOLD) + ); + assert!( + threshold > 0, + error::invalid_argument(EINVALID_THRESHOLD) + ); + + let constructor_ref = + object::create_named_object(account, create_multisig_seed(&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 tiers = vector::map( + tiers, + |tier| { + let (_, index) = vector::index_of(&tiers, &tier); + Tier { name: tier, weight: *vector::borrow(&tier_weights, index) } + } + ); + + let members = construct_members_with_tiers(members, member_tiers, tiers); + + move_to( + &multisig_signer, + MultisigWallet { + extend_ref, + name, + members, + weighted: true, + tiers: option::some(tiers), + threshold, + proposals: table::new() + } + ); + + event::emit( + CreateMultisigAccountEvent { + multisig_addr, + weighted: true, + name, + members, + threshold + } + ) + } + + fun total_weight(members: &vector): u64 { + vector::fold( + *members, + 0u64, + |acc, member| { + let m: Member = member; + acc + + if (option::is_some(&m.tier)) { + let tier = *option::borrow(&m.tier); + tier.weight + } else { 1u64 } + } + ) + } + + /// Create new proposal + public entry fun create_proposal( + account: &signer, + multisig_addr: address, + module_address_list: vector
, + module_name_list: vector, + function_name_list: vector, + type_args_list: vector>, + args_list: vector>>, + expiry_duration: Option + ) acquires MultisigWallet { + assert!( + vector::length(&module_address_list) == vector::length(&module_name_list) + && vector::length(&module_name_list) + == vector::length(&function_name_list) + && vector::length(&function_name_list) + == vector::length(&type_args_list) + && vector::length(&type_args_list) == vector::length(&args_list), + error::invalid_argument(EINVALID_PROPOSAL_MESSAGE_LENGTH) + ); + + let index = 0; + let execute_messages = vector::map( + module_address_list, + |module_address| { + let module_name = *vector::borrow(&module_name_list, index); + let function_name = *vector::borrow(&function_name_list, index); + let type_args = *vector::borrow(&type_args_list, index); + let args = *vector::borrow(&args_list, index); + index = index + 1; + + ExecuteMessage { + module_address, + module_name, + function_name, + type_args, + args, + json_args: vector[] + } + } + ); + + create_proposal_internal( + account, + multisig_addr, + false, + execute_messages, + expiry_duration + ) + } + + /// Create new proposal + public entry fun create_proposal_with_json( + account: &signer, + multisig_addr: address, + module_address_list: vector
, + module_name_list: vector, + function_name_list: vector, + type_args_list: vector>, + args_list: vector>, + expiry_duration: Option + ) acquires MultisigWallet { + assert!( + vector::length(&module_address_list) == vector::length(&module_name_list) + && vector::length(&module_name_list) + == vector::length(&function_name_list) + && vector::length(&function_name_list) + == vector::length(&type_args_list) + && vector::length(&type_args_list) == vector::length(&args_list), + error::invalid_argument(EINVALID_PROPOSAL_MESSAGE_LENGTH) + ); + + let index = 0; + let execute_messages = vector::map( + module_address_list, + |module_address| { + let module_name = *vector::borrow(&module_name_list, index); + let function_name = *vector::borrow(&function_name_list, index); + let type_args = *vector::borrow(&type_args_list, index); + let json_args = *vector::borrow(&args_list, index); + index = index + 1; + + ExecuteMessage { + module_address, + module_name, + function_name, + type_args, + args: vector[], + json_args + } + } + ); + + create_proposal_internal( + account, + multisig_addr, + true, + execute_messages, + expiry_duration + ) + } + + /// Vote proposal + public entry fun vote_proposal( + account: &signer, + multisig_addr: address, + proposal_id: u64, + vote_yes: bool + ) acquires MultisigWallet { + let voter_address = signer::address_of(account); + let multisig_wallet = borrow_global_mut(multisig_addr); + assert_multisig_member(&multisig_wallet.members, &voter_address); + + 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_proposal(proposal); + + let voter = get_member_by_address(multisig_wallet.members, voter_address); + vote(&mut proposal.votes, voter, vote_yes); + + event::emit( + VoteProposalEvent { multisig_addr, proposal_id, voter, vote_yes } + ) + } + + /// Execute proposal + public entry fun execute_proposal( + account: &signer, multisig_addr: address, proposal_id: u64 + ) acquires MultisigWallet { + let executor_address = signer::address_of(account); + let multisig_wallet = borrow_global_mut(multisig_addr); + let executor = get_member_by_address(multisig_wallet.members, executor_address); + assert_multisig_member(&multisig_wallet.members, &executor_address); + + 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_proposal(proposal); + + // check passed + assert!( + yes_vote_score(&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); + + proposal.status = 1; // change the status first in case of updating config + + if (!proposal.is_json) { + vector::for_each( + proposal.execute_messages, + |execute_message| { + let m: ExecuteMessage = execute_message; + move_execute( + multisig_signer, + m.module_address, + m.module_name, + m.function_name, + m.type_args, + m.args + ) + } + ) + } else { + vector::for_each( + proposal.execute_messages, + |execute_message| { + let m: ExecuteMessage = execute_message; + move_execute_with_json( + multisig_signer, + m.module_address, + m.module_name, + m.function_name, + m.type_args, + m.json_args + ) + } + ) + }; + + event::emit( + ExecuteProposalEvent { multisig_addr, proposal_id, executor } + ) + } + + /// Update config. Only execute by multisig wallet itself + public entry fun update_config( + account: &signer, + new_members: vector
, + new_tiers: Option>, + new_tier_weights: Option>, + new_member_tiers: Option>, + new_threshold: u64 + ) acquires MultisigWallet { + let multisig_addr = signer::address_of(account); + let multisig_wallet = borrow_global_mut(multisig_addr); + + assert_uniqueness(new_members); + + let removed_members = vector::filter( + multisig_wallet.members, + |member| { + let m: &Member = member; + !vector::contains(&new_members, &m.address) + } + ); + + if (multisig_wallet.weighted) { + let new_tiers = *option::borrow(&new_tiers); + let new_tier_weights = *option::borrow(&new_tier_weights); + let new_member_tiers = *option::borrow(&new_member_tiers); + + assert_tier_config( + new_tiers, + new_tier_weights, + &new_members, + new_member_tiers + ); + assert_uniqueness(new_tiers); + + // check threshold computed from each member weights + let total_weight = vector::fold( + new_member_tiers, + 0u64, + |acc, tier| { + let (_, index) = vector::index_of(&new_tiers, &tier); + acc + *vector::borrow(&new_tier_weights, index) + } + ); + + assert!( + total_weight >= new_threshold, + error::invalid_argument(EINVALID_THRESHOLD) + ); + assert!( + new_threshold > 0, + error::invalid_argument(EINVALID_THRESHOLD) + ); + + let tiers = vector::map( + new_tiers, + |tier| { + let (_, index) = vector::index_of(&new_tiers, &tier); + Tier { name: tier, weight: *vector::borrow(&new_tier_weights, index) } + } + ); + + multisig_wallet.threshold = new_threshold; + multisig_wallet.tiers = option::some(tiers); + multisig_wallet.members = construct_members_with_tiers( + new_members, new_member_tiers, tiers + ); + } else { + assert!( + vector::length(&new_members) >= new_threshold, + error::invalid_argument(EINVALID_THRESHOLD) + ); + + multisig_wallet.threshold = new_threshold; + multisig_wallet.members = vector::map( + new_members, + |member| Member { address: member, tier: option::none() } + ); + }; + + // remove votes of the removed members from active proposals + let iter = + table::iter_mut( + &mut multisig_wallet.proposals, + option::none(), + option::none(), + 2 + ); + while (table::prepare(iter)) { + let (_, proposal) = table::next_mut(iter); + // only cares about active proposals + if (proposal.status != 0 || is_proposal_expired(proposal)) { + continue + }; + + proposal.threshold = new_threshold; + proposal.total_weight = total_weight(&multisig_wallet.members); + + // remove removed_members votes + vector::for_each( + removed_members, + |member| { + let m: Member = member; + if (simple_map::contains_key(&proposal.votes, &m)) { + simple_map::remove(&mut proposal.votes, &m); + } + } + ); + }; + + event::emit( + UpdateConfigEvent { + multisig_addr, + members: multisig_wallet.members, + tiers: multisig_wallet.tiers, + threshold: multisig_wallet.threshold + } + ) + } + + // public functions + + public fun create_multisig_seed(name: &String): vector { + assert!( + string::length(name) <= MAX_MULTISIG_NAME_LENGTH, + error::out_of_range(EMULTISIG_NAME_TOO_LONG) + ); + + let type_name = type_info::type_name(); + let seed = *string::bytes(&type_name); + vector::append(&mut seed, *string::bytes(name)); + seed + } + + // private functions + + fun construct_members_with_tiers( + members: vector
, member_tiers: vector, tiers: vector + ): vector { + let index = 0; + vector::map( + members, + |member| { + let tier_name = *vector::borrow(&member_tiers, index); + index = index + 1; + + // find tier with tier_name in tiers + let (found, tier_index) = vector::find( + &tiers, + |t| { + let tt: &Tier = t; + tt.name == tier_name + } + ); + + assert!(found, error::invalid_argument(EINVALID_MEMBER_TIERS)); + + let tier = *vector::borrow(&tiers, tier_index); + + Member { address: member, tier: option::some(tier) } + } + ) + } + + fun get_member_by_address(members: vector, address: address): Member { + let (found, index) = vector::find( + &members, + |member| { + let m: &Member = member; + m.address == address + } + ); + + assert!(found, error::permission_denied(ENOT_MEMBER)); + + *vector::borrow(&members, index) + } + + fun create_proposal_internal( + account: &signer, + multisig_addr: address, + is_json: bool, + execute_messages: vector, + expiry_duration: Option + ) acquires MultisigWallet { + let addr = signer::address_of(account); + let multisig_wallet = borrow_global_mut(multisig_addr); + assert_multisig_member(&multisig_wallet.members, &addr); + + let (height, timestamp) = get_block_info(); + + let expiry_timestamp = + if (option::is_some(&expiry_duration)) { + let time_until_expired = *option::borrow(&expiry_duration); + option::some(timestamp + time_until_expired) + } else { + option::none() + }; + + // proposer votes yes on proposal creation + let votes = simple_map::create(); + let proposer = get_member_by_address(multisig_wallet.members, addr); + simple_map::add(&mut votes, proposer, true); + + let proposal = Proposal { + proposer, + proposed_height: height, + proposed_timestamp: timestamp, + expiry_timestamp, + threshold: multisig_wallet.threshold, + total_weight: total_weight(&multisig_wallet.members), + votes, + status: 0, // in voting period + is_json, + execute_messages + }; + + let proposal_id = table::length(&multisig_wallet.proposals) + 1; + table::add( + &mut multisig_wallet.proposals, + proposal_id, + proposal + ); + + event::emit( + CreateProposalEvent { multisig_addr, proposal_id, proposer, execute_messages } + ) + } + + fun is_proposal_expired(proposal: &Proposal): bool { + let (_, timestamp) = get_block_info(); + + if (option::is_none(&proposal.expiry_timestamp)) { + return false + }; + + let expiry = *option::borrow(&proposal.expiry_timestamp); + + return timestamp >= expiry + } + + fun vote( + votes: &mut SimpleMap, + voter: Member, + 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); + }; + } + + fun yes_vote_score( + votes: &SimpleMap, members: &vector + ): u64 { + vector::fold( + *members, + 0u64, + |acc, member| { + let m: Member = member; + let weight = + if (option::is_some(&m.tier)) { + let tier = *option::borrow(&m.tier); + tier.weight + } else { 1u64 }; + if (simple_map::contains_key(votes, &m) + && *simple_map::borrow(votes, &m)) { + acc + weight + } else { acc } + } + ) + } + + 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(proposal); + let yes_vote_score = yes_vote_score(&proposal.votes, &multisig_wallet.members); + if (status_index == 0 && is_expired) { + status_index = 2 + }; + + ProposalResponse { + multisig_addr, + proposal_id, + proposer: proposal.proposer, + proposed_height: proposal.proposed_height, + proposed_timestamp: proposal.proposed_timestamp, + expiry_timestamp: proposal.expiry_timestamp, + votes: proposal.votes, + threshold: proposal.threshold, + total_weight: proposal.total_weight, + yes_vote_score, + status: string::utf8(*vector::borrow(&STATUS, (status_index as u64))), + is_json: proposal.is_json, + execute_messages: proposal.execute_messages + } + } + + inline fun assert_uniqueness(vec: vector) { + let m = simple_map::create(); + vector::for_each(vec, |elem| simple_map::add(&mut m, elem, true)) + } + + inline fun assert_member(members: &vector
, member: &address) { + assert!( + vector::contains(members, member), + error::permission_denied(ENOT_MEMBER) + ) + } + + inline fun assert_multisig_member( + multisig_members: &vector, member: &address + ) { + let member_addresses = vector::map_ref( + multisig_members, + |multisig_member| { + let m: &Member = multisig_member; + m.address + } + ); + + assert_member(&member_addresses, member) + } + + inline fun assert_proposal(proposal: &Proposal) { + assert!( + proposal.status == 0, + error::invalid_state(EINVALID_PROPOSAL_STATUS) + ); + assert!( + !is_proposal_expired(proposal), + error::invalid_state(EPROPOSAL_EXPIRED) + ); + } + + inline fun assert_tier_config( + tiers: vector, + tier_weights: vector, + members: &vector
, + member_tiers: vector + ) { + assert!( + vector::length(&tiers) == vector::length(&tier_weights), + error::invalid_argument(EINVALID_TIERS_LENGTH) + ); + + assert!( + vector::length(members) == vector::length(&member_tiers), + error::invalid_argument(EINVALID_MEMBERS_LENGTH) + ); + + vector::for_each( + member_tiers, + |tier| assert!( + vector::contains(&tiers, &tier), + error::invalid_argument(EINVALID_MEMBER_TIERS) + ) + ); + } + + #[test_only] + use minitia_std::address; + #[test_only] + use minitia_std::block::set_block_info; + + #[test_only] + fun get_multisig_address(creator: &address, name: &String): address { + let seed = address::to_string(@minitia_std); + string::append(&mut seed, string::utf8(b"::multisig_v2::MultisigWallet")); + string::append(&mut seed, *name); + + object::create_object_address(creator, *string::bytes(&seed)) + } + + // create test_only function for create votes map + #[test_only] + fun create_votes_map(members: vector, votes: vector): + SimpleMap { + let votes_map = simple_map::create(); + let index = 0; + vector::for_each( + members, + |member| { + let vote = *vector::borrow(&votes, index); + index = index + 1; + + simple_map::add(&mut votes_map, member, vote) + } + ); + + votes_map + } + + // view functions tests + + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + fun is_exist_test( + account1: signer, account2: signer, account3: signer + ) { + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + let name = string::utf8(b"multisig wallet"); + + assert!(!is_exist(addr1, name), 1); + + create_non_weighted_multisig_account( + &account1, name, vector[addr1, addr2, addr3], 2 + ); + + assert!(is_exist(addr1, name), 1) + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x50002, location = Self)] + fun create_non_weighted_wallet_by_other( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account4, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + } + + // test multisig wallet name too long + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + #[expected_failure(abort_code = 0x2000b, location = Self)] + fun wallet_name_too_long( + account1: signer, account2: signer, account3: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8( + b"multimultimultimultimultimultimultimultimultimultimultimultimulti" + ), // 64 letters + vector[addr1, addr2, addr3], + 2 + ); + } + + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + #[expected_failure(abort_code = 0x10001, location = Self)] + fun non_weighted_invalid_threshold( + account1: signer, account2: signer, account3: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 4 + ); + } + + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + #[expected_failure(abort_code = 0x10001, location = simple_map)] + fun non_weighted_duplicate_members( + account1: signer, account2: signer, account3: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr1, addr2, addr3], + 3 + ); + } + + // test create weight multisig wallet successfully, check keys in object + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + fun create_non_weighted_wallet_success( + account1: signer, account2: signer, account3: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 3 + ); + + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + let multisig_wallet = borrow_global(multisig_addr); + assert!( + vector::length(&multisig_wallet.members) == 3, + error::invalid_state(EINVALID_MEMBERS_LENGTH) + ); + + // assert each member tier is correct + vector::for_each_ref( + &multisig_wallet.members, + |member| { + let m: &Member = member; + assert!(option::is_none(&m.tier), 1) + } + ); + + assert!( + multisig_wallet.threshold == 3, + error::invalid_state(EINVALID_THRESHOLD) + ); + + assert!( + !multisig_wallet.weighted, + error::invalid_state(1) + ); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x50002, location = Self)] + fun create_weighted_wallet_by_other( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_weighted_multisig_account( + &account4, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2, 1], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ], + 2 + ); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x10007, location = Self)] + fun weighted_invalid_tiers_length( + account1: signer, account2: signer, account3: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ], + 2 + ); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x10008, location = Self)] + fun weighted_invalid_members_length( + account1: signer, account2: signer, account3: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2, 1], + vector[addr1, addr2, addr3], + vector[string::utf8(b"admin"), string::utf8(b"member")], + 2 + ); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x10009, location = Self)] + fun weighted_invalid_members_tiers( + account1: signer, account2: signer, account3: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2, 1], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"god") + ], + 2 + ); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x10001, location = Self)] + fun weighted_invalid_threshold( + account1: signer, account2: signer, account3: signer + ) { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[10, 1], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"admin"), + string::utf8(b"member") + ], + 22 + ); + } + + // test create weight multisig wallet successfully, check keys in object + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + fun create_weighted_wallet_success( + account1: signer, account2: signer, account3: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + let member_tiers = vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ]; + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2, 1], + vector[addr1, addr2, addr3], + member_tiers, + 2 + ); + + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + let multisig_wallet = borrow_global(multisig_addr); + assert!( + vector::length(&multisig_wallet.members) == 3, + error::invalid_state(EINVALID_MEMBERS_LENGTH) + ); + + // assert each member tier is correct + let index = 0; + vector::for_each_ref( + &multisig_wallet.members, + |member| { + let tier_name = *vector::borrow(&member_tiers, index); + index = index + 1; + + let m: &Member = member; + let tier = option::borrow(&m.tier); + assert!(tier_name == tier.name, 1) + } + ); + + // assert if multisig_wallet.tiers is not none and length is 2 + let tiers = option::borrow(&multisig_wallet.tiers); + assert!( + vector::length(tiers) == 2, + error::invalid_state(EINVALID_TIERS_LENGTH) + ); + + assert!( + multisig_wallet.threshold == 2, + error::invalid_state(EINVALID_THRESHOLD) + ); + + assert!( + multisig_wallet.weighted, + error::invalid_state(1) + ); + } + + // test total_weight(members) + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + fun total_weight_test( + account1: signer, account2: signer, account3: signer + ) acquires MultisigWallet { + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2, 1], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ], + 2 + ); + + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + let multisig_wallet = borrow_global(multisig_addr); + + let total_weight = total_weight(&multisig_wallet.members); + assert!(total_weight == 4, 1); + } + + #[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 + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal( + &account4, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::none() + ); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x1000c, location = Self)] + fun invalid_list_create_proposal( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal( + &account4, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2"), string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::none() + ); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + fun create_proposal_successfully( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + set_block_info(100, 100); + + create_proposal( + &account1, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + // borrow proposal from multisig wallet + let multisig_wallet = borrow_global(multisig_addr); + let proposal = table::borrow(&multisig_wallet.proposals, 1); + + let expected_votes = simple_map::create(); + simple_map::add( + &mut expected_votes, + get_member_by_address(multisig_wallet.members, addr1), + true + ); + + assert!( + proposal.proposer == get_member_by_address(multisig_wallet.members, addr1), + 1 + ); + assert!(proposal.proposed_height == 100, 1); + assert!(proposal.proposed_timestamp == 100, 1); + assert!( + *option::borrow(&proposal.expiry_timestamp) == 199, + 1 + ); + assert!(proposal.status == 0, 1); + assert!(proposal.is_json == false, 1); + + let execute_message = vector::borrow(&proposal.execute_messages, 0); + assert!(vector::length(&execute_message.json_args) == 0, 1); + assert!( + &execute_message.args + == &vector[ + 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()) + ], + 1 + ); + + assert!(vector::length(&execute_message.type_args) == 0, 1); + assert!(execute_message.module_address == @minitia_std, 1); + assert!( + execute_message.module_name == string::utf8(b"multisig_v2"), + 1 + ); + assert!( + execute_message.function_name == string::utf8(b"update_config"), + 1 + ); + assert!( + proposal.threshold == multisig_wallet.threshold, + 1 + ); + assert!(proposal.total_weight == 3, 1); + assert!( + yes_vote_score(&proposal.votes, &multisig_wallet.members) == 1, + 1 + ); + } + + // test proposal_to_proposal_response for weight multisig wallet + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + fun proposal_to_proposal_response_weighted( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2, 1], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + set_block_info(100, 100); + + create_proposal( + &account1, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + let multisig_wallet = borrow_global(multisig_addr); + let proposal = table::borrow(&multisig_wallet.proposals, 1); + + let proposal_response = + proposal_to_proposal_response(multisig_wallet, multisig_addr, 1, proposal); + + let expected_proposal_response = ProposalResponse { + multisig_addr, + proposal_id: 1, + proposer: get_member_by_address(multisig_wallet.members, addr1), + proposed_height: 100, + proposed_timestamp: 100, + expiry_timestamp: option::some(199), + votes: proposal.votes, + threshold: 2, + total_weight: 4, + yes_vote_score: 2, + status: string::utf8(b"voting"), + is_json: false, + execute_messages: vector[ + ExecuteMessage { + module_address: @minitia_std, + module_name: string::utf8(b"multisig_v2"), + function_name: string::utf8(b"update_config"), + type_args: vector[], + args: vector[ + 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()) + ], + json_args: vector[] + } + ] + }; + + assert!( + proposal_response == expected_proposal_response, + 1 + ); + } + + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + fun proposal_with_json( + account1: signer, account2: signer, account3: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal_with_json( + &account1, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + string::utf8(b"[\"0x101\", \"0x102\", \"0x104\"]"), + string::utf8(b"\"3\""), + string::utf8(b""), + string::utf8(b"") + ] + ], + option::some(99) + ); + + let proposal = get_proposal(multisig_addr, 1); + let execute_message = vector::borrow(&proposal.execute_messages, 0); + + assert!(execute_message.module_address == @minitia_std, 0); + assert!( + execute_message.module_name == string::utf8(b"multisig_v2"), + 1 + ); + assert!( + execute_message.function_name == string::utf8(b"update_config"), + 2 + ); + assert!(execute_message.type_args == vector[], 3); + assert!( + execute_message.json_args + == vector[ + string::utf8(b"[\"0x101\", \"0x102\", \"0x104\"]"), + string::utf8(b"\"3\""), + string::utf8(b""), + string::utf8(b"") + ], + 4 + ); + assert!(execute_message.args == vector[], 5); + } + + #[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 + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + set_block_info(100, 100); + create_proposal( + &account1, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + vote_proposal(&account4, multisig_addr, 1, true); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x30004, location = Self)] + fun vote_after_proposal_expired( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + set_block_info(100, 100); + create_proposal( + &account1, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + set_block_info(100, 199); + vote_proposal(&account2, multisig_addr, 1, true); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + fun vote_proposal_of_non_weighted_multisig_successfully( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + set_block_info(100, 100); + create_proposal( + &account1, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + vote_proposal(&account1, multisig_addr, 1, true); + vote_proposal(&account2, multisig_addr, 1, false); + vote_proposal(&account3, multisig_addr, 1, true); + + let multisig_wallet = borrow_global(multisig_addr); + let proposal = table::borrow(&multisig_wallet.proposals, 1); + let proposal_response = + proposal_to_proposal_response(multisig_wallet, multisig_addr, 1, proposal); + + let expected_votes = + create_votes_map( + multisig_wallet.members, + vector[true, false, true] + ); + + assert!(proposal_response.votes == expected_votes, 1); + + assert!(proposal_response.yes_vote_score == 2, 1); + + assert!(proposal_response.total_weight == 3, 1); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + fun vote_proposal_of_weighted_multisig_successfully( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[2, 1], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + set_block_info(100, 100); + create_proposal( + &account1, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + vote_proposal(&account1, multisig_addr, 1, true); + vote_proposal(&account2, multisig_addr, 1, false); + vote_proposal(&account3, multisig_addr, 1, true); + + let multisig_wallet = borrow_global(multisig_addr); + let proposal = table::borrow(&multisig_wallet.proposals, 1); + let proposal_response = + proposal_to_proposal_response(multisig_wallet, multisig_addr, 1, proposal); + + let expected_votes = + create_votes_map( + multisig_wallet.members, + vector[true, false, true] + ); + + assert!(proposal_response.votes == expected_votes, 1); + + assert!(proposal_response.yes_vote_score == 3, 1); + + assert!(proposal_response.total_weight == 4, 1); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x50002, location = Self)] + fun execute_by_others( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal( + &account1, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + vote_proposal(&account1, multisig_addr, 1, true); + vote_proposal(&account2, multisig_addr, 1, false); + vote_proposal(&account3, multisig_addr, 1, false); + + execute_proposal(&account4, multisig_addr, 1); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x10006, location = Self)] + fun execute_on_a_non_existing_proposal( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal( + &account1, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + execute_proposal(&account1, multisig_addr, 2); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x30005, location = Self)] + fun non_weighted_multisig_execute_not_pass( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal( + &account1, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + vote_proposal(&account1, multisig_addr, 1, true); + vote_proposal(&account2, multisig_addr, 1, false); + vote_proposal(&account3, multisig_addr, 1, false); + + execute_proposal(&account1, multisig_addr, 1); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + #[expected_failure(abort_code = 0x30005, location = Self)] + fun weighted_multisig_execute_not_pass( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[3, 2], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ], + 6 + ); + + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal( + &account1, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + vote_proposal(&account1, multisig_addr, 1, true); + vote_proposal(&account2, multisig_addr, 1, false); + vote_proposal(&account3, multisig_addr, 1, true); + + execute_proposal(&account1, multisig_addr, 1); + } + + #[test( + account1 = @0x101, account2 = @0x102, account3 = @0x103, account4 = @0x104 + )] + fun execute_pass_successfully( + account1: signer, + account2: signer, + account3: signer, + account4: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + let addr4 = signer::address_of(&account4); + + create_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[string::utf8(b"admin"), string::utf8(b"member")], + vector[3, 2], + vector[addr1, addr2, addr3], + vector[ + string::utf8(b"admin"), + string::utf8(b"member"), + string::utf8(b"member") + ], + 5 + ); + + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + create_proposal( + &account1, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + 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()) + ] + ], + option::some(99) + ); + + vote_proposal(&account1, multisig_addr, 1, true); + vote_proposal(&account2, multisig_addr, 1, false); + vote_proposal(&account3, multisig_addr, 1, true); + + execute_proposal(&account1, multisig_addr, 1); + } + + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + #[expected_failure(abort_code = 0x10001, location = simple_map)] + fun update_config_duplicate_members( + account1: signer, account2: signer, account3: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + let multisig_wallet = borrow_global(multisig_addr); + let multisig_signer = + &object::generate_signer_for_extending(&multisig_wallet.extend_ref); + + update_config( + multisig_signer, + vector[addr1, addr2, addr3, addr3], + option::none(), + option::none(), + option::none(), + 3 + ); + } + + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + #[expected_failure(abort_code = 0x10001, location = Self)] + fun update_config_non_weighted_invalid_threshold( + account1: signer, account2: signer, account3: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 4 + ); + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + let multisig_wallet = borrow_global(multisig_addr); + let multisig_signer = + &object::generate_signer_for_extending(&multisig_wallet.extend_ref); + + update_config( + multisig_signer, + vector[addr1, addr2, addr3, addr3], + option::none(), + option::none(), + option::none(), + 3 + ); + } + + #[test(account1 = @0x101, account2 = @0x102, account3 = @0x103)] + fun update_config_non_weighted_successfully( + account1: signer, account2: signer, account3: signer + ) acquires MultisigWallet { + // create multisig wallet + let addr1 = signer::address_of(&account1); + let addr2 = signer::address_of(&account2); + let addr3 = signer::address_of(&account3); + + create_non_weighted_multisig_account( + &account1, + string::utf8(b"multisig wallet"), + vector[addr1, addr2, addr3], + 2 + ); + + let multisig_addr = get_multisig_address( + &addr1, &string::utf8(b"multisig wallet") + ); + + set_block_info(100, 100); + + // proposal 1 : active proposal with votes from addr1, addr2, addr3 + create_proposal( + &account1, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + std::bcs::to_bytes(&vector[addr1, addr2, addr3]), std::bcs::to_bytes( + &3u64 + ), std::bcs::to_bytes(&option::none()), std::bcs::to_bytes( + &option::none() + ), std::bcs::to_bytes(&option::none()) + ] + ], + option::some(99) + ); + + // vote on proposal 1 without execution + vote_proposal(&account1, multisig_addr, 1, true); + vote_proposal(&account2, multisig_addr, 1, false); + vote_proposal(&account3, multisig_addr, 1, true); + + // proposal 2 : expired proposal with votes from addr1, addr2, addr3 + create_proposal( + &account1, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + std::bcs::to_bytes(&vector[addr1, addr2, addr3]), + std::bcs::to_bytes(&3u64), + std::bcs::to_bytes(&option::none()), + std::bcs::to_bytes(&option::none()) + ] + ], + option::some(1) + ); + + // vote on proposal 2 without execution + vote_proposal(&account1, multisig_addr, 2, false); + vote_proposal(&account2, multisig_addr, 2, false); + vote_proposal(&account3, multisig_addr, 2, true); + + // proposal 2 is now expired + set_block_info(100, 110); + + // proposal 3 : executed proposal with votes from addr1, addr2, addr3 + create_proposal( + &account1, + multisig_addr, + vector[@minitia_std], + vector[string::utf8(b"multisig_v2")], + vector[string::utf8(b"update_config")], + vector[vector[]], + vector[ + vector[ + std::bcs::to_bytes(&vector[addr1, addr2, addr3]), + std::bcs::to_bytes(&3u64), + std::bcs::to_bytes(&option::none()), + std::bcs::to_bytes(&option::none()) + ] + ], + option::some(99) + ); + + // vote on proposal 3 with execution + vote_proposal(&account1, multisig_addr, 3, true); + vote_proposal(&account2, multisig_addr, 3, false); + vote_proposal(&account3, multisig_addr, 3, true); + execute_proposal(&account1, multisig_addr, 3); + + // update_config + let multisig_wallet = borrow_global(multisig_addr); + let multisig_signer = + &object::generate_signer_for_extending(&multisig_wallet.extend_ref); + update_config( + multisig_signer, + vector[addr2, addr3], + option::none(), + option::none(), + option::none(), + 1 + ); + + // check if multisig wallet is updated + let updated_multisig_wallet = borrow_global(multisig_addr); + assert!( + updated_multisig_wallet.members + == vector::map( + vector[addr2, addr3], + |addr| Member { address: addr, tier: option::none() } + ), + 1 + ); + assert!(updated_multisig_wallet.threshold == 1, 1); + + // proposal 1 details changed accordingly + let updated_proposal1 = get_proposal(multisig_addr, 1); + assert!(updated_proposal1.threshold == 1, 1); + assert!(updated_proposal1.total_weight == 2, 1); + assert!( + !simple_map::contains_key( + &updated_proposal1.votes, &Member { address: addr1, tier: option::none() } + ), + 1 + ); + assert!( + simple_map::contains_key( + &updated_proposal1.votes, &Member { address: addr2, tier: option::none() } + ), + 1 + ); + assert!( + simple_map::contains_key( + &updated_proposal1.votes, &Member { address: addr3, tier: option::none() } + ), + 1 + ); + + // proposal 2 (expired) details remain unchanged + let updated_proposal2 = get_proposal(multisig_addr, 2); + assert!(updated_proposal2.threshold == 2, 1); + assert!(updated_proposal2.total_weight == 3, 1); + assert!( + simple_map::contains_key( + &updated_proposal2.votes, &Member { address: addr1, tier: option::none() } + ), + 1 + ); + assert!( + simple_map::contains_key( + &updated_proposal2.votes, &Member { address: addr2, tier: option::none() } + ), + 1 + ); + assert!( + simple_map::contains_key( + &updated_proposal2.votes, &Member { address: addr3, tier: option::none() } + ), + 1 + ); + + // proposal 3 (executed) details remain unchanged + let updated_proposal3 = get_proposal(multisig_addr, 3); + assert!(updated_proposal3.threshold == 2, 1); + assert!(updated_proposal3.total_weight == 3, 1); + assert!( + simple_map::contains_key( + &updated_proposal3.votes, &Member { address: addr1, tier: option::none() } + ), + 1 + ); + assert!( + simple_map::contains_key( + &updated_proposal3.votes, &Member { address: addr2, tier: option::none() } + ), + 1 + ); + assert!( + simple_map::contains_key( + &updated_proposal3.votes, &Member { address: addr3, tier: option::none() } + ), + 1 + ); + } +} diff --git a/minitia_stdlib/sources/object.move b/minitia_stdlib/sources/object.move index 8e90c06..727283d 100644 --- a/minitia_stdlib/sources/object.move +++ b/minitia_stdlib/sources/object.move @@ -261,11 +261,7 @@ module minitia_std::object { ): 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 - ) + create_object_internal(creator_address, obj_addr, can_delete) } /// Create a new object by generating a random unique address based on transaction hash. @@ -274,11 +270,7 @@ module minitia_std::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 - ) + create_object_internal(owner_address, unique_address, can_delete) } fun create_object_internal( @@ -663,11 +655,7 @@ module minitia_std::object { public fun hero_unequip( owner: &signer, hero: Object, weapon: Object ) acquires Hero, ObjectCore { - transfer( - owner, - weapon, - signer::address_of(owner) - ); + transfer(owner, weapon, signer::address_of(owner)); let hero = borrow_global_mut(object_address(&hero)); option::extract(&mut hero.weapon); event::emit(HeroEquipEvent { weapon_id: option::none() }); diff --git a/minitia_stdlib/sources/simple_map.move b/minitia_stdlib/sources/simple_map.move index 4db63b9..4eda478 100644 --- a/minitia_stdlib/sources/simple_map.move +++ b/minitia_stdlib/sources/simple_map.move @@ -87,7 +87,9 @@ module minitia_std::simple_map { value: Value ) { let maybe_idx = find(self, &key); - assert!(option::is_none(&maybe_idx), error::invalid_argument(EKEY_ALREADY_EXISTS)); + assert!( + option::is_none(&maybe_idx), error::invalid_argument(EKEY_ALREADY_EXISTS) + ); vector::push_back(&mut self.data, Element { key, value }); } diff --git a/minitia_stdlib/sources/string_utils.move b/minitia_stdlib/sources/string_utils.move index cbeb25c..d914fcf 100644 --- a/minitia_stdlib/sources/string_utils.move +++ b/minitia_stdlib/sources/string_utils.move @@ -108,10 +108,7 @@ module minitia_std::string_utils { #[test] fun test_format() { - assert!( - to_string(&1u64) == std::string::utf8(b"1"), - 1 - ); + assert!(to_string(&1u64) == std::string::utf8(b"1"), 1); assert!( to_string(&false) == std::string::utf8(b"false"), 2 @@ -156,7 +153,13 @@ module minitia_std::string_utils { #[test] #[expected_failure(abort_code = EARGS_MISMATCH)] fun test_format_list_to_many_vals() { - format4(&b"a = {} b = {} c = {}", 1, 2, 3, 4); + format4( + &b"a = {} b = {} c = {}", + 1, + 2, + 3, + 4 + ); } #[test] @@ -188,27 +191,44 @@ module minitia_std::string_utils { #[test] #[expected_failure(abort_code = EINVALID_FORMAT)] fun test_format_unclosed_braces() { - format3(&b"a = {} b = {} c = {", 1, 2, 3); + format3( + &b"a = {} b = {} c = {", + 1, + 2, + 3 + ); } #[test] #[expected_failure(abort_code = EINVALID_FORMAT)] fun test_format_unclosed_braces_2() { - format3(&b"a = {} b = { c = {}", 1, 2, 3); + format3( + &b"a = {} b = { c = {}", + 1, + 2, + 3 + ); } #[test] #[expected_failure(abort_code = EINVALID_FORMAT)] fun test_format_unopened_braces() { - format3(&b"a = } b = {} c = {}", 1, 2, 3); + format3( + &b"a = } b = {} c = {}", + 1, + 2, + 3 + ); } #[test] fun test_format_escape_braces_works() { - let s = format3(&b"{{a = {} b = {} c = {}}}", 1, 2, 3); - assert!( - s == std::string::utf8(b"{a = 1 b = 2 c = 3}"), - 1 + let s = format3( + &b"{{a = {} b = {} c = {}}}", + 1, + 2, + 3 ); + assert!(s == std::string::utf8(b"{a = 1 b = 2 c = 3}"), 1); } } diff --git a/minitia_stdlib/sources/token/collection.move b/minitia_stdlib/sources/token/collection.move index e151d53..9c38847 100644 --- a/minitia_stdlib/sources/token/collection.move +++ b/minitia_stdlib/sources/token/collection.move @@ -248,10 +248,7 @@ module minitia_std::collection { move_to(object_signer, collection); if (option::is_some(&supply)) { - move_to( - object_signer, - option::destroy_some(supply) - ); + move_to(object_signer, option::destroy_some(supply)); let collection_addr = signer::address_of(object_signer); event::emit( CreateCollectionEvent { @@ -415,10 +412,7 @@ module minitia_std::collection { && vector::length(&res) < (limit as u64)) { let (token_id, nft) = table::next(nfts_iter); - vector::push_back( - &mut res, - NftResponse { token_id, nft: *nft } - ); + vector::push_back(&mut res, NftResponse { token_id, nft: *nft }); }; res @@ -534,8 +528,10 @@ module minitia_std::collection { assert!(count(collection) == option::some(0), 0); } - #[test(creator = @0x123, receipient = @0x456)] - entry fun test_create_and_transfer(creator: &signer, receipient: &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); @@ -561,7 +557,6 @@ module minitia_std::collection { 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) { @@ -619,21 +614,9 @@ module minitia_std::collection { ); 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 - ); - increment_supply( - collection, - string::utf8(b"2"), - @0x002 - ); - increment_supply( - collection, - string::utf8(b"3"), - @0x003 - ); + increment_supply(collection, string::utf8(b"1"), @0x001); + increment_supply(collection, string::utf8(b"2"), @0x002); + increment_supply(collection, string::utf8(b"3"), @0x003); let nfts = nfts(collection, option::none(), 5); assert!( diff --git a/minitia_stdlib/sources/token/initia_nft.move b/minitia_stdlib/sources/token/initia_nft.move index 54d7dc5..9d7d9af 100644 --- a/minitia_stdlib/sources/token/initia_nft.move +++ b/minitia_stdlib/sources/token/initia_nft.move @@ -172,11 +172,7 @@ module minitia_std::initia_nft { 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)); } } @@ -598,11 +594,7 @@ module minitia_std::initia_nft { fun test_set_immutable_collection_description(creator: &signer) acquires InitiaNftCollection { 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"") - ); + set_collection_description(creator, collection, string::utf8(b"")); } #[test(creator = @0x123, noncreator = @0x456)] @@ -612,11 +604,7 @@ module minitia_std::initia_nft { ) 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"") - ); + set_collection_description(noncreator, collection, string::utf8(b"")); } #[test(creator = @0x123)] @@ -634,11 +622,7 @@ module minitia_std::initia_nft { fun test_set_immutable_collection_uri(creator: &signer) acquires InitiaNftCollection { let collection_name = string::utf8(b"collection name"); let collection = create_collection_helper(creator, collection_name, false); - set_collection_uri( - creator, - collection, - string::utf8(b"") - ); + set_collection_uri(creator, collection, string::utf8(b"")); } #[test(creator = @0x123, noncreator = @0x456)] @@ -648,11 +632,7 @@ module minitia_std::initia_nft { ) 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"") - ); + set_collection_uri(noncreator, collection, string::utf8(b"")); } #[test(creator = @0x123)] diff --git a/minitia_stdlib/sources/token/nft.move b/minitia_stdlib/sources/token/nft.move index a786f60..81f0438 100644 --- a/minitia_stdlib/sources/token/nft.move +++ b/minitia_stdlib/sources/token/nft.move @@ -391,11 +391,7 @@ module minitia_std::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_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); } @@ -409,18 +405,10 @@ module minitia_std::nft { 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 - ); + let nft_addr = create_nft_address(creator_address, &collection_name, &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) - ); + object::transfer(creator, nft, signer::address_of(trader)); assert!( object::owner(nft) == signer::address_of(trader), 1 @@ -466,11 +454,7 @@ module minitia_std::nft { string::utf8(b"nft uri") ); - let nft_addr = create_nft_address( - creator_address, - &collection_name, - &token_id - ); + let nft_addr = create_nft_address(creator_address, &collection_name, &token_id); let nft = object::address_to_object(nft_addr); assert!( option::some(expected_royalty) == royalty(nft), @@ -501,11 +485,7 @@ module minitia_std::nft { ); let creator_address = signer::address_of(creator); - let nft_addr = create_nft_address( - creator_address, - &collection_name, - &token_id - ); + let nft_addr = create_nft_address(creator_address, &collection_name, &token_id); let nft = object::address_to_object(nft_addr); assert!(option::none() == royalty(nft), 0); } @@ -548,7 +528,9 @@ module minitia_std::nft { let token_id = string::utf8(b"nft token_id"); create_collection_helper(creator, collection_name, 1); - let mutator_ref = create_nft_with_mutation_ref(creator, collection_name, token_id); + let mutator_ref = create_nft_with_mutation_ref( + creator, collection_name, token_id + ); let nft = object::address_to_object( create_nft_address( @@ -570,7 +552,9 @@ module minitia_std::nft { let token_id = string::utf8(b"nft token_id"); create_collection_helper(creator, collection_name, 1); - let mutator_ref = create_nft_with_mutation_ref(creator, collection_name, token_id); + let mutator_ref = create_nft_with_mutation_ref( + creator, collection_name, token_id + ); let nft = object::address_to_object( create_nft_address( diff --git a/minitia_stdlib/sources/token/property_map.move b/minitia_stdlib/sources/token/property_map.move index f61addd..901f362 100644 --- a/minitia_stdlib/sources/token/property_map.move +++ b/minitia_stdlib/sources/token/property_map.move @@ -439,10 +439,7 @@ module minitia_std::property_map { 6 ); assert!( - read_bytes( - object, - &string::utf8(b"vector") - ) == vector[0x01], + read_bytes(object, &string::utf8(b"vector")) == vector[0x01], 7 ); assert!( @@ -455,37 +452,13 @@ module minitia_std::property_map { assert!(length(object) == 9, 9); - update_typed( - &mutator, - &string::utf8(b"bool"), - false - ); + update_typed(&mutator, &string::utf8(b"bool"), false); update_typed(&mutator, &string::utf8(b"u8"), 0x21); - update_typed( - &mutator, - &string::utf8(b"u16"), - 0x22 - ); - update_typed( - &mutator, - &string::utf8(b"u32"), - 0x23 - ); - update_typed( - &mutator, - &string::utf8(b"u64"), - 0x24 - ); - update_typed( - &mutator, - &string::utf8(b"u128"), - 0x25 - ); - update_typed( - &mutator, - &string::utf8(b"u256"), - 0x26 - ); + update_typed(&mutator, &string::utf8(b"u16"), 0x22); + update_typed(&mutator, &string::utf8(b"u32"), 0x23); + update_typed(&mutator, &string::utf8(b"u64"), 0x24); + update_typed(&mutator, &string::utf8(b"u128"), 0x25); + update_typed(&mutator, &string::utf8(b"u256"), 0x26); update_typed>( &mutator, &string::utf8(b"vector"), @@ -526,10 +499,7 @@ module minitia_std::property_map { 16 ); assert!( - read_bytes( - object, - &string::utf8(b"vector") - ) == vector[0x02], + read_bytes(object, &string::utf8(b"vector")) == vector[0x02], 17 ); assert!( @@ -557,25 +527,13 @@ module minitia_std::property_map { assert!(length(object) == 0, 20); - add_typed( - &mutator, - string::utf8(b"bool"), - false - ); + add_typed(&mutator, string::utf8(b"bool"), false); add_typed(&mutator, string::utf8(b"u8"), 0x21); add_typed(&mutator, string::utf8(b"u16"), 0x22); add_typed(&mutator, string::utf8(b"u32"), 0x23); add_typed(&mutator, string::utf8(b"u64"), 0x24); - add_typed( - &mutator, - string::utf8(b"u128"), - 0x25 - ); - add_typed( - &mutator, - string::utf8(b"u256"), - 0x26 - ); + add_typed(&mutator, string::utf8(b"u128"), 0x25); + add_typed(&mutator, string::utf8(b"u256"), 0x26); add_typed>( &mutator, string::utf8(b"vector"), @@ -616,10 +574,7 @@ module minitia_std::property_map { 27 ); assert!( - read_bytes( - object, - &string::utf8(b"vector") - ) == vector[0x02], + read_bytes(object, &string::utf8(b"vector")) == vector[0x02], 28 ); assert!( @@ -732,10 +687,7 @@ module minitia_std::property_map { 38 ); assert!( - read_bytes( - object, - &string::utf8(b"vector") - ) == vector[0x01], + read_bytes(object, &string::utf8(b"vector")) == vector[0x01], 39 ); assert!( @@ -832,10 +784,7 @@ module minitia_std::property_map { 16 ); assert!( - read_bytes( - object, - &string::utf8(b"vector") - ) == vector[0x02], + read_bytes(object, &string::utf8(b"vector")) == vector[0x02], 17 ); assert!( diff --git a/minitia_stdlib/sources/token/royalty.move b/minitia_stdlib/sources/token/royalty.move index 7fe6f29..78c99ce 100644 --- a/minitia_stdlib/sources/token/royalty.move +++ b/minitia_stdlib/sources/token/royalty.move @@ -117,10 +117,7 @@ module minitia_std::royalty { generate_mutator_ref(object::generate_extend_ref(&constructor_ref)); let update_royalty = create(bigdecimal::from_ratio_u64(2, 5), @0x456); update(&mutator_ref, update_royalty); - assert!( - option::some(update_royalty) == get(object), - 3 - ); + assert!(option::some(update_royalty) == get(object), 3); assert!( royalty(&update_royalty) == bigdecimal::from_ratio_u64(2, 5), 4 @@ -139,10 +136,7 @@ module minitia_std::royalty { generate_mutator_ref(object::generate_extend_ref(&constructor_ref)); let update_royalty = create(bigdecimal::from_ratio_u64(1, 5), @0x123); update(&mutator_ref, update_royalty); - assert!( - option::some(update_royalty) == get(object), - 1 - ); + assert!(option::some(update_royalty) == get(object), 1); } #[test] diff --git a/minitia_stdlib/sources/token/simple_nft.move b/minitia_stdlib/sources/token/simple_nft.move index 43cf4b4..d901b16 100644 --- a/minitia_stdlib/sources/token/simple_nft.move +++ b/minitia_stdlib/sources/token/simple_nft.move @@ -126,11 +126,7 @@ module minitia_std::simple_nft { 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)); } } @@ -315,11 +311,7 @@ module minitia_std::simple_nft { error::permission_denied(EPROPERTIES_NOT_MUTABLE) ); - property_map::update_typed( - &simple_nft.property_mutator_ref, - &key, - value - ); + property_map::update_typed(&simple_nft.property_mutator_ref, &key, value); } // Collection accessors diff --git a/minitia_stdlib/sources/token/soul_bound_token.move b/minitia_stdlib/sources/token/soul_bound_token.move index 727f65a..5e4afd3 100644 --- a/minitia_stdlib/sources/token/soul_bound_token.move +++ b/minitia_stdlib/sources/token/soul_bound_token.move @@ -567,12 +567,7 @@ module minitia_std::soul_bound_token { let nft_name = string::utf8(b"nft name"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); let description = string::utf8(b"not"); assert!(nft::description(nft) != description, 0); @@ -589,12 +584,7 @@ module minitia_std::soul_bound_token { let nft_name = string::utf8(b"nft name"); create_collection_helper(creator, collection_name, false); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); set_description(creator, nft, string::utf8(b"")); } @@ -608,12 +598,7 @@ module minitia_std::soul_bound_token { let nft_name = string::utf8(b"nft name"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); let description = string::utf8(b"not"); set_description(noncreator, nft, description); @@ -625,12 +610,7 @@ module minitia_std::soul_bound_token { let nft_name = string::utf8(b"nft name"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); let uri = string::utf8(b"not"); assert!(nft::uri(nft) != uri, 0); @@ -645,12 +625,7 @@ module minitia_std::soul_bound_token { let nft_name = string::utf8(b"nft name"); create_collection_helper(creator, collection_name, false); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); set_uri(creator, nft, string::utf8(b"")); } @@ -664,12 +639,7 @@ module minitia_std::soul_bound_token { let nft_name = string::utf8(b"nft name"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); let uri = string::utf8(b"not"); set_uri(noncreator, nft, uri); @@ -698,11 +668,7 @@ module minitia_std::soul_bound_token { ) 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"") - ); + set_collection_description(creator, collection, string::utf8(b"")); } #[test(creator = @0x123, noncreator = @0x456)] @@ -712,11 +678,7 @@ module minitia_std::soul_bound_token { ) 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"") - ); + set_collection_description(noncreator, collection, string::utf8(b"")); } #[test(creator = @0x123)] @@ -734,11 +696,7 @@ module minitia_std::soul_bound_token { fun test_set_immutable_collection_uri(creator: &signer) acquires SoulBoundTokenCollection { let collection_name = string::utf8(b"collection name"); let collection = create_collection_helper(creator, collection_name, false); - set_collection_uri( - creator, - collection, - string::utf8(b"") - ); + set_collection_uri(creator, collection, string::utf8(b"")); } #[test(creator = @0x123, noncreator = @0x456)] @@ -748,11 +706,7 @@ module minitia_std::soul_bound_token { ) 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"") - ); + set_collection_uri(noncreator, collection, string::utf8(b"")); } #[test(creator = @0x123)] @@ -763,12 +717,7 @@ module minitia_std::soul_bound_token { let property_type = string::utf8(b"u8"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); add_property( creator, nft, @@ -790,12 +739,7 @@ module minitia_std::soul_bound_token { let property_name = string::utf8(b"u8"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); add_typed_property(creator, nft, property_name, 0x8); assert!( @@ -812,12 +756,7 @@ module minitia_std::soul_bound_token { let property_type = string::utf8(b"bool"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); update_property( creator, nft, @@ -841,12 +780,7 @@ module minitia_std::soul_bound_token { let property_name = string::utf8(b"bool"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); update_typed_property(creator, nft, property_name, false); assert!( @@ -862,12 +796,7 @@ module minitia_std::soul_bound_token { let property_name = string::utf8(b"bool"); create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); remove_property(creator, nft, property_name); } @@ -877,12 +806,7 @@ module minitia_std::soul_bound_token { let nft_name = string::utf8(b"nft name"); let collection = create_collection_helper(creator, collection_name, true); - let nft = mint_helper( - creator, - collection_name, - nft_name, - @0x123 - ); + let nft = mint_helper(creator, collection_name, nft_name, @0x123); let royalty_before = option::extract(&mut nft::royalty(nft)); set_collection_royalties_call( diff --git a/minitia_stdlib/sources/transaction_context.move b/minitia_stdlib/sources/transaction_context.move index b8f8efe..9a384b8 100644 --- a/minitia_stdlib/sources/transaction_context.move +++ b/minitia_stdlib/sources/transaction_context.move @@ -34,10 +34,7 @@ module minitia_std::transaction_context { let count: u64 = 50; while (i < count) { i = i + 1; - vector::push_back( - &mut addrs, - generate_unique_address() - ); + vector::push_back(&mut addrs, generate_unique_address()); }; i = 0; diff --git a/minitia_stdlib/sources/type_info.move b/minitia_stdlib/sources/type_info.move index 8cfd1fd..8349a37 100644 --- a/minitia_stdlib/sources/type_info.move +++ b/minitia_stdlib/sources/type_info.move @@ -26,10 +26,7 @@ module minitia_std::type_info { #[test] fun test() { let type_info = type_of(); - assert!( - account_address(&type_info) == @minitia_std, - 0 - ); + assert!(account_address(&type_info) == @minitia_std, 0); assert!(module_name(&type_info) == b"type_info", 1); assert!(struct_name(&type_info) == b"TypeInfo", 2); } diff --git a/minitia_stdlib/sources/vip/score.move b/minitia_stdlib/sources/vip/score.move index d3d4f3e..24f69b0 100644 --- a/minitia_stdlib/sources/vip/score.move +++ b/minitia_stdlib/sources/vip/score.move @@ -372,11 +372,7 @@ module minitia_std::vip_score { !simple_map::contains_key(&module_store.deployers, &deployer), error::invalid_argument(EDEPLOYER_ALREADY_ADDED) ); - simple_map::add( - &mut module_store.deployers, - deployer, - true - ); + simple_map::add(&mut module_store.deployers, deployer, true); event::emit(DeployerAddedEvent { deployer: deployer }) } @@ -475,12 +471,7 @@ module minitia_std::vip_score { init_module_for_test(); add_deployer_script(chain, signer::address_of(deployer)); - update_score_script( - deployer, - 1, - vector[@0x123, @0x234], - vector[] - ); + update_score_script(deployer, 1, vector[@0x123, @0x234], vector[]); } #[test(chain = @0x1, deployer = @0x2, user = @0x123)] diff --git a/minitia_stdlib/tests/deflation_token_tests.move b/minitia_stdlib/tests/deflation_token_tests.move index d5c6dc4..a9f0bf6 100644 --- a/minitia_stdlib/tests/deflation_token_tests.move +++ b/minitia_stdlib/tests/deflation_token_tests.move @@ -333,7 +333,10 @@ module 0xcafe::deflation_token_tests { assert!(primary_fungible_store::balance(aaron_address, metadata) == 69, 4); primary_fungible_store::transfer_with_ref( - &transfer_ref, aaron_address, creator_address, 20 + &transfer_ref, + aaron_address, + creator_address, + 20 ); assert!(primary_fungible_store::balance(creator_address, metadata) == 42, 3); diff --git a/minitia_stdlib/tests/simple_dispatchable_token_pfs_tests.move b/minitia_stdlib/tests/simple_dispatchable_token_pfs_tests.move index 81b42c6..0d37792 100644 --- a/minitia_stdlib/tests/simple_dispatchable_token_pfs_tests.move +++ b/minitia_stdlib/tests/simple_dispatchable_token_pfs_tests.move @@ -62,7 +62,12 @@ module minitia_std::simple_token_pfs_tests { assert!(is_frozen(aaron_address, metadata), 5); let fa = withdraw_with_ref(&transfer_ref, aaron_address, 30); deposit_with_ref(&transfer_ref, aaron_address, fa); - transfer_with_ref(&transfer_ref, aaron_address, creator_address, 20); + transfer_with_ref( + &transfer_ref, + aaron_address, + creator_address, + 20 + ); set_frozen_flag(&transfer_ref, aaron_address, false); assert!(!is_frozen(aaron_address, metadata), 6); burn(&burn_ref, aaron_address, 50); diff --git a/minitia_stdlib/tests/ten_x_token_tests.move b/minitia_stdlib/tests/ten_x_token_tests.move index cffbbf2..ae6f086 100644 --- a/minitia_stdlib/tests/ten_x_token_tests.move +++ b/minitia_stdlib/tests/ten_x_token_tests.move @@ -31,7 +31,8 @@ module minitia_std::ten_x_token_tests { // The derived supply is 10x assert!( - dispatchable_fungible_asset::derived_supply(metadata) == option::some(1000), 5 + dispatchable_fungible_asset::derived_supply(metadata) == option::some(1000), + 5 ); } } diff --git a/move_nursery/sources/capability.move b/move_nursery/sources/capability.move index 136c75f..868f892 100644 --- a/move_nursery/sources/capability.move +++ b/move_nursery/sources/capability.move @@ -184,10 +184,7 @@ module std::capability { ) acquires CapState { let addr = signer::address_of(to); if (exists>(addr)) return; - move_to( - to, - CapDelegateState { root: cap.root } - ); + move_to(to, CapDelegateState { root: cap.root }); add_element( &mut borrow_global_mut>(cap.root).delegates, addr diff --git a/move_stdlib/sources/fixed_point32.move b/move_stdlib/sources/fixed_point32.move index 8fd6d8f..9c71ca3 100644 --- a/move_stdlib/sources/fixed_point32.move +++ b/move_stdlib/sources/fixed_point32.move @@ -115,7 +115,10 @@ 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); diff --git a/move_stdlib/sources/vector.move b/move_stdlib/sources/vector.move index 2ad413d..ff5706a 100644 --- a/move_stdlib/sources/vector.move +++ b/move_stdlib/sources/vector.move @@ -251,14 +251,10 @@ module std::vector { if (i >= len) abort EINDEX_OUT_OF_BOUNDS; len = len - 1; - while (i < len) swap( - v, - i, - { - i = i + 1; - i - } - ); + while (i < len) swap(v, i, { + i = i + 1; + i + }); pop_back(v) } @@ -652,7 +648,10 @@ module std::vector { public fun slice( v: &vector, start: u64, end: u64 ): vector { - assert!(start <= end && end <= length(v), EINVALID_SLICE_RANGE); + assert!( + start <= end && end <= length(v), + EINVALID_SLICE_RANGE + ); let vec = vector[]; while (start < end) {