From e3a2c82fe3548ee8d72f40b19b3660b37f07ef1b Mon Sep 17 00:00:00 2001 From: lispking Date: Sun, 1 Dec 2024 22:05:08 +0800 Subject: [PATCH 1/9] feat: support batch harvest for grow_bitcoin --- apps/grow_bitcoin/sources/grow_bitcoin.move | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/apps/grow_bitcoin/sources/grow_bitcoin.move b/apps/grow_bitcoin/sources/grow_bitcoin.move index 95ce65f128..2b0bb2f499 100644 --- a/apps/grow_bitcoin/sources/grow_bitcoin.move +++ b/apps/grow_bitcoin/sources/grow_bitcoin.move @@ -6,6 +6,7 @@ module grow_bitcoin::grow_bitcoin { use std::string::{Self, String}; use std::option; use std::u64; + use std::vector; use bitcoin_move::bbn; use bitcoin_move::bbn::BBNStakeSeal; use bitcoin_move::types; @@ -416,6 +417,18 @@ module grow_bitcoin::grow_bitcoin { withdraw_token } + /// Harvest yield farming token from stake + public entry fun batch_harvest(signer:&signer, assets: vector) { + let len = vector::length(&assets); + let i = 0; + while (i < len) { + let asset_id = *vector::borrow(&assets, i); + let coin = do_harvest(signer, asset_id); + account_coin_store::deposit(sender(), coin); + i = i + 1; + } + } + /// Harvest yield farming token from stake public entry fun harvest(signer:&signer, asset: &mut Object) { let coin = do_harvest(signer, object::id(asset)); From c768f6992aa85fa73fd9ee0fc7e132ae8873aaee Mon Sep 17 00:00:00 2001 From: lispking Date: Sun, 1 Dec 2024 23:05:33 +0800 Subject: [PATCH 2/9] update: se object::borrow_mut_object to check the ObjectID type and the ownership --- apps/grow_bitcoin/sources/grow_bitcoin.move | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/grow_bitcoin/sources/grow_bitcoin.move b/apps/grow_bitcoin/sources/grow_bitcoin.move index 2b0bb2f499..c2a9cd484e 100644 --- a/apps/grow_bitcoin/sources/grow_bitcoin.move +++ b/apps/grow_bitcoin/sources/grow_bitcoin.move @@ -423,7 +423,8 @@ module grow_bitcoin::grow_bitcoin { let i = 0; while (i < len) { let asset_id = *vector::borrow(&assets, i); - let coin = do_harvest(signer, asset_id); + let utxo_obj = object::borrow_mut_object(signer, asset_id); + let coin = do_harvest(signer, object::id(utxo_obj)); account_coin_store::deposit(sender(), coin); i = i + 1; } From 79bed2ace5619a1b4491439becfada258a7a5def Mon Sep 17 00:00:00 2001 From: lispking Date: Mon, 2 Dec 2024 23:44:37 +0800 Subject: [PATCH 3/9] feat: support batch stake and unstake --- apps/grow_bitcoin/sources/grow_bitcoin.move | 72 +++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/apps/grow_bitcoin/sources/grow_bitcoin.move b/apps/grow_bitcoin/sources/grow_bitcoin.move index c2a9cd484e..8a04cb5948 100644 --- a/apps/grow_bitcoin/sources/grow_bitcoin.move +++ b/apps/grow_bitcoin/sources/grow_bitcoin.move @@ -270,6 +270,25 @@ module grow_bitcoin::grow_bitcoin { farming_asset.alive = alive; } + /// Supports batch invocation by stake users, allowing multiple assets to be staked to receive yield farming tokens + public entry fun batch_stake( + signer: &signer, + assets: vector, + ) { + let len = vector::length(&assets); + let i = 0; + while (i < len) { + let asset_id = *vector::borrow(&assets, i); + let asset = object::borrow_mut_object(signer, asset_id); + assert!(!utxo::contains_temp_state(asset), ErrorAlreadyStaked); + utxo::add_temp_state(asset, StakeInfo {}); + let utxo_value = value( object::borrow(asset)); + let asset_weight = utxo_value * calculate_time_lock_weight(0); + do_stake(signer, asset, utxo_value, asset_weight); + i = i + 1; + } + } + /// Call by stake user, staking amount of asset in order to get yield farming token public entry fun stake( signer: &signer, @@ -282,6 +301,28 @@ module grow_bitcoin::grow_bitcoin { do_stake(signer, asset, utxo_value, asset_weight); } + /// Supports batch invocation by stake users, allowing multiple assets to be staked to receive yield farming tokens + public entry fun batch_stake_bbn( + signer: &signer, + assets: vector, + ) { + let len = vector::length(&assets); + let i = 0; + while (i < len) { + let asset_id = *vector::borrow(&assets, i); + let asset = object::borrow_mut_object(signer, asset_id); + assert!(!bbn::contains_temp_state(asset), ErrorAlreadyStaked); + bbn::add_temp_state(asset, StakeInfo {}); + let bbn_stake_seal = object::borrow(asset); + let stake_value = bbn::staking_value(bbn_stake_seal); + let asset_weight = stake_value * calculate_time_lock_weight( + (((bbn::staking_time(bbn_stake_seal) as u64) + bbn::block_height(bbn_stake_seal)) as u32) + ); + do_stake(signer, asset, stake_value, asset_weight); + i = i + 1; + } + } + public entry fun stake_bbn( signer: &signer, asset: &mut Object, @@ -365,6 +406,23 @@ module grow_bitcoin::grow_bitcoin { table::add(&mut farming_asset.stake_table, asset_id, account); } + /// Supports batch invocation by stake users, allowing multiple assets to be unstaked to receive yield farming tokens + public entry fun batch_unstake( + signer: &signer, + assets: vector, + ) { + let len = vector::length(&assets); + let i = 0; + while (i < len) { + let asset_id = *vector::borrow(&assets, i); + let asset = object::borrow_mut_object(signer, asset_id); + let coin = do_unstake(signer, object::id(asset)); + utxo::remove_temp_state(asset); + account_coin_store::deposit(sender(), coin); + i = i + 1; + } + } + /// Unstake asset from farming pool public entry fun unstake(signer: &signer, asset: &mut Object) { let coin = do_unstake(signer, object::id(asset)); @@ -372,6 +430,20 @@ module grow_bitcoin::grow_bitcoin { account_coin_store::deposit(sender(), coin); } + /// Supports batch invocation by stake users, allowing multiple assets to be unstaked to receive yield farming tokens + public entry fun batch_unstake_bbn(signer: &signer, assets: vector) { + let len = vector::length(&assets); + let i = 0; + while (i < len) { + let asset_id = *vector::borrow(&assets, i); + let asset = object::borrow_mut_object(signer, asset_id); + let coin = do_unstake(signer, object::id(asset)); + bbn::remove_temp_state(asset); + account_coin_store::deposit(sender(), coin); + i = i + 1; + } + } + public entry fun unstake_bbn(signer: &signer, asset: &mut Object) { // TODO check bbn stake seal is expired let coin = do_unstake(signer, object::id(asset)); From 8a648a15b237d0135124c9716ffc0fc7f57c7984 Mon Sep 17 00:00:00 2001 From: lispking Date: Mon, 2 Dec 2024 23:50:42 +0800 Subject: [PATCH 4/9] make code tidy --- apps/grow_bitcoin/sources/grow_bitcoin.move | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/grow_bitcoin/sources/grow_bitcoin.move b/apps/grow_bitcoin/sources/grow_bitcoin.move index 8a04cb5948..5afa606fc4 100644 --- a/apps/grow_bitcoin/sources/grow_bitcoin.move +++ b/apps/grow_bitcoin/sources/grow_bitcoin.move @@ -282,7 +282,7 @@ module grow_bitcoin::grow_bitcoin { let asset = object::borrow_mut_object(signer, asset_id); assert!(!utxo::contains_temp_state(asset), ErrorAlreadyStaked); utxo::add_temp_state(asset, StakeInfo {}); - let utxo_value = value( object::borrow(asset)); + let utxo_value = value(object::borrow(asset)); let asset_weight = utxo_value * calculate_time_lock_weight(0); do_stake(signer, asset, utxo_value, asset_weight); i = i + 1; @@ -296,7 +296,7 @@ module grow_bitcoin::grow_bitcoin { ) { assert!(!utxo::contains_temp_state(asset), ErrorAlreadyStaked); utxo::add_temp_state(asset, StakeInfo {}); - let utxo_value = value( object::borrow(asset)); + let utxo_value = value(object::borrow(asset)); let asset_weight = utxo_value * calculate_time_lock_weight(0); do_stake(signer, asset, utxo_value, asset_weight); } From a91b0857c6df326eadb471466d2bd6b535e1d5b0 Mon Sep 17 00:00:00 2001 From: lispking Date: Tue, 3 Dec 2024 00:43:46 +0800 Subject: [PATCH 5/9] add batch_stake ut --- apps/grow_bitcoin/sources/grow_bitcoin.move | 38 +++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/apps/grow_bitcoin/sources/grow_bitcoin.move b/apps/grow_bitcoin/sources/grow_bitcoin.move index 5afa606fc4..72bee40136 100644 --- a/apps/grow_bitcoin/sources/grow_bitcoin.move +++ b/apps/grow_bitcoin/sources/grow_bitcoin.move @@ -815,4 +815,42 @@ module grow_bitcoin::grow_bitcoin { assert!(weight == 22, 0); assert!(weight2 == 13, 0) } + + #[test(sender=@0x42)] + fun test_batch_stake(sender: signer) { + let owner_addr = signer::address_of(&sender); + bitcoin_move::genesis::init_for_test(); + add_latest_block(100, @0x77dfc2fe598419b00641c296181a96cf16943697f573480b023b77cce82ada21); + init(); + let _admin_cap = app_admin::admin::init_for_test(); + //deploy(1, 0, 200, admin_cap); + let seconds = 100; + let tx_id = @0x77dfc2fe598419b00641c296181a96cf16943697f573480b023b77cce82ada21; + let sat_value = 100000000; + let utxo = utxo::new_for_testing(tx_id, 0u32, sat_value); + let utxo2 = utxo::new_for_testing(tx_id, 1u32, sat_value); + let utxo_id = object::id(&utxo); + let utxo_id2 = object::id(&utxo2); + + utxo::transfer_for_testing(utxo, owner_addr); + utxo::transfer_for_testing(utxo2, owner_addr); + + timestamp::fast_forward_seconds_for_test(seconds); + batch_stake(&sender, vector[utxo_id, utxo_id2]); + + let (total_value, total_weight) = query_total_stake(); + assert!(total_value == 2 * sat_value, 1); + assert!(total_weight == 2 * sat_value * calculate_time_lock_weight(0), 2); + timestamp::fast_forward_seconds_for_test(seconds); + let amount = query_gov_token_amount(utxo_id); + let amount2 = query_gov_token_amount(utxo_id2); + assert!(amount == 2025450, 1); + assert!(amount2 == 675150, 2); + + batch_unstake(&sender, vector[utxo_id, utxo_id2]); + let amount = query_gov_token_amount(utxo_id); + assert!(amount == 0, 3); + let amount2 = query_gov_token_amount(utxo_id2); + assert!(amount2 == 0, 4); + } } \ No newline at end of file From 9779b5971a0d78fab92c012f857afafb4a9c6bb0 Mon Sep 17 00:00:00 2001 From: lispking Date: Tue, 3 Dec 2024 00:47:53 +0800 Subject: [PATCH 6/9] make code tidy --- apps/grow_bitcoin/sources/grow_bitcoin.move | 26 ++++----------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/apps/grow_bitcoin/sources/grow_bitcoin.move b/apps/grow_bitcoin/sources/grow_bitcoin.move index 72bee40136..2f6a624c30 100644 --- a/apps/grow_bitcoin/sources/grow_bitcoin.move +++ b/apps/grow_bitcoin/sources/grow_bitcoin.move @@ -280,11 +280,7 @@ module grow_bitcoin::grow_bitcoin { while (i < len) { let asset_id = *vector::borrow(&assets, i); let asset = object::borrow_mut_object(signer, asset_id); - assert!(!utxo::contains_temp_state(asset), ErrorAlreadyStaked); - utxo::add_temp_state(asset, StakeInfo {}); - let utxo_value = value(object::borrow(asset)); - let asset_weight = utxo_value * calculate_time_lock_weight(0); - do_stake(signer, asset, utxo_value, asset_weight); + stake(signer, asset); i = i + 1; } } @@ -311,14 +307,7 @@ module grow_bitcoin::grow_bitcoin { while (i < len) { let asset_id = *vector::borrow(&assets, i); let asset = object::borrow_mut_object(signer, asset_id); - assert!(!bbn::contains_temp_state(asset), ErrorAlreadyStaked); - bbn::add_temp_state(asset, StakeInfo {}); - let bbn_stake_seal = object::borrow(asset); - let stake_value = bbn::staking_value(bbn_stake_seal); - let asset_weight = stake_value * calculate_time_lock_weight( - (((bbn::staking_time(bbn_stake_seal) as u64) + bbn::block_height(bbn_stake_seal)) as u32) - ); - do_stake(signer, asset, stake_value, asset_weight); + stake_bbn(signer, asset); i = i + 1; } } @@ -416,9 +405,7 @@ module grow_bitcoin::grow_bitcoin { while (i < len) { let asset_id = *vector::borrow(&assets, i); let asset = object::borrow_mut_object(signer, asset_id); - let coin = do_unstake(signer, object::id(asset)); - utxo::remove_temp_state(asset); - account_coin_store::deposit(sender(), coin); + unstake(signer, asset); i = i + 1; } } @@ -437,9 +424,7 @@ module grow_bitcoin::grow_bitcoin { while (i < len) { let asset_id = *vector::borrow(&assets, i); let asset = object::borrow_mut_object(signer, asset_id); - let coin = do_unstake(signer, object::id(asset)); - bbn::remove_temp_state(asset); - account_coin_store::deposit(sender(), coin); + unstake_bbn(signer, asset); i = i + 1; } } @@ -496,8 +481,7 @@ module grow_bitcoin::grow_bitcoin { while (i < len) { let asset_id = *vector::borrow(&assets, i); let utxo_obj = object::borrow_mut_object(signer, asset_id); - let coin = do_harvest(signer, object::id(utxo_obj)); - account_coin_store::deposit(sender(), coin); + harvest(signer, utxo_obj); i = i + 1; } } From f52c11fe23fa3f5f152451294c766e4f7b700ee6 Mon Sep 17 00:00:00 2001 From: lispking Date: Tue, 3 Dec 2024 00:59:13 +0800 Subject: [PATCH 7/9] update: merge coin and one send --- apps/grow_bitcoin/sources/grow_bitcoin.move | 24 +++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/apps/grow_bitcoin/sources/grow_bitcoin.move b/apps/grow_bitcoin/sources/grow_bitcoin.move index 2f6a624c30..f99bde1f82 100644 --- a/apps/grow_bitcoin/sources/grow_bitcoin.move +++ b/apps/grow_bitcoin/sources/grow_bitcoin.move @@ -402,12 +402,16 @@ module grow_bitcoin::grow_bitcoin { ) { let len = vector::length(&assets); let i = 0; + let total_coin = coin::zero(); while (i < len) { let asset_id = *vector::borrow(&assets, i); let asset = object::borrow_mut_object(signer, asset_id); - unstake(signer, asset); + let coin = do_unstake(signer, object::id(asset)); + utxo::remove_temp_state(asset); + coin::merge(&mut total_coin, coin); i = i + 1; - } + }; + account_coin_store::deposit(sender(), total_coin); } /// Unstake asset from farming pool @@ -421,12 +425,16 @@ module grow_bitcoin::grow_bitcoin { public entry fun batch_unstake_bbn(signer: &signer, assets: vector) { let len = vector::length(&assets); let i = 0; + let total_coin = coin::zero(); while (i < len) { let asset_id = *vector::borrow(&assets, i); let asset = object::borrow_mut_object(signer, asset_id); - unstake_bbn(signer, asset); + let coin = do_unstake(signer, object::id(asset)); + bbn::remove_temp_state(asset); + coin::merge(&mut total_coin, coin); i = i + 1; - } + }; + account_coin_store::deposit(sender(), total_coin); } public entry fun unstake_bbn(signer: &signer, asset: &mut Object) { @@ -478,12 +486,16 @@ module grow_bitcoin::grow_bitcoin { public entry fun batch_harvest(signer:&signer, assets: vector) { let len = vector::length(&assets); let i = 0; + let total_coin = coin::zero(); while (i < len) { let asset_id = *vector::borrow(&assets, i); let utxo_obj = object::borrow_mut_object(signer, asset_id); - harvest(signer, utxo_obj); + let coin = do_harvest(signer, object::id(utxo_obj)); + utxo::remove_temp_state(utxo_obj); + coin::merge(&mut total_coin, coin); i = i + 1; - } + }; + account_coin_store::deposit(sender(), total_coin); } /// Harvest yield farming token from stake From fc40a0b7b31c1a56cdcb14c97f4f7b5a3b45b5b3 Mon Sep 17 00:00:00 2001 From: lispking Date: Tue, 3 Dec 2024 09:49:22 +0800 Subject: [PATCH 8/9] fix: Get the address from the signer via signer::address_of(signer) not sender() --- apps/grow_bitcoin/sources/grow_bitcoin.move | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/apps/grow_bitcoin/sources/grow_bitcoin.move b/apps/grow_bitcoin/sources/grow_bitcoin.move index f99bde1f82..40987a01f0 100644 --- a/apps/grow_bitcoin/sources/grow_bitcoin.move +++ b/apps/grow_bitcoin/sources/grow_bitcoin.move @@ -13,7 +13,6 @@ module grow_bitcoin::grow_bitcoin { use bitcoin_move::bitcoin; use moveos_std::event::emit; - use moveos_std::tx_context::sender; use moveos_std::table; use moveos_std::table::Table; use moveos_std::object; @@ -411,14 +410,14 @@ module grow_bitcoin::grow_bitcoin { coin::merge(&mut total_coin, coin); i = i + 1; }; - account_coin_store::deposit(sender(), total_coin); + account_coin_store::deposit(signer::address_of(signer), total_coin); } /// Unstake asset from farming pool public entry fun unstake(signer: &signer, asset: &mut Object) { let coin = do_unstake(signer, object::id(asset)); utxo::remove_temp_state(asset); - account_coin_store::deposit(sender(), coin); + account_coin_store::deposit(signer::address_of(signer), coin); } /// Supports batch invocation by stake users, allowing multiple assets to be unstaked to receive yield farming tokens @@ -434,14 +433,14 @@ module grow_bitcoin::grow_bitcoin { coin::merge(&mut total_coin, coin); i = i + 1; }; - account_coin_store::deposit(sender(), total_coin); + account_coin_store::deposit(signer::address_of(signer), total_coin); } public entry fun unstake_bbn(signer: &signer, asset: &mut Object) { // TODO check bbn stake seal is expired let coin = do_unstake(signer, object::id(asset)); bbn::remove_temp_state(asset); - account_coin_store::deposit(sender(), coin); + account_coin_store::deposit(signer::address_of(signer), coin); } fun do_unstake(signer: &signer, asset_id: ObjectID): Coin { @@ -495,19 +494,19 @@ module grow_bitcoin::grow_bitcoin { coin::merge(&mut total_coin, coin); i = i + 1; }; - account_coin_store::deposit(sender(), total_coin); + account_coin_store::deposit(signer::address_of(signer), total_coin); } /// Harvest yield farming token from stake public entry fun harvest(signer:&signer, asset: &mut Object) { let coin = do_harvest(signer, object::id(asset)); - account_coin_store::deposit(sender(), coin); + account_coin_store::deposit(signer::address_of(signer), coin); } public entry fun harvest_bbn(signer:&signer, asset: &mut Object) { // TODO check bbn stake seal is expired let coin = do_harvest(signer, object::id(asset)); - account_coin_store::deposit(sender(), coin); + account_coin_store::deposit(signer::address_of(signer), coin); } fun do_harvest(signer:&signer, asset_id: ObjectID): Coin { From 11b46aeaae6f01d3e9bae6fa9554ecab550573d8 Mon Sep 17 00:00:00 2001 From: lispking Date: Wed, 11 Dec 2024 09:54:47 +0800 Subject: [PATCH 9/9] add batch_harvest_bbn for grow_bitcoin --- apps/grow_bitcoin/sources/grow_bitcoin.move | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/apps/grow_bitcoin/sources/grow_bitcoin.move b/apps/grow_bitcoin/sources/grow_bitcoin.move index 40987a01f0..c8f415d31c 100644 --- a/apps/grow_bitcoin/sources/grow_bitcoin.move +++ b/apps/grow_bitcoin/sources/grow_bitcoin.move @@ -503,6 +503,22 @@ module grow_bitcoin::grow_bitcoin { account_coin_store::deposit(signer::address_of(signer), coin); } + /// Harvest yield farming token from bbn stake + public entry fun batch_harvest_bbn(signer:&signer, assets: vector) { + let len = vector::length(&assets); + let i = 0; + let total_coin = coin::zero(); + while (i < len) { + let asset_id = *vector::borrow(&assets, i); + let bbn_obj = object::borrow_mut_object(signer, asset_id); + let coin = do_harvest(signer, object::id(bbn_obj)); + bbn::remove_temp_state(bbn_obj); + coin::merge(&mut total_coin, coin); + i = i + 1; + }; + account_coin_store::deposit(signer::address_of(signer), total_coin); + } + public entry fun harvest_bbn(signer:&signer, asset: &mut Object) { // TODO check bbn stake seal is expired let coin = do_harvest(signer, object::id(asset));