From b182001ce6bacbbf54493e2bdb5cc1efa6db9223 Mon Sep 17 00:00:00 2001 From: JSHan94 Date: Tue, 5 Mar 2024 11:02:43 +0000 Subject: [PATCH 1/3] collect stage history --- precompile/binaries/stdlib/vip_reward.mv | Bin 9842 -> 10295 bytes precompile/binaries/stdlib/vip_zapping.mv | Bin 4285 -> 4285 bytes .../initia_stdlib/sources/vip/reward.move | 382 ++++++++++++------ .../initia_stdlib/sources/vip/zapping.move | 2 +- 4 files changed, 257 insertions(+), 127 deletions(-) diff --git a/precompile/binaries/stdlib/vip_reward.mv b/precompile/binaries/stdlib/vip_reward.mv index 08d5c6b76a9a58cf870a9f6a763230b423f04f22..2b327121293660689569b3846f8c7b50e1a49ce9 100644 GIT binary patch literal 10295 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 IF_5PJ7q!c~RsaA1 literal 9842 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 diff --git a/precompile/binaries/stdlib/vip_zapping.mv b/precompile/binaries/stdlib/vip_zapping.mv index bc6d97247b21f152f378bd03fe9d4753a04ff9f4..c335812882bb2c24faedaaad7bae5dfa5a6e1a86 100644 GIT binary patch delta 16 Ycmdn1xL0ul2N(0l_Y9l4xi+x@05&ZJ;s5{u delta 16 Ycmdn1xL0ul2N(0B`;42pxi+x@05wYm!~g&Q diff --git a/precompile/modules/initia_stdlib/sources/vip/reward.move b/precompile/modules/initia_stdlib/sources/vip/reward.move index 39294dc2..c5da1618 100644 --- a/precompile/modules/initia_stdlib/sources/vip/reward.move +++ b/precompile/modules/initia_stdlib/sources/vip/reward.move @@ -6,6 +6,7 @@ module initia_std::vip_reward { use std::vector; use std::option; use std::event; + use std::block; use initia_std::object::{Self, Object, ExtendRef}; use initia_std::fungible_asset::{Self, Metadata, FungibleAsset, FungibleStore}; @@ -46,6 +47,7 @@ module initia_std::vip_reward { const EZAPPING_STAKELISTED_NOT_ENOUGH: u64 = 23; const EALREADY_REGISTERED: u64 = 24; const EBRIDGE_NOT_FOUND: u64 = 25; + const EVESTING_IN_PROGRESS: u64 = 26; // // Constants @@ -55,46 +57,51 @@ module initia_std::vip_reward { const PROOF_LENGTH: u64 = 32; const REWARD_SYMBOL: vector = b"uinit"; const DEFAULT_PROPORTION_RATIO: vector = b"0.5"; - const DEFAULT_VESTING_PERIOD: u64 = 52; // stage + const DEFAULT_VESTING_PERIOD: u64 = 52; // 52 times const DEFAULT_MINIMUM_TVL: u64 = 0; const DEFAULT_MAXIMUM_TVL: u64 = 100_000_000_000_000_000; - const DEFAULT_VIP_WEIGHT: u64 = 1; const DEFAULT_VIP_START_STAGE: u64 = 1; struct ModuleStore has key { // global stage stage: u64, + // governance-defined vesting period in stage unit + // the number of times vesting is divided + vesting_period: u64, // agent for VIP reward and snapshot taker agent: address, // governance-defined proportion to decrease overhead of keeping the L2 INIT balance. - // A user only need to keep the `vesting.l2_score * proportion` amount of INIT token + // a user only need to keep the `vesting.l2_score * proportion` amount of INIT token // to vest whole vesting rewards. proportion: Decimal256, - // governance-defined vesting period in stage unit. - vesting_period: u64, // TVL cap of L2 INIT token to receive the reward. maximum_tvl: u64, // minimum TVL of L2 INIT token to receive the reward. minimum_tvl: u64, - // total reward amount for each stage - total_stage_reward: table::Table /* stage */, u64 /* total reward amount */>, + stage_history: table::Table /* stage */, StageHistory>, // a set of bridge info bridges: table::Table /* bridge id */, Bridge>, } struct RewardStore has key { - /// Reward object's ExtendRef + // reward object's ExtendRef extend_ref: ExtendRef, - /// The total reward coins + // the total reward coins reward: Object, - /// The stage data for each stage. - /// key: stage (use `table_key::encode_u64` for iterating) - stage_data: table::Table, StageData>, - /// Total reward for the stage. + // the stage data for each stage. + stage_data: table::Table /* stage */, StageData>, + // total reward for the stage. stage_reward: table::Table, u64>, } - struct Bridge has store { + struct StageHistory has store { + // total reward amount funded + total_reward: u64, + vesting_period: u64, + release_time: u64, + } + + struct Bridge has store, drop { bridge_addr: address, reward_addr: address, operator_addr: address, @@ -102,35 +109,31 @@ module initia_std::vip_reward { } struct StageData has store { - /// Merkle root of L2 INIT token score. + // merkle root of L2 INIT token score. merkle_root: vector, - /// Sum of total L2 scores. + // sum of total L2 scores. total_l2_score: u64, } - /// User vesting store contains the claimed stages - /// and the vesting rewards. struct VestingStore has key { - /// key: stage claimed_stages: table::Table, - /// key: start_stage (use `table_key::encode_u64` for iterating) - vestings: table::Table, VestingScore>, - vestings_finalized: table::Table, VestingScore>, + vestings: table::Table /* vesting start stage */, VestingScore>, + vestings_finalized: table::Table /* vesting start stage */, VestingScore>, } struct VestingScore has copy, drop, store { - /// initial vesting reward amount. + // initial vesting reward amount. initial_reward: u64, - /// remaining vesting reward amount. + // remaining vesting reward amount. remaining_reward: u64, - /// The initial score of the L2 contract that were present - /// to receive the reward. + // the initial score of the L2 contract that were present + // to receive the reward. l2_score: u64, - /// start stage + // start stage start_stage: u64, - /// end stage (start_stage + vesting_period) + // end stage (start_stage + vesting_period) end_stage: u64, - /// minimum score to receive the reward. + // minimum score to receive the reward. minimum_score: u64, } @@ -152,30 +155,37 @@ module initia_std::vip_reward { maximum_tvl: u64, } + struct StageHistoryResponse has drop { + total_reward: u64, + vesting_period: u64, + release_time: u64, + } + struct BridgeResponse has drop { bridge_addr: address, reward_addr: address, operator_addr: address, vip_weight: u64, } + // // Events // - /// Event emitted when a user claimed the rewards. + // Event emitted when a user claimed the rewards. struct ClaimEvent has drop, store { account: address, operator: address, bridge_id: u64, - /// Claimed stage. + // claimed stage. stage: u64, - /// Newly distributed vesting reward amount. + // newly distributed vesting reward amount. vesting_reward_amount: u64, - /// Quantity claimed vesting reward that was previously distributed. + // accumulated claimed vesting reward that was previously distributed. vested_reward_amount: u64, // reward coin metadata metadata: Object, - /// l2 score + // l2 score l2_score: u64, } @@ -196,9 +206,9 @@ module initia_std::vip_reward { vesting_period: DEFAULT_VESTING_PERIOD, proportion: decimal256::from_string(&string::utf8(DEFAULT_PROPORTION_RATIO)), agent: signer::address_of(chain), - total_stage_reward: table::new, u64>(), maximum_tvl: DEFAULT_MAXIMUM_TVL, minimum_tvl: DEFAULT_MINIMUM_TVL, + stage_history: table::new, StageHistory>(), bridges: table::new, Bridge>(), }); } @@ -264,10 +274,10 @@ module initia_std::vip_reward { vesting_addr } - /// Compare bytes and return a following result number: - /// 0: equal - /// 1: v1 is greator than v2 - /// 2: v1 is less than v2 + // Compare bytes and return a following result number: + // 0: equal + // 1: v1 is greator than v2 + // 2: v1 is less than v2 fun bytes_cmp(v1: &vector, v2: &vector): u8 { assert!(vector::length(v1) == PROOF_LENGTH, error::invalid_argument(EINVALID_PROOF_LENGTH)); assert!(vector::length(v2) == PROOF_LENGTH, error::invalid_argument(EINVALID_PROOF_LENGTH)); @@ -340,12 +350,12 @@ module initia_std::vip_reward { assert!(merkle_root == root_hash, error::invalid_argument(EINVALID_MERKLE_PROOFS)); } - /// check signer is chain + // check signer is chain fun check_chain_permission(chain: &signer) { assert!(signer::address_of(chain) == @initia_std, error::permission_denied(EUNAUTHORIZED)); } - /// check signer is chain + // check signer is chain fun check_agent_permission(agent: &signer) acquires ModuleStore { let module_store = borrow_global(@initia_std); assert!(signer::address_of(agent) == module_store.agent, error::permission_denied(EUNAUTHORIZED)); @@ -449,6 +459,11 @@ module initia_std::vip_reward { let module_store = borrow_global(@initia_std); // assert claimable conditions + let (_, block_time) = block::get_block_info(); + let vesting_history = table::borrow(&module_store.stage_history, table_key::encode_u64(stage)); + + assert!(block_time >= vesting_history.release_time , error::unavailable(EVESTING_IN_PROGRESS)); + assert!(!table::contains(&vesting_store.claimed_stages, stage), error::invalid_argument(ESTAGE_ALREADY_CLAIMED)); assert!(table::contains(&reward_store.stage_data, table_key::encode_u64(stage)), error::not_found(ESTAGE_DATA_NOT_FOUND)); @@ -485,13 +500,14 @@ module initia_std::vip_reward { let remaining_reward_ratio = decimal256::sub(&decimal256::one(),&operator_store.commission_rate); let vesting_reward_amount = decimal256::mul_u64(&remaining_reward_ratio, reward_amount); + let stage_history = table::borrow(&module_store.stage_history, table_key::encode_u64(stage)); table::add(&mut vesting_store.vestings, table_key::encode_u64(stage), VestingScore { initial_reward: vesting_reward_amount, remaining_reward: vesting_reward_amount, l2_score, start_stage: stage, - end_stage: stage + module_store.vesting_period, + end_stage: stage + stage_history.vesting_period, minimum_score: decimal256::mul_u64(&module_store.proportion, l2_score), }); @@ -552,45 +568,61 @@ module initia_std::vip_reward { // Entry Functions // - /// Permissioned entry function for vesting snapshot operator. public entry fun register( chain: &signer, operator: address, bridge_id: u64, bridge_address: address, + vip_weight: u64, ) acquires ModuleStore { check_chain_permission(chain); let module_store = borrow_global_mut(signer::address_of(chain)); assert!(!table::contains(&module_store.bridges, table_key::encode_u64(bridge_id)), error::already_exists(EALREADY_REGISTERED)); - let constructor_ref = object::create_named_object(chain, generate_reward_seed(operator, bridge_id), false); - let extend_ref = object::generate_extend_ref(&constructor_ref); - let object = object::generate_signer(&constructor_ref); - let object_addr = object::address_from_constructor_ref(&constructor_ref); - let transfer_ref = object::generate_transfer_ref(&constructor_ref); - object::disable_ungated_transfer(&transfer_ref); + let object_addr = object::create_object_address(signer::address_of(chain), generate_reward_seed(operator, bridge_id)); + + // if object is already created, it means that the bridge has been deregistered + if (!object::is_object(object_addr)){ + let constructor_ref = object::create_named_object(chain, generate_reward_seed(operator, bridge_id), false); + let extend_ref = object::generate_extend_ref(&constructor_ref); + let object = object::generate_signer(&constructor_ref); + let transfer_ref = object::generate_transfer_ref(&constructor_ref); + object::disable_ungated_transfer(&transfer_ref); + + assert!(!exists(object_addr), error::already_exists(EREWARD_STORE_ALREADY_EXISTS)); + let reward_store = primary_fungible_store::ensure_primary_store_exists(object_addr, reward_metadata()); + + move_to( + &object, RewardStore { + extend_ref, + reward: reward_store, + stage_data: table::new, StageData>(), + stage_reward: table::new, u64>(), + } + ); + }; // add bridge info table::add(&mut module_store.bridges, table_key::encode_u64(bridge_id), Bridge { bridge_addr: bridge_address, reward_addr: object_addr, operator_addr: operator, - vip_weight: DEFAULT_VIP_WEIGHT, + vip_weight, }); + } - assert!(!exists(object_addr), error::already_exists(EREWARD_STORE_ALREADY_EXISTS)); - let reward_store = primary_fungible_store::ensure_primary_store_exists(object_addr, reward_metadata()); + public entry fun deregister( + chain: &signer, + bridge_id: u64, + ) acquires ModuleStore { + check_chain_permission(chain); + let module_store = borrow_global_mut(signer::address_of(chain)); + assert!(table::contains(&module_store.bridges, table_key::encode_u64(bridge_id)), error::not_found(EBRIDGE_NOT_FOUND)); - move_to( - &object, RewardStore { - extend_ref, - reward: reward_store, - stage_data: table::new, StageData>(), - stage_reward: table::new, u64>(), - } - ); + table::remove(&mut module_store.bridges, table_key::encode_u64(bridge_id)); } + public entry fun update_agent( old_agent: &signer, new_agent: address, @@ -617,17 +649,26 @@ module initia_std::vip_reward { } } - /// Permissionless interface to fund reward reserve. + // Permissionless interface to fund reward reserve. public entry fun fund_reward_script( agent: &signer, amount: u64, stage: u64, + release_time: u64, ) acquires ModuleStore, RewardStore { let shares = vector::empty(); let total_share = calculate_total_share(&mut shares); assert!(total_share > 0, error::invalid_state(EINVALID_TOTAL_SHARE)); - fund_reward(agent, total_share, &mut shares, reward_metadata(), amount, stage); + fund_reward( + agent, + total_share, + &mut shares, + reward_metadata(), + amount, + stage, + release_time, + ); } fun fund_reward( @@ -637,10 +678,11 @@ module initia_std::vip_reward { metadata: Object, amount: u64, stage: u64, + release_time: u64, ) acquires RewardStore, ModuleStore { let module_store = borrow_global_mut(@initia_std); assert!(signer::address_of(agent) == module_store.agent, error::permission_denied(EUNAUTHORIZED)); - assert!(!table::contains(&mut module_store.total_stage_reward, table_key::encode_u64(stage)), error::already_exists(EALREADY_FUNDED)); + assert!(!table::contains(&mut module_store.stage_history, table_key::encode_u64(stage)), error::already_exists(EALREADY_FUNDED)); assert!(stage == module_store.stage, error::invalid_argument(EINVALID_FUND_STAGE)); assert!(primary_fungible_store::balance(signer::address_of(agent), metadata) >= amount, error::invalid_argument(EREWARD_NOT_ENOUGH)); @@ -677,7 +719,11 @@ module initia_std::vip_reward { primary_fungible_store::deposit(signer::address_of(agent), total_reward); module_store.stage = stage + 1; - table::add(&mut module_store.total_stage_reward, table_key::encode_u64(stage), amount) + table::add(&mut module_store.stage_history, table_key::encode_u64(stage), StageHistory { + total_reward: amount, + vesting_period: module_store.vesting_period, + release_time + }) } fun calculate_total_share( @@ -708,7 +754,7 @@ module initia_std::vip_reward { (total_share) } - /// Permissioned entry function for vesting snapshot operator. + // Permissioned entry function for vesting snapshot operator. public entry fun set_merkle_root ( agent: &signer, operator: address, @@ -744,7 +790,7 @@ module initia_std::vip_reward { }); } - /// Claim user rewards and unlock vesting rewards. + // Claim user rewards and unlock vesting rewards. public entry fun claim_reward_script ( account: &signer, operator: address, @@ -786,7 +832,7 @@ module initia_std::vip_reward { ) acquires ModuleStore { check_chain_permission(chain); let module_store = borrow_global_mut(signer::address_of(chain)); - assert!(vesting_period > 0,error::invalid_argument(EINVALID_VEST_PERIOD)); + assert!(vesting_period > 0, error::invalid_argument(EINVALID_VEST_PERIOD)); module_store.vesting_period = vesting_period; } @@ -853,6 +899,18 @@ module initia_std::vip_reward { // // View Functions // + + #[view] + public fun get_stage_history_info(stage: u64): StageHistoryResponse acquires ModuleStore { + let module_store = borrow_global(@initia_std); + let vesting_history = table::borrow(&module_store.stage_history, table_key::encode_u64(stage)); + + StageHistoryResponse { + total_reward: vesting_history.total_reward, + vesting_period: vesting_history.vesting_period, + release_time: vesting_history.release_time, + } + } #[view] public fun get_bridge_info(bridge_id: u64): BridgeResponse acquires ModuleStore { @@ -1030,13 +1088,10 @@ module initia_std::vip_reward { // // Test Functions // - + #[test_only] use initia_std::coin::{BurnCapability, FreezeCapability, MintCapability}; - #[test_only] - use std::block; - #[test_only] use initia_std::dex; @@ -1051,7 +1106,10 @@ module initia_std::vip_reward { burn_cap: BurnCapability, freeze_cap: FreezeCapability, mint_cap: MintCapability, - } + } + + #[test_only] + const DEFAULT_VIP_WEIGHT_FOR_TEST: u64 = 1; #[test_only] public fun init_module_for_test(chain: &signer){ @@ -1097,6 +1155,7 @@ module initia_std::vip_reward { signer::address_of(operator), bridge_id, bridge_address, + DEFAULT_VIP_WEIGHT_FOR_TEST, ); update_operator_commission_rate( @@ -1116,7 +1175,7 @@ module initia_std::vip_reward { mint_amount: u64, commission_rate: Decimal256, proportion: Decimal256, - ): (u64) acquires OperatorStore, ModuleStore { + ): u64 acquires OperatorStore, ModuleStore { primary_fungible_store::init_module_for_test(chain); init_module_for_test(chain); let (burn_cap, freeze_cap, mint_cap, _) = test_initialize_coin(chain, string::utf8(b"uinit")); @@ -1142,7 +1201,7 @@ module initia_std::vip_reward { mint_cap, }); - (bridge_id) + bridge_id } #[test_only] @@ -1151,13 +1210,14 @@ module initia_std::vip_reward { operator: address, bridge_id: u64, reward_amount: u64, + release_time: u64, ): vector> acquires RewardStore, OperatorStore, ModuleStore { - fund_reward_script(agent, reward_amount, 1); - fund_reward_script(agent, reward_amount, 2); - fund_reward_script(agent, reward_amount, 3); - fund_reward_script(agent, reward_amount, 4); - fund_reward_script(agent, reward_amount, 5); - fund_reward_script(agent, reward_amount, 6); + fund_reward_script(agent, reward_amount, 1, release_time); + fund_reward_script(agent, reward_amount, 2, release_time); + fund_reward_script(agent, reward_amount, 3, release_time); + fund_reward_script(agent, reward_amount, 4, release_time); + fund_reward_script(agent, reward_amount, 5, release_time); + fund_reward_script(agent, reward_amount, 6, release_time); set_merkle_root(agent, operator, bridge_id, 1, x"c2c9964717d099fa39ebfde03685dd0b050be59fce12231da9eae065fc8dfb93", 800_000); set_merkle_root(agent, operator, bridge_id, 2, x"c2c9964717d099fa39ebfde03685dd0b050be59fce12231da9eae065fc8dfb93", 800_000); @@ -1179,19 +1239,20 @@ module initia_std::vip_reward { operator: address, bridge_id: u64, reward_amount: u64, + release_time: u64, ): vector> acquires RewardStore, OperatorStore, ModuleStore { - fund_reward_script(agent, reward_amount, 1); - fund_reward_script(agent, reward_amount, 2); + fund_reward_script(agent, reward_amount, 1, release_time); + fund_reward_script(agent, reward_amount, 2, release_time); set_merkle_root(agent, operator, bridge_id, 1, x"c40a82c8bd1653b6f4da68b0d0f137efd2d04d65af60007e6a623eb203dc44a3", 1_000); set_merkle_root(agent, operator, bridge_id, 2, x"c40a82c8bd1653b6f4da68b0d0f137efd2d04d65af60007e6a623eb203dc44a3", 1_000); - fund_reward_script(agent, reward_amount, 3); - fund_reward_script(agent, reward_amount, 4); + fund_reward_script(agent, reward_amount, 3, release_time); + fund_reward_script(agent, reward_amount, 4, release_time); set_merkle_root(agent, operator, bridge_id, 3, x"932a2280f1a1afdd9cc9a4ed047b0b8019ba542440264a826b38bc883c951a45", 500); set_merkle_root(agent, operator, bridge_id, 4, x"932a2280f1a1afdd9cc9a4ed047b0b8019ba542440264a826b38bc883c951a45", 500); - fund_reward_script(agent, reward_amount, 5); - fund_reward_script(agent, reward_amount, 6); + fund_reward_script(agent, reward_amount, 5, release_time); + fund_reward_script(agent, reward_amount, 6, release_time); set_merkle_root(agent, operator, bridge_id, 5, x"a123e381099b7b8a60b0019e739797eabf6ce8bfcc831e52475a96c0ca499e9f", 100); set_merkle_root(agent, operator, bridge_id, 6, x"a123e381099b7b8a60b0019e739797eabf6ce8bfcc831e52475a96c0ca499e9f", 100); @@ -1263,6 +1324,7 @@ module initia_std::vip_reward { signer::address_of(operator), 1, @0x90, + DEFAULT_VIP_WEIGHT_FOR_TEST, ); // initialize vip_reward @@ -1271,6 +1333,7 @@ module initia_std::vip_reward { signer::address_of(operator), 1, @0x90, + DEFAULT_VIP_WEIGHT_FOR_TEST, ); } @@ -1292,10 +1355,11 @@ module initia_std::vip_reward { signer::address_of(operator), 1, @0x90, + DEFAULT_VIP_WEIGHT_FOR_TEST ); let bridge_info = get_bridge_info(1); - assert!(bridge_info.vip_weight == DEFAULT_VIP_WEIGHT, 1); + assert!(bridge_info.vip_weight == DEFAULT_VIP_WEIGHT_FOR_TEST, 1); update_vip_weight( chain, @@ -1310,7 +1374,7 @@ module initia_std::vip_reward { #[test(chain=@0x1, operator=@0x56ccf33c45b99546cd1da172cf6849395bbf8573, bridge=@0x99, receiver=@0x19c9b6007d21a996737ea527f46b160b0a057c37)] fun test_update_proportion(chain: &signer, operator: &signer, bridge: &signer, receiver: &signer) acquires RewardStore, VestingStore, OperatorStore, ModuleStore { let operator_addr = signer::address_of(operator); - let (bridge_id) = test_setup( + let bridge_id = test_setup( chain, operator, 1, @@ -1318,10 +1382,10 @@ module initia_std::vip_reward { 1_000_000_000_000, decimal256::from_string(&string::utf8(b"0")), decimal256::from_string(&string::utf8(b"0.1")) - ); + ); let reward_per_stage = 1_000_000; - let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, reward_per_stage); + let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, reward_per_stage, 0); claim_reward_script(receiver, operator_addr, bridge_id, 1, score_merkle_proofs, 800_000); claim_reward_script(receiver, operator_addr, bridge_id, 2, score_merkle_proofs, 800_000); @@ -1341,7 +1405,7 @@ module initia_std::vip_reward { #[test(chain=@0x1, operator=@0x56ccf33c45b99546cd1da172cf6849395bbf8573, bridge=@0x99, receiver=@0x19c9b6007d21a996737ea527f46b160b0a057c37)] fun test_get_last_claimed_stages(chain: &signer, operator: &signer, bridge: &signer, receiver: &signer) acquires RewardStore, VestingStore, OperatorStore, ModuleStore { let operator_addr = signer::address_of(operator); - let (bridge_id) = test_setup( + let bridge_id = test_setup( chain, operator, 1, @@ -1351,7 +1415,7 @@ module initia_std::vip_reward { decimal256::from_string(&string::utf8(b"1")) ); - let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, 1_000_000); + let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, 1_000_000, 0); claim_reward_script(receiver, operator_addr, bridge_id, 1, score_merkle_proofs, 800_000); assert!(get_last_claimed_stage(signer::address_of(receiver), bridge_id) == 1, 2); @@ -1369,7 +1433,7 @@ module initia_std::vip_reward { #[test(chain=@0x1, operator=@0x56ccf33c45b99546cd1da172cf6849395bbf8573, bridge=@0x99, receiver=@0x19c9b6007d21a996737ea527f46b160b0a057c37)] fun test_update_vesting_period(chain: &signer, operator: &signer, bridge: &signer, receiver: &signer) acquires RewardStore, VestingStore, OperatorStore, ModuleStore { let operator_addr = signer::address_of(operator); - let (bridge_id) = test_setup( + let bridge_id = test_setup( chain, operator, 1, @@ -1382,7 +1446,7 @@ module initia_std::vip_reward { let reward_per_stage = 1_000_000; let vesting_period = 10; update_vesting_period(chain, vesting_period); - let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, reward_per_stage); + let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, reward_per_stage, 0); claim_reward_script(receiver, operator_addr, bridge_id, 1, score_merkle_proofs, 800_000); claim_reward_script(receiver, operator_addr, bridge_id, 2, score_merkle_proofs, 800_000); @@ -1390,18 +1454,19 @@ module initia_std::vip_reward { claim_reward_script(receiver, operator_addr, bridge_id, 4, score_merkle_proofs, 400_000); claim_reward_script(receiver, operator_addr, bridge_id, 5, score_merkle_proofs, 800_000); + assert!(get_stage_history_info(1).vesting_period == vesting_period, 1); assert!(coin::balance(signer::address_of(receiver), reward_metadata()) == ( reward_per_stage/vesting_period + reward_per_stage/(vesting_period*2) + reward_per_stage/(vesting_period*2) + reward_per_stage/vesting_period // stage 1 + reward_per_stage/(vesting_period*2) + reward_per_stage/(vesting_period*2) + reward_per_stage/vesting_period // stage 2 + reward_per_stage/vesting_period + reward_per_stage/vesting_period // stage 3 + reward_per_stage/vesting_period // stage 4 - ), 6); + ), 2); } #[test(chain=@0x1, operator=@0x56ccf33c45b99546cd1da172cf6849395bbf8573, bridge=@0x99, receiver=@0x19c9b6007d21a996737ea527f46b160b0a057c37)] fun test_finalized_vesting(chain: &signer, operator: &signer, bridge: &signer, receiver: &signer) acquires RewardStore, VestingStore, OperatorStore, ModuleStore { let operator_addr = signer::address_of(operator); - let (bridge_id) = test_setup( + let bridge_id = test_setup( chain, operator, 1, @@ -1414,7 +1479,7 @@ module initia_std::vip_reward { let reward_per_stage = 1_000_000; let vesting_period = 2; update_vesting_period(chain, vesting_period); - let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, reward_per_stage); + let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, reward_per_stage, 0); claim_reward_script(receiver, operator_addr, bridge_id, 1, score_merkle_proofs, 800_000); // vesting 1 created claim_reward_script(receiver, operator_addr, bridge_id, 2, score_merkle_proofs, 800_000); // vesting 2 created @@ -1434,7 +1499,7 @@ module initia_std::vip_reward { #[test(chain=@0x1, operator=@0x56ccf33c45b99546cd1da172cf6849395bbf8573, bridge=@0x99, receiver=@0x19c9b6007d21a996737ea527f46b160b0a057c37)] fun test_update_minimum_tvl(chain: &signer, operator: &signer, bridge: &signer, receiver: &signer) acquires ModuleStore, VestingStore, OperatorStore, RewardStore { let operator_addr = signer::address_of(operator); - let (bridge_id) = test_setup( + let bridge_id = test_setup( chain, operator, 1, @@ -1444,7 +1509,7 @@ module initia_std::vip_reward { decimal256::from_string(&string::utf8(b"1")) ); - let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, 1_000_000); + let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, 1_000_000, 0); update_minimum_tvl(chain, 1_000); claim_reward_script(receiver, operator_addr, bridge_id, 1, score_merkle_proofs, 800_000); @@ -1457,7 +1522,7 @@ module initia_std::vip_reward { fun test_claim_already_claimed(chain: &signer, operator: &signer, bridge: &signer, receiver: &signer) acquires RewardStore, VestingStore, OperatorStore, ModuleStore { let operator_addr = signer::address_of(operator); - let (bridge_id) = test_setup( + let bridge_id = test_setup( chain, operator, 1, @@ -1467,7 +1532,7 @@ module initia_std::vip_reward { decimal256::from_string(&string::utf8(b"1")) ); - let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, 1_000_000); + let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, 1_000_000, 0); claim_reward_script(receiver, operator_addr, bridge_id, 1, score_merkle_proofs, 800_000); claim_reward_script(receiver, operator_addr, bridge_id, 1, score_merkle_proofs, 800_000); @@ -1477,7 +1542,7 @@ module initia_std::vip_reward { fun test_shrink_reward(chain: &signer, operator: &signer, bridge: &signer, receiver: &signer) acquires RewardStore, VestingStore, OperatorStore, ModuleStore { let operator_addr = signer::address_of(operator); - let (bridge_id) = test_setup( + let bridge_id = test_setup( chain, operator, 1, @@ -1491,7 +1556,7 @@ module initia_std::vip_reward { let reward_per_stage = 1_000_000; update_vesting_period(chain, vesting_period); - let score_merkle_proofs = test_setup_merkle_scene2(chain, operator_addr, bridge_id, reward_per_stage); + let score_merkle_proofs = test_setup_merkle_scene2(chain, operator_addr, bridge_id, reward_per_stage, 0); claim_reward_script(receiver, operator_addr, bridge_id, 1, score_merkle_proofs, 1_000); claim_reward_script(receiver, operator_addr, bridge_id, 2, score_merkle_proofs, 1_000); @@ -1499,6 +1564,7 @@ module initia_std::vip_reward { claim_reward_script(receiver, operator_addr, bridge_id, 4, score_merkle_proofs, 500); claim_reward_script(receiver, operator_addr, bridge_id, 5, score_merkle_proofs, 100); claim_reward_script(receiver, operator_addr, bridge_id, 6, score_merkle_proofs, 100); + let vesting = get_vesting_at_stage(signer::address_of(receiver), bridge_id, 1); let reward_by_stage_1 = vesting.initial_reward - vesting.remaining_reward; let max_reward_per_claim = reward_per_stage / vesting_period; @@ -1514,7 +1580,7 @@ module initia_std::vip_reward { fun test_claim_jump_stage(chain: &signer, operator: &signer, bridge: &signer, receiver: &signer) acquires RewardStore, VestingStore, OperatorStore, ModuleStore { let operator_addr = signer::address_of(operator); - let (bridge_id) = test_setup( + let bridge_id = test_setup( chain, operator, 1, @@ -1526,7 +1592,7 @@ module initia_std::vip_reward { let reward_per_stage = 1_000_000; let vesting_period = DEFAULT_VESTING_PERIOD; - let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, reward_per_stage); + let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, reward_per_stage, 0); claim_reward_script(receiver, operator_addr, bridge_id, 1, score_merkle_proofs, 800_000); claim_reward_script(receiver, operator_addr, bridge_id, 3, score_merkle_proofs, 400_000); @@ -1554,6 +1620,7 @@ module initia_std::vip_reward { signer::address_of(operator), 1, @0x90, + DEFAULT_VIP_WEIGHT_FOR_TEST, ); register( @@ -1561,6 +1628,7 @@ module initia_std::vip_reward { signer::address_of(operator), 2, @0x91, + DEFAULT_VIP_WEIGHT_FOR_TEST, ); register( @@ -1568,6 +1636,7 @@ module initia_std::vip_reward { signer::address_of(operator), 3, @0x92, + DEFAULT_VIP_WEIGHT_FOR_TEST, ); update_operator_commission_rate( @@ -1576,11 +1645,7 @@ module initia_std::vip_reward { ); let total_reward_amount = 100_000_000; - fund_reward_script( - chain, - total_reward_amount, - 1 - ); + fund_reward_script(chain, total_reward_amount, 1, 0); let reward_addr = create_reward_address(signer::address_of(operator), 1); let reward_store = borrow_global(reward_addr); @@ -1593,12 +1658,75 @@ module initia_std::vip_reward { assert!(fungible_asset::balance(reward_store.reward) == total_reward_amount/4, 3); } + #[test(chain=@0x1, agent=@0x2, operator=@0x56ccf33c45b99546cd1da172cf6849395bbf8573, bridge=@0x99, receiver=@0x19c9b6007d21a996737ea527f46b160b0a057c37)] + fun test_deregistered_bridge(chain: &signer, agent:&signer, operator: &signer, receiver: &signer, bridge: &signer) + acquires RewardStore, VestingStore, OperatorStore, ModuleStore, TestCapability { + let operator_addr = signer::address_of(operator); + let bridge_id = test_setup( + chain, + operator, + 1, + signer::address_of(bridge), + 1_000_000_000_000, + decimal256::from_string(&string::utf8(b"0")), + decimal256::from_string(&string::utf8(b"0.5")) + ); + + let cap = borrow_global(signer::address_of(chain)); + let bridge_id2 = 2; + + test_register_bridge( + chain, + operator, + bridge_id2, + @0x1000, + 10000000000000000, + decimal256::from_string(&string::utf8(b"0")), + &cap.mint_cap + ); + + let reward_per_stage = 1_000_000_000; + let score_merkle_proofs: vector> = vector::empty>(); + vector::push_back(&mut score_merkle_proofs, x"b59284dd26bfe937d585d797edaf117bce6981a38fffa321b4f324f21932a010"); + vector::push_back(&mut score_merkle_proofs, x"437b58ec38d14fca98d5dc411b2d59cb03915ccce0718f94a94952846613f3f2"); + + update_agent(chain, signer::address_of(agent)); + primary_fungible_store::transfer(chain, reward_metadata(), signer::address_of(agent), 1_000_000_000_000); + + fund_reward_script(agent, reward_per_stage, 1, 0); + fund_reward_script(agent, reward_per_stage/2, 2, 0); + + deregister(chain, bridge_id); + + fund_reward_script(agent, reward_per_stage, 3, 0); + fund_reward_script(agent, reward_per_stage, 4, 0); + + register( + chain, + operator_addr, + bridge_id, + signer::address_of(bridge), + DEFAULT_VIP_WEIGHT_FOR_TEST, + ); + + fund_reward_script(agent, reward_per_stage, 5, 0); + + set_merkle_root(agent, operator_addr, bridge_id, 1, x"c2c9964717d099fa39ebfde03685dd0b050be59fce12231da9eae065fc8dfb93", 8_000_000); + set_merkle_root(agent, operator_addr, bridge_id, 2, x"c2c9964717d099fa39ebfde03685dd0b050be59fce12231da9eae065fc8dfb93", 8_000_000); + set_merkle_root(agent, operator_addr, bridge_id, 5, x"c2c9964717d099fa39ebfde03685dd0b050be59fce12231da9eae065fc8dfb93", 8_000_000); + + claim_reward_script(receiver, operator_addr, bridge_id, 1, score_merkle_proofs, 800_000); + claim_reward_script(receiver, operator_addr, bridge_id, 2, score_merkle_proofs, 800_000); + claim_reward_script(receiver, operator_addr, bridge_id, 5, score_merkle_proofs, 800_000); + } + + #[test(chain=@0x1, operator=@0x56ccf33c45b99546cd1da172cf6849395bbf8573, bridge=@0x99, receiver=@0x19c9b6007d21a996737ea527f46b160b0a057c37)] fun test_e2e_scene1(chain: &signer, operator: &signer, receiver: &signer, bridge: &signer) acquires RewardStore, VestingStore, OperatorStore, ModuleStore { let operator_addr = signer::address_of(operator); let vesting_period = DEFAULT_VESTING_PERIOD; - let (bridge_id) = test_setup( + let bridge_id = test_setup( chain, operator, 1, @@ -1609,7 +1737,7 @@ module initia_std::vip_reward { ); let reward_per_stage = 1_000_000_000; - let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, reward_per_stage); + let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, reward_per_stage, 0); claim_reward_script(receiver, operator_addr, bridge_id, 1, score_merkle_proofs, 800_000); assert!(coin::balance(signer::address_of(receiver), reward_metadata()) == 0, 1); @@ -1644,7 +1772,7 @@ module initia_std::vip_reward { let bridge_info = get_bridge_info(bridge_id); assert!(bridge_info.reward_addr == reward_address && bridge_info.operator_addr == operator_addr - && bridge_info.vip_weight == DEFAULT_VIP_WEIGHT + && bridge_info.vip_weight == DEFAULT_VIP_WEIGHT_FOR_TEST && bridge_info.bridge_addr == signer::address_of(bridge), 7); assert!(get_stage_reward(1, 1) == reward_per_stage, 8); assert!(get_stage_reward(1, 100) == 0, 9); @@ -1655,7 +1783,7 @@ module initia_std::vip_reward { fun test_e2e_scene2(chain: &signer, agent:&signer, operator: &signer, receiver: &signer, bridge: &signer) acquires RewardStore, VestingStore, OperatorStore, ModuleStore { let operator_addr = signer::address_of(operator); let vesting_period = DEFAULT_VESTING_PERIOD; - let (bridge_id) = test_setup( + let bridge_id = test_setup( chain, operator, 1, @@ -1674,11 +1802,11 @@ module initia_std::vip_reward { update_agent(chain, signer::address_of(agent)); primary_fungible_store::transfer(chain, reward_metadata(), signer::address_of(agent), 1_000_000_000_000); - fund_reward_script(agent, reward_per_stage, 1); - fund_reward_script(agent, reward_per_stage/2, 2); - fund_reward_script(agent, reward_per_stage, 3); - fund_reward_script(agent, reward_per_stage, 4); - fund_reward_script(agent, reward_per_stage, 5); + fund_reward_script(agent, reward_per_stage, 1, 0); + fund_reward_script(agent, reward_per_stage/2, 2, 0); + fund_reward_script(agent, reward_per_stage, 3, 0); + fund_reward_script(agent, reward_per_stage, 4, 0); + fund_reward_script(agent, reward_per_stage, 5, 0); set_merkle_root(agent, operator_addr, bridge_id, 1, x"c2c9964717d099fa39ebfde03685dd0b050be59fce12231da9eae065fc8dfb93", 8_000_000); set_merkle_root(agent, operator_addr, bridge_id, 2, x"c2c9964717d099fa39ebfde03685dd0b050be59fce12231da9eae065fc8dfb93", 8_000_000); set_merkle_root(agent, operator_addr, bridge_id, 3, x"b949f287db8f4c1489df57c66034eac6948a35cfc52fdfb7638e7f6313dc15e6", 4_000_000); @@ -1718,7 +1846,7 @@ module initia_std::vip_reward { fun test_get_next_stage(chain: &signer, operator: &signer, operator2: &signer) acquires RewardStore, OperatorStore, ModuleStore, TestCapability { let operator_addr = signer::address_of(operator); - let (bridge_id) = test_setup( + let bridge_id = test_setup( chain, operator, 1, @@ -1727,23 +1855,24 @@ module initia_std::vip_reward { decimal256::from_string(&string::utf8(b"0")), decimal256::from_string(&string::utf8(b"1")) ); - + let release_time = 0; assert!(get_module_store().stage == 1, 1); assert!(get_next_stage(bridge_id) == 1, 2); // increase stage - fund_reward_script(chain, 100_000_000, 1); + fund_reward_script(chain, 100_000_000, 1, release_time); set_merkle_root(chain, operator_addr, bridge_id, 1, x"8888888888888888888888888888888888888888888888888888888888888888", 0); assert!(get_next_stage(bridge_id) == 2, 2); assert!(get_module_store().stage == 2, 3); // increase stage - fund_reward_script(chain, 100_000_000, 2); + fund_reward_script(chain, 100_000_000, 2, release_time); set_merkle_root(chain, operator_addr, bridge_id, 2, x"8888888888888888888888888888888888888888888888888888888888888888", 0); let cap = borrow_global(signer::address_of(chain)); let operator_addr2 = signer::address_of(operator2); let bridge_id2 = 2; + // new bridge registered test_register_bridge( chain, @@ -1757,7 +1886,7 @@ module initia_std::vip_reward { assert!(get_next_stage(bridge_id2) == 3, 4); // increase stage - fund_reward_script(chain, 100_000_000, 3); + fund_reward_script(chain, 100_000_000, 3, release_time); set_merkle_root(chain, operator_addr, bridge_id, 3, x"8888888888888888888888888888888888888888888888888888888888888888", 0); set_merkle_root(chain, operator_addr2, bridge_id2, 3, x"8888888888888888888888888888888888888888888888888888888888888888", 0); assert!(get_next_stage(bridge_id) == 4, 5); @@ -1791,6 +1920,7 @@ module initia_std::vip_reward { signer::address_of(operator), bridge_id, bridge_address, + DEFAULT_VIP_WEIGHT_FOR_TEST ); let (_burn_cap, _freeze_cap, mint_cap, stakelisted_metadata) = test_initialize_coin(chain,string::utf8(b"USDC")); @@ -1839,7 +1969,7 @@ module initia_std::vip_reward { decimal256::from_string(&string::utf8(b"0")), ); - let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, 1_000_000); + let score_merkle_proofs = test_setup_merkle_scene1(chain, operator_addr, bridge_id, 1_000_000, 0); claim_reward_script(receiver, operator_addr, bridge_id, 1, score_merkle_proofs, 800_000); let stage = 1; @@ -1896,7 +2026,7 @@ module initia_std::vip_reward { vector::push_back(&mut score_merkle_proofs, x"437b58ec38d14fca98d5dc411b2d59cb03915ccce0718f94a94952846613f3f2"); while (idx <= vesting_period ) { - fund_reward_script(chain, reward_per_stage, idx); + fund_reward_script(chain, reward_per_stage, idx, 0); set_merkle_root(chain, operator_addr, bridge_id, idx, x"c2c9964717d099fa39ebfde03685dd0b050be59fce12231da9eae065fc8dfb93", 800_000); claim_reward_script(receiver, operator_addr, bridge_id, idx, score_merkle_proofs, 800_000); diff --git a/precompile/modules/initia_stdlib/sources/vip/zapping.move b/precompile/modules/initia_stdlib/sources/vip/zapping.move index a3eb9851..f813b158 100644 --- a/precompile/modules/initia_stdlib/sources/vip/zapping.move +++ b/precompile/modules/initia_stdlib/sources/vip/zapping.move @@ -32,7 +32,7 @@ module initia_std::vip_zapping { // Constants // const ZAPPING_PREFIX: u8 = 0xf5; - const DEFAULT_LOCK_PERIOD: u64 = 60 * 60 * 24 * 7 * 52; // 52 weeks + const DEFAULT_LOCK_PERIOD: u64 = 60 * 60 * 24 * 7 * 26; // 26 weeks struct ModuleStore has key { extend_ref: ExtendRef, From 3e295c6d0c76ce5a0f9fd26de9e6d01263529386 Mon Sep 17 00:00:00 2001 From: JSHan94 Date: Wed, 6 Mar 2024 04:58:40 +0000 Subject: [PATCH 2/3] add vesting event --- precompile/binaries/stdlib/vip_reward.mv | Bin 10295 -> 10474 bytes .../initia_stdlib/sources/vip/reward.move | 149 +++++++++++++----- 2 files changed, 107 insertions(+), 42 deletions(-) diff --git a/precompile/binaries/stdlib/vip_reward.mv b/precompile/binaries/stdlib/vip_reward.mv index 2b327121293660689569b3846f8c7b50e1a49ce9..75a921dbf800fd27b7fce090b459d252497fa641 100644 GIT binary patch delta 5525 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 Ih(YYX0bu=G4FCWD delta 5343 zcmai2TXbE=S)PAp&z`+!=IqP4>aHVMcg6DE-gYe8iWS+Clh|>b#Ez5LvZdH^6xop- zCoQFi6biJZm$11MD9~~%kd}rT2zPkvT9ijvs}Hai4~4a$FFf*AzS-xnBcBjorLRlxJN_;CzWN8H-j2Ut3I2V!>3@3L z_j&T4qhAj7+dKY=>_6}P*MZWvPcOW4^lVEpHV`m1%2+t9h>?0EVBP`6q6Lo&JnQE` zWu@m8Q?CasyzR5-r->I!;d{hc_{Rj&Uw24skYRU|3&w^#$=I-uVVmPH;)byxWNbXZ zY(g8xCbelXHU;I`_7aAf2*VB?GqzJ=*d-Ijc586hlVaHGhJ93KY`?@TGZn@T5{5&L z*Q1Vhm@v%BDq}}#m>sQSIObO8(gtIXx#76mGVhdmTz4_nI?>(3*vZ~L#uocQTyn~s zq5;O97=#K>Hu3n>5Qfuk;fx!e9>#Fi4bQm8bK5XHI|8ofM=`sAA^AxfCt|@*Q5-Y* zX@Y9{XNabVML$cAYzI2gXK1F&{kA?!GdnObpQBxp0`KPt7I~ki8pbcs9*ke4y%@hl z`}Q;M9oi$A{drP`$=tD(zu-pxi$paR{}KVU=$GlxqhKh%>{g;*p+kk7U!@}iYWQn( z^cYiLp~pf9`*qsesxb8%^tfdHZ_)`O9}#qtSok$sG%WfpI`xEO_1lh>X&+L*Lr;ZF zeU(lV1<~))kuzNI`1dHrj^eERy4y{^PtU}}^dHa(XZ9b`c?nMHb950_M(@(gPRG(W zs1;vf-Z$xLg++fvw8DiKeTz&IC5XLS7r3*V<# ziJ3pAUF#Hxm5l+W{(>$JP@w*jZb38euN;uk-_V^mz$^M&x?8~TcXannJg4VBMr^M* z5NECFgVTqmAKiK4;Ns!M*`>oLW}lclaeQh1^uprw+3CfD=XO3f_x$nGPcI$3XfDcZ z{^0zf`4{8G`4jUm&1SO)XAjN3Ja_5%m4jENPfTB(zOnPl?3Lq7(^n2(nO{7^AKjNhF9||>Y1o_tYtrTvHprFL1Ajy3zl>2I7A`0Ss zyVuo9D8LrsVJ|isBJP_MOalfc0psfalM0x0Ji)3sjw4cZq`+rb!Z%0+BnVH4&Ox*F ztKHe+ped6GDv*aK4mG~(jkfBANEJX0!g|PxXV2*pvan5R)5+8e5`wlp!IK}tMKPCP zh*%1e_D4V&?so?K!k&a;jIs(nAqg`-a2xz#s{)+!13ZSlfcYg%gbJ+FBXpSL@5p+q zt&P(NY-(gFsKVYttiVq91%`f5qJTRiq=O!wfnf!b?qtX)q!Km*UW~B9p^Y6u2?C*o z5;&#s#0$n?rks6X-U2#)$UGpSd3z{M8|i<91ooz_KSmii*dPb?Nf@nY3t1@Z^MIuD zDKvxC66UvKK!7f`Hae7B0R6+Fog4=gPD%VAAc6|eZHGQF^AM51%okqA3vE{vaaM&o zFfDP&k}%!Qe4_!Z5h5_2i_4FMR`*tDwI_H2^a$Lb6qInV0RscXx6?WX5-yD0(!KAg zak@7W{u>>QuC3m=bZhhGt(%*7)^2W;-Q(u!o6DOkmzGynHdk-oewc*k)y=!Bq1$!) z&hoX@{8FQl&zR8{Dvoq__4b{$jcZ#cs~@0sP7FLud}VE8d428Us}R;%E~IVoxwX2v zcJtmh%zyCx(b~q^oweolj&jN7>TAm&L0DT`19dh#Ji^tDm5zG<6ZHo{huytu{1sCE z`s&8DJJ<8~lG8d|yM5{Al^d&9@7()ga+UK>h4)q}Jz_`lz(Dk|0-}x8w>sRnC=Wo( zzgfS2@khXfogX!41=IqpH#XL9UVRm&w+#UKN8$x~{Hcv|ZE8jKJfP;E>|UqI z{0H6pX*?h9S)|?hdQbPlVPtc|kY7s>RfRgp@MMP7Pr z)SHq!oS+nfB879Rn$G3l?P<0S#AQ0Z3bKIhE<#a1**r^+~ z$v!bp`pRbCDNfly)1>bysZ}|hhaH-yjVWaljoz5{Pg&coY1+585Mfj7(kE>xDwzn>uKViw zwqhJ7D5bmbk>D*%C8<~I#v~1>F;_NO$)If+ZiMNI>giMIxRGU^Md%rdJO@?FhII`X zfyZ#u3pF}dI;L6Y5CBhc<0w4fr)SVl0K2b-4K}2u^l2VCf-D{*JZkbtE_H(;Xz629 z(zV%yX#$?HSCVCemZ{(h!(+!{A;Ud|-S<=H6E#6$IMF-gQaW$Y04|$CztZx<_tZbFE#sVKEK|apF59iYX8-F4O{#R ziDt+am|7&2MKLJy3dvck^195WjZ}FbMA%FBQMLNPE@gC_WXL19|BFNW zTKza|N*y;L!XI`M=L3$><&n-Z-0<+ShoS?=e$X>rvfs##XXKV=s(kSOVALw&VT)7x zu#Z2;DQ)|>%JFvkkZ*>nd*O0Kz*x z8Hr$)+a(_+yo+~oKAg0C8(0w{qm$&mG%lrzByXqqI3K|lWKXfh@)^TX3_=-wXx{`M zb>(CAS$I#nWJNJhTA_TnNR6B595n+)7;dY+%XF8|uB4+7*-(e+O4B=OAjFZvbk!mN z(pOM;WqQp97_Z|(Z_+g#PO7GNKpqA&G#fAq)A4N5>L@V2(b-fsT~^zbT!MZ^p-w?O z3TTL$=#^Ra2wxaOV!YNU92_}84!-NIx20>CU9%$Fp3P)4Ww;uBPj0t-yr`3EST)nj z>8pGKfGp~20u;s)lBF)Yl~*(~Bw@d7wllDV zt`;Lmw>nLvV*rlc&@Playgl-eiQTnZb-BZFT(mRW3TAK<2%6sG@`=uRy;yg7xHBCe z^3KVNorMTB)D-RVKJ#$Kgy>(1Mwc>)Yg^htv@4l58Lk4%T?V2I6hR!xa**xjQ$>$( zN$jcNUe_XAvx&nRpDtD!&ixLBd}yrR?L=Z#)c7OCYVH2&nX#Uc&T3zcZ^x?tIwBeo zj7B)=H@y^M;n(~NV}r+M+~LiK8GisC3pl?oe;h#NJ&<3j@fd#tC` z5!h4XJKbs@ia;t|+bY`G2vP{WHs&?H3m(3G;z0?)`+7zh?V@at^-F%Xw~4Yhhsi!0 zAj+8z60bVq^#suI?}jrs0?Xfj1JLwgE7RJODoln zj=Mh57i{u9=#9$eUz%u)?naLQY(m0bBwTT=kX-s9w@kTLX_PCQ|Kmir@wmtEx-8J4 F{ujmAY5)KL diff --git a/precompile/modules/initia_stdlib/sources/vip/reward.move b/precompile/modules/initia_stdlib/sources/vip/reward.move index c5da1618..1645fc0c 100644 --- a/precompile/modules/initia_stdlib/sources/vip/reward.move +++ b/precompile/modules/initia_stdlib/sources/vip/reward.move @@ -91,7 +91,7 @@ module initia_std::vip_reward { // the stage data for each stage. stage_data: table::Table /* stage */, StageData>, // total reward for the stage. - stage_reward: table::Table, u64>, + stage_reward: table::Table /* stage */, u64>, } struct StageHistory has store { @@ -168,6 +168,17 @@ module initia_std::vip_reward { vip_weight: u64, } + struct VestingResponse has drop { + length: u64, + vestings: vector, + } + + struct Vesting has drop { + start_stage: u64, + end_stage: u64, + remaining_reward: u64, + initial_reward: u64 + } // // Events // @@ -196,6 +207,15 @@ module initia_std::vip_reward { reward_amount: u64, } + struct VestingEvent has drop, store { + account: address, + bridge_id: u64, + claim_stage: u64, + vesting_start_stage: u64, + initial_reward: u64, + remaining_reward: u64, + } + // // Heldper Functions // @@ -399,6 +419,8 @@ module initia_std::vip_reward { } fun vest_reward( + account: address, + bridge_id: u64, stage: u64, l2_score: u64, vestings: &mut table::Table, VestingScore>, @@ -434,6 +456,17 @@ module initia_std::vip_reward { vested_reward = vested_reward + vest_amount; value.remaining_reward = value.remaining_reward - vest_amount; + + event::emit( + VestingEvent { + account, + bridge_id, + claim_stage: stage, + vesting_start_stage: value.start_stage, + initial_reward: value.initial_reward, + remaining_reward: value.remaining_reward, + } + ); }; vested_reward } @@ -486,6 +519,8 @@ module initia_std::vip_reward { // Vest previous vesting rewards. let reward_signer = &object::generate_signer_for_extending(&reward_store.extend_ref); let amount = vest_reward( + account_addr, + bridge_id, stage, l2_score, &mut vesting_store.vestings, @@ -581,15 +616,13 @@ module initia_std::vip_reward { let object_addr = object::create_object_address(signer::address_of(chain), generate_reward_seed(operator, bridge_id)); - // if object is already created, it means that the bridge has been deregistered - if (!object::is_object(object_addr)){ + if (!exists(object_addr)){ let constructor_ref = object::create_named_object(chain, generate_reward_seed(operator, bridge_id), false); let extend_ref = object::generate_extend_ref(&constructor_ref); let object = object::generate_signer(&constructor_ref); let transfer_ref = object::generate_transfer_ref(&constructor_ref); object::disable_ungated_transfer(&transfer_ref); - assert!(!exists(object_addr), error::already_exists(EREWARD_STORE_ALREADY_EXISTS)); let reward_store = primary_fungible_store::ensure_primary_store_exists(object_addr, reward_metadata()); move_to( @@ -934,18 +967,7 @@ module initia_std::vip_reward { } #[view] - public fun get_reward_reserve(bridge_id: u64): u64 acquires RewardStore, ModuleStore { - let bridge_info = get_bridge_info(bridge_id); - - let reward_addr = create_reward_address(bridge_info.operator_addr, bridge_id); - assert!(exists(reward_addr), error::not_found(EVESTING_STORE_NOT_FOUND)); - let reward_store = borrow_global(reward_addr); - - fungible_asset::balance(reward_store.reward) - } - - #[view] - public fun get_vesting_at_stage(account_addr: address, bridge_id: u64, stage: u64): VestingScore acquires VestingStore { + public fun get_vesting(account_addr: address, bridge_id: u64, stage: u64): VestingScore acquires VestingStore { let vesting_addr = create_vesting_address(account_addr, bridge_id); assert!(exists(vesting_addr), error::not_found(EVESTING_STORE_NOT_FOUND)); let vesting_store = borrow_global_mut(vesting_addr); @@ -957,7 +979,7 @@ module initia_std::vip_reward { } #[view] - public fun get_vesting_finalized_at_stage(account_addr: address, bridge_id: u64, stage: u64): VestingScore acquires VestingStore { + public fun get_vesting_finalized(account_addr: address, bridge_id: u64, stage: u64): VestingScore acquires VestingStore { let vesting_addr = create_vesting_address(account_addr, bridge_id); assert!(exists(vesting_addr), error::not_found(EVESTING_STORE_NOT_FOUND)); let vesting_store = borrow_global_mut(vesting_addr); @@ -968,6 +990,64 @@ module initia_std::vip_reward { *vesting_finalized } + #[view] + public fun get_vestings(account_addr: address, bridge_id: u64) : VestingResponse acquires VestingStore { + let vesting_addr = create_vesting_address(account_addr, bridge_id); + assert!(exists(vesting_addr), error::not_found(EVESTING_STORE_NOT_FOUND)); + let vesting_store = borrow_global_mut(vesting_addr); + + let vestings = vector::empty(); + let iter = table::iter(&mut vesting_store.vestings, option::none(), option::none(), 1); + loop { + if (!table::prepare, VestingScore>(&mut iter)) { + break + }; + + let (_, value) = table::next, VestingScore>(&mut iter); + + vector::push_back(&mut vestings, Vesting { + start_stage: value.start_stage, + end_stage: value.end_stage, + remaining_reward: value.remaining_reward, + initial_reward: value.initial_reward, + }); + }; + + VestingResponse { + length: vector::length(&vestings), + vestings + } + } + + #[view] + public fun get_vestings_finalized(account_addr: address, bridge_id: u64) : VestingResponse acquires VestingStore { + let vesting_addr = create_vesting_address(account_addr, bridge_id); + assert!(exists(vesting_addr), error::not_found(EVESTING_STORE_NOT_FOUND)); + let vesting_store = borrow_global_mut(vesting_addr); + + let vestings = vector::empty(); + let iter = table::iter(&mut vesting_store.vestings_finalized, option::none(), option::none(), 1); + loop { + if (!table::prepare, VestingScore>(&mut iter)) { + break + }; + + let (_, value) = table::next, VestingScore>(&mut iter); + + vector::push_back(&mut vestings, Vesting { + start_stage: value.start_stage, + end_stage: value.end_stage, + remaining_reward: value.remaining_reward, + initial_reward: value.initial_reward, + }); + }; + + VestingResponse { + length: vector::length(&vestings), + vestings + } + } + #[view] public fun get_last_claimed_stage(account_addr: address, bridge_id: u64): u64 acquires VestingStore { let vesting_addr = create_vesting_address(account_addr, bridge_id); @@ -1024,24 +1104,6 @@ module initia_std::vip_reward { } } - #[view] - public fun get_stage(): u64 acquires ModuleStore { - let module_response = get_module_store(); - module_response.stage - } - - #[view] - public fun get_proportion(): Decimal256 acquires ModuleStore { - let module_response = get_module_store(); - module_response.proportion - } - - #[view] - public fun get_vesting_period(): u64 acquires ModuleStore { - let module_response = get_module_store(); - module_response.vesting_period - } - #[view] public fun get_minimum_score(account_addr: address, bridge_id: u64, stage: u64): u64 acquires VestingStore { let vesting_store = borrow_global_mut(get_vesting_address(account_addr, bridge_id)); @@ -1484,15 +1546,18 @@ module initia_std::vip_reward { claim_reward_script(receiver, operator_addr, bridge_id, 1, score_merkle_proofs, 800_000); // vesting 1 created claim_reward_script(receiver, operator_addr, bridge_id, 2, score_merkle_proofs, 800_000); // vesting 2 created - get_vesting_at_stage(signer::address_of(receiver), bridge_id, 1); - get_vesting_at_stage(signer::address_of(receiver), bridge_id, 2); + get_vesting(signer::address_of(receiver), bridge_id, 1); + get_vesting(signer::address_of(receiver), bridge_id, 2); claim_reward_script(receiver, operator_addr, bridge_id, 3, score_merkle_proofs, 400_000); claim_reward_script(receiver, operator_addr, bridge_id, 4, score_merkle_proofs, 400_000); // vesting 1 finalized claim_reward_script(receiver, operator_addr, bridge_id, 5, score_merkle_proofs, 800_000); // vesting 2 finalized - get_vesting_finalized_at_stage(signer::address_of(receiver), bridge_id, 1); - get_vesting_finalized_at_stage(signer::address_of(receiver), bridge_id, 2); + get_vesting_finalized(signer::address_of(receiver), bridge_id, 1); + get_vesting_finalized(signer::address_of(receiver), bridge_id, 2); + + assert!(get_vestings(signer::address_of(receiver), bridge_id).length == 3, 1); + assert!(get_vestings_finalized(signer::address_of(receiver), bridge_id).length == 2, 2); } @@ -1565,7 +1630,7 @@ module initia_std::vip_reward { claim_reward_script(receiver, operator_addr, bridge_id, 5, score_merkle_proofs, 100); claim_reward_script(receiver, operator_addr, bridge_id, 6, score_merkle_proofs, 100); - let vesting = get_vesting_at_stage(signer::address_of(receiver), bridge_id, 1); + let vesting = get_vesting(signer::address_of(receiver), bridge_id, 1); let reward_by_stage_1 = vesting.initial_reward - vesting.remaining_reward; let max_reward_per_claim = reward_per_stage / vesting_period; @@ -1741,7 +1806,7 @@ module initia_std::vip_reward { claim_reward_script(receiver, operator_addr, bridge_id, 1, score_merkle_proofs, 800_000); assert!(coin::balance(signer::address_of(receiver), reward_metadata()) == 0, 1); - assert!(get_vesting_at_stage(signer::address_of(receiver), bridge_id, 1).initial_reward == reward_per_stage, 2); + assert!(get_vesting(signer::address_of(receiver), bridge_id, 1).initial_reward == reward_per_stage, 2); claim_reward_script(receiver, operator_addr, bridge_id, 2, score_merkle_proofs, 800_000); assert!(coin::balance(signer::address_of(receiver), reward_metadata()) == (reward_per_stage/vesting_period), 3); @@ -1815,7 +1880,7 @@ module initia_std::vip_reward { claim_reward_script(receiver, operator_addr, bridge_id, 1, score_merkle_proofs, 800_000); assert!(get_locked_reward(signer::address_of(receiver), bridge_id, 1) == reward_per_stage/portion, 1); - assert!(get_vesting_at_stage(signer::address_of(receiver), bridge_id, 1).initial_reward == reward_per_stage/portion, 2); + assert!(get_vesting(signer::address_of(receiver), bridge_id, 1).initial_reward == reward_per_stage/portion, 2); claim_reward_script(receiver, operator_addr, bridge_id, 2, score_merkle_proofs, 800_000); assert!(get_unlocked_reward(signer::address_of(receiver), bridge_id, 2, 800_000) == (reward_per_stage/vesting_period)/portion, 3); From be06ed050fe157a72970b4876c732ad447046975 Mon Sep 17 00:00:00 2001 From: JSHan94 Date: Wed, 6 Mar 2024 05:37:35 +0000 Subject: [PATCH 3/3] vectorize vesting changes --- precompile/binaries/stdlib/vip_reward.mv | Bin 10474 -> 10483 bytes .../initia_stdlib/sources/vip/reward.move | 47 +++++++----------- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/precompile/binaries/stdlib/vip_reward.mv b/precompile/binaries/stdlib/vip_reward.mv index 75a921dbf800fd27b7fce090b459d252497fa641..fd88702efbdcd58cdbdbdf61b34f2cc878d52946 100644 GIT binary patch delta 1357 zcmYjRTW}Ob6zwxTy))B2JF}Yyn`{=cd9a~$2_%qY6UdSf_CX*TkcZ*nCO~)u5|l&~ z3XK6Dpdw;}1QiugQ9%?J!52P0^~(=G{PIzyWhs7G@?rU**b_>Mu9|cE_PO`m+tbzk z+mfqGT2Dr<2p=KD2C3Gn_k*6rVWwa94Y4!EpN4V5{j1PCQWf=GsQO6@jK_X9`9HN+ zVgE66U(|o~aI16=K+`A)toNW1D}Vlb1EY^(8bHj);JSqE2V;ak4%`ajJb~%88YRw? zm{IE4gP1W>S@9I=8BF~UP)PKrQLOMVW-ELK4GJY1n}~h{vl+3E!VrW#>#4G19%|!2 zF>#NBxx{%6bLNgJMfSW$IWJ(&M4c0u2eoRwh_-fOyo3dos`j#{ZJb1g5#K9V2>9qJ zbb?r~Vv!)uYv{VoQ+nM~64!H#)9AK{aSBTS(|H5)mTFXU--N3oCUV(ZV55xS43@hf z{45rF+aALzrlg#=ao1dB{pa9rAo@G#FC@;pz($Sg&UthxF=Ac7<}Ji}9|K#7brA#Y z#JYrmZN&NjgCOEV)DOX=AK~tDVtkApac&24(-Lj75sjfS+Ej^-# zHKv==iS#NrlTM{qCmWMZ$wYEZD%X;Wr{cZwjdi(XE|rbvT65`4YIDbyj%;#k+T4~N zOn0Yy)A9<|B>NZ*FOk-q%i;7T8( z8$IP8LI;}YL!hJdLF(7EG0?r>rf@W$x6)7d&)mt{m)9xt0xaC1y3 zIA6ucFUuOkZS&Qon;3S8Q_gtU4X7{Z4@ozYE-mFEz&Q;rNcikR;c;rtOL?grid0yo z&ZOXC!9+-oM|!bX{vBz+?fDs#*8x5b0 z*QTiJ?*2~}RCNY#Cd<{P*2}@Fqu3;AwZwLLthx=0mJ>?+ZIpJ17 zFRIqVrp;JXIcCv~+zOisrcW0ZxW>&ygRPE7n8Hr@naM2<+gB@mL27d$IG>~{dD()8 pYPjW^#avfDD^g$-36CkT7tCj-pb#2_u8v)PS2G8VGCb|;{{UEr1oHp@ delta 1370 zcmYjRS#T6Z818R+dS|A4c4jvR$&!VfBoUWD0!cQ3EF@;wB@juF!*IA+A%Q>wNFs-Y z200Xr3fLkdULcAJqPTbhCBDg<558MvX;B4QrQ(xXmOZhs=&Jtj|ND=c>D%2myIW30 zZ;1dQ#0II*Dh`64#}TGq32bHOjb9Aog!_B0IaXd0I9L9o7CKz{lga<6`5X4HGyW_N z-aOhO-DjX_6a-cl8nG^2{NBLm)2IfBc@VBk*dZ`R_!w|6i1RF_)o7GB&tZDR=g(vM z48_G^)G?U)5g?c7N0G1S3z(&-M7^RfqM?!K$1sZ#`z08Hu;V@|d)cSj2_T=iuYkG4 zIf>bGMinA^)pt3sVfJ{P*D)8$YQ2GZt;Bc}_gSjiDIeQ7jroiO-a-lp&@)&7V!e$H zL7aE6sMAL}>m!N(a*TJe*doRmbOEOG9_DsyRCC{lt0Km8**UOLMsOZWT@d~OQvTR` z(Zdv!a{+7SC?5O}?pmUMgmt;Zxd`-WRChkcA_YdQPq2Oiu|CDXMq+)2fmULDj)6_Y z`T~O>;!D&G!K8g#iivRE?9Ii}l9(YtxBzdn%T0Nqfom4Q&H$sl+C4(DH`7F0b>kUQgbn z+57;blo}#Wp_qO+K9?3?m zje2;fZzQuWGm(aw(w`}Xno(wj@7HbDH14HTIk<9wO?03!uEjt!o5imp;W==nq zHwq3V0%?|^dqAHA9i>mupr-8w-3M+8M+^9te!81JPWOYl8a)8jC&fOW`RzWHJzKa( z!*y9*RE3D_DvC}k5L^_5L|&ynmDP&~LjN8FIQVHt_ej}&qd;+%%t;{iKY_#P$mLS86$MoXC7o1{`?F1x)&LL4wIE@wZR&kRGno?4O2j$X|VXTzj zl+42_X_Z!CwX7{o;vu=KbS2Vqc3H8!t#n^Xp;!J>HVGMdx~wB7!=jGanh|DBP@Am& zbN7xjTHX=9+gYq$k%#4u@?+?i!3v4Z@>In3N0<2z)cCP&uE!BaE#h^y88qWF zOY|UHtb|!Mw=K0#9@6tF^ogb&U?oa1^Zw5*wF4rcPZJzm=T^Ml4ss?e5sU|!$<@kj zqed8EY71d=F+o-GvxO+A=G-;&IZ=5&Jj+wW$P>Od$Bs8JQ!of!eFO4F)oe7%^6GE@ E1?VRO{{R30 diff --git a/precompile/modules/initia_stdlib/sources/vip/reward.move b/precompile/modules/initia_stdlib/sources/vip/reward.move index 1645fc0c..4ac2b975 100644 --- a/precompile/modules/initia_stdlib/sources/vip/reward.move +++ b/precompile/modules/initia_stdlib/sources/vip/reward.move @@ -179,6 +179,13 @@ module initia_std::vip_reward { remaining_reward: u64, initial_reward: u64 } + + struct VestingChange has drop, store { + vesting_start_stage: u64, + initial_reward: u64, + remaining_reward: u64, + } + // // Events // @@ -194,10 +201,10 @@ module initia_std::vip_reward { vesting_reward_amount: u64, // accumulated claimed vesting reward that was previously distributed. vested_reward_amount: u64, - // reward coin metadata - metadata: Object, // l2 score l2_score: u64, + // vesting changes + vesting_changes: vector, } struct FundEvent has drop, store { @@ -207,15 +214,6 @@ module initia_std::vip_reward { reward_amount: u64, } - struct VestingEvent has drop, store { - account: address, - bridge_id: u64, - claim_stage: u64, - vesting_start_stage: u64, - initial_reward: u64, - remaining_reward: u64, - } - // // Heldper Functions // @@ -419,12 +417,11 @@ module initia_std::vip_reward { } fun vest_reward( - account: address, - bridge_id: u64, stage: u64, l2_score: u64, vestings: &mut table::Table, VestingScore>, vestings_finalized: &mut table::Table, VestingScore>, + vesting_changes: &mut vector, ) : u64 { let vested_reward = 0u64; let iter = table::iter_mut(vestings, option::none(), option::none(), 1); @@ -451,22 +448,16 @@ module initia_std::vip_reward { // // vest_ratio = max_ratio * score_ratio // vest_amount = value.initial_reward * vest_ratio - let vest_amount = calculate_vest(value, l2_score); vested_reward = vested_reward + vest_amount; value.remaining_reward = value.remaining_reward - vest_amount; - event::emit( - VestingEvent { - account, - bridge_id, - claim_stage: stage, - vesting_start_stage: value.start_stage, - initial_reward: value.initial_reward, - remaining_reward: value.remaining_reward, - } - ); + vector::push_back(vesting_changes, VestingChange { + vesting_start_stage: value.start_stage, + initial_reward: value.initial_reward, + remaining_reward: value.remaining_reward, + }); }; vested_reward } @@ -518,13 +509,13 @@ module initia_std::vip_reward { // Vest previous vesting rewards. let reward_signer = &object::generate_signer_for_extending(&reward_store.extend_ref); + let vesting_changes = vector::empty(); let amount = vest_reward( - account_addr, - bridge_id, stage, l2_score, &mut vesting_store.vestings, &mut vesting_store.vestings_finalized, + &mut vesting_changes, ); let vested_reward = fungible_asset::withdraw(reward_signer, reward_store.reward, amount); @@ -555,8 +546,8 @@ module initia_std::vip_reward { stage, vesting_reward_amount, vested_reward_amount: fungible_asset::amount(&vested_reward), - metadata: reward_metadata(), - l2_score + l2_score, + vesting_changes, } );