From b6dfe0005d24c6e49d68e55836e4905b26dc4b08 Mon Sep 17 00:00:00 2001 From: dongcool <95206510+dongcool@users.noreply.github.com> Date: Tue, 26 Mar 2024 11:08:15 +0800 Subject: [PATCH 1/3] make sync balance public --- README.md | 2 +- contracts/linear/src/epoch_actions.rs | 22 +- contracts/linear/src/internal.rs | 4 - contracts/linear/src/validator_pool.rs | 4 - makefile | 5 +- tests/__tests__/linear/helper.ts | 10 +- tests/__tests__/linear/sync-balance.ava.ts | 696 ++++++++++----------- 7 files changed, 356 insertions(+), 387 deletions(-) diff --git a/README.md b/README.md index f4035d8c..c24032bc 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ We adopt unit tests and heavily used the [`workspace-js`](https://github.com/nea - Run LiNEAR simulation tests: - Run all: `make test-linear` - Run specific test file: `TEST_FILE={filename} make test-linear` - - Print contract logs: `LOGS=1 make test-linear` + - Print contract logs: `NO_LOGS=false make test-linear` ### Deploy diff --git a/contracts/linear/src/epoch_actions.rs b/contracts/linear/src/epoch_actions.rs index d05af780..48398bf9 100644 --- a/contracts/linear/src/epoch_actions.rs +++ b/contracts/linear/src/epoch_actions.rs @@ -8,7 +8,6 @@ use crate::utils::*; const MIN_AMOUNT_TO_PERFORM_STAKE: Balance = ONE_NEAR; const MAX_SYNC_BALANCE_DIFF: Balance = 100; -const MANAGER_SYNC_BALANCE_DIFF_THRESHOLD: Balance = 1_000_000; /// Actions that should be called by off-chain actors /// during each epoch. @@ -266,11 +265,7 @@ trait EpochActionCallbacks { fn validator_get_balance_callback(&mut self, validator_id: AccountId); - fn validator_get_account_callback( - &mut self, - validator_id: AccountId, - post_action: bool, - ) -> bool; + fn validator_get_account_callback(&mut self, validator_id: AccountId) -> bool; fn validator_withdraw_callback(&mut self, validator_id: AccountId, amount: U128); } @@ -307,7 +302,6 @@ impl LiquidStakingContract { .sync_account_balance(&mut self.validator_pool, true) .then(ext_self_action_cb::validator_get_account_callback( validator_id, - true, env::current_account_id(), NO_DEPOSIT, GAS_CB_VALIDATOR_SYNC_BALANCE, @@ -357,7 +351,6 @@ impl LiquidStakingContract { .sync_account_balance(&mut self.validator_pool, true) .then(ext_self_action_cb::validator_get_account_callback( validator_id, - true, env::current_account_id(), NO_DEPOSIT, GAS_CB_VALIDATOR_SYNC_BALANCE, @@ -421,7 +414,6 @@ impl LiquidStakingContract { pub fn validator_get_account_callback( &mut self, validator_id: AccountId, - post_action: bool, #[callback_result] result: Result, ) -> bool { let mut validator = self @@ -429,12 +421,6 @@ impl LiquidStakingContract { .get_validator(&validator_id) .unwrap_or_else(|| panic!("{}: {}", ERR_VALIDATOR_NOT_EXIST, &validator_id)); - let max_sync_balance_diff = if !post_action && self.signed_by_manager() { - MANAGER_SYNC_BALANCE_DIFF_THRESHOLD - } else { - MAX_SYNC_BALANCE_DIFF - }; - match result { Ok(account) => { // allow at most max_sync_balance_diff diff in total balance, staked balance and unstake balance @@ -442,15 +428,15 @@ impl LiquidStakingContract { if abs_diff_eq( new_total_balance, validator.total_balance(), - max_sync_balance_diff, + MAX_SYNC_BALANCE_DIFF, ) && abs_diff_eq( account.staked_balance.0, validator.staked_amount, - max_sync_balance_diff, + MAX_SYNC_BALANCE_DIFF, ) && abs_diff_eq( account.unstaked_balance.0, validator.unstaked_amount, - max_sync_balance_diff, + MAX_SYNC_BALANCE_DIFF, ) { Event::SyncValidatorBalanceSuccess { validator_id: &validator_id, diff --git a/contracts/linear/src/internal.rs b/contracts/linear/src/internal.rs index d9bc017d..2e4bd6bf 100644 --- a/contracts/linear/src/internal.rs +++ b/contracts/linear/src/internal.rs @@ -357,8 +357,4 @@ impl LiquidStakingContract { ERR_NOT_MANAGER ); } - - pub(crate) fn signed_by_manager(&self) -> bool { - self.managers.contains(&env::signer_account_id()) - } } diff --git a/contracts/linear/src/validator_pool.rs b/contracts/linear/src/validator_pool.rs index 0ee9e9d6..f0f6635c 100644 --- a/contracts/linear/src/validator_pool.rs +++ b/contracts/linear/src/validator_pool.rs @@ -587,10 +587,8 @@ impl LiquidStakingContract { } /// Sync contract staked and unstaked balance from validator - /// - Only allowed by manager pub fn sync_balance_from_validator(&mut self, validator_id: AccountId) { self.assert_running(); - self.assert_manager(); let min_gas = GAS_SYNC_BALANCE + GAS_EXT_GET_ACCOUNT + GAS_CB_VALIDATOR_SYNC_BALANCE; require!( @@ -607,7 +605,6 @@ impl LiquidStakingContract { .sync_account_balance(&mut self.validator_pool, false) .then(ext_self_action_cb::validator_get_account_callback( validator.account_id, - false, env::current_account_id(), NO_DEPOSIT, GAS_CB_VALIDATOR_SYNC_BALANCE, @@ -798,7 +795,6 @@ impl LiquidStakingContract { .sync_account_balance(&mut self.validator_pool, true) .then(ext_self_action_cb::validator_get_account_callback( validator_id, - true, env::current_account_id(), NO_DEPOSIT, GAS_CB_VALIDATOR_SYNC_BALANCE, diff --git a/makefile b/makefile index e2b3e4f8..f9b7b801 100644 --- a/makefile +++ b/makefile @@ -57,7 +57,8 @@ test-unit: cargo test --features "test" TEST_FILE ?= ** -LOGS ?= +NO_LOGS=true + test-contracts: linear_test mock-staking-pool mock-fungible-token mock-dex mock-lockup mock-whitelist @mkdir -p ./tests/compiled-contracts/ @cp ./res/linear_test.wasm ./tests/compiled-contracts/linear.wasm @@ -68,7 +69,7 @@ test-contracts: linear_test mock-staking-pool mock-fungible-token mock-dex mock- @cp ./res/mock_whitelist.wasm ./tests/compiled-contracts/mock_whitelist.wasm test-linear: test-contracts - cd tests && NEAR_PRINT_LOGS=$(LOGS) npx ava --timeout=2m __tests__/linear/$(TEST_FILE).ava.ts --verbose + cd tests && NEAR_WORKSPACES_NO_LOGS=$(NO_LOGS) npx ava --timeout=2m __tests__/linear/$(TEST_FILE).ava.ts --verbose test-mock-staking-pool: mock-staking-pool @mkdir -p ./tests/compiled-contracts/ diff --git a/tests/__tests__/linear/helper.ts b/tests/__tests__/linear/helper.ts index a584d878..c534a974 100644 --- a/tests/__tests__/linear/helper.ts +++ b/tests/__tests__/linear/helper.ts @@ -1,19 +1,19 @@ +import anyTest, { TestFn } from 'ava'; import { - Worker, - NEAR, - NearAccount, BN, Gas, + NEAR, + NearAccount, TransactionResult, + Worker, } from 'near-workspaces'; -import anyTest, { TestFn } from 'ava'; export const test = anyTest as TestFn; export const ONE_YOCTO = '1'; export const NUM_EPOCHS_TO_UNLOCK = 4; export const MAX_SYNC_BALANCE_DIFF = NEAR.from(100); -export const MANAGER_SYNC_BALANCE_DIFF_THRESHOLD = NEAR.from(1_000_000); +export const SYNC_BALANCE_DIFF_THRESHOLD = NEAR.from(100); interface RewardFee { numerator: number; diff --git a/tests/__tests__/linear/sync-balance.ava.ts b/tests/__tests__/linear/sync-balance.ava.ts index 70a0ecb7..86cfc235 100644 --- a/tests/__tests__/linear/sync-balance.ava.ts +++ b/tests/__tests__/linear/sync-balance.ava.ts @@ -1,16 +1,14 @@ +import { Gas, NEAR, NearAccount } from 'near-workspaces'; import { - MANAGER_SYNC_BALANCE_DIFF_THRESHOLD, MAX_SYNC_BALANCE_DIFF, - assertFailure, + SYNC_BALANCE_DIFF_THRESHOLD, createStakingPool, epochStake, epochUnstake, getValidator, initWorkspace, - setManager, - test, + test } from './helper'; -import { Gas, NEAR, NearAccount } from 'near-workspaces'; function assertValidatorAmountHelper( test: any, @@ -38,207 +36,210 @@ test.afterEach(async (t) => { await t.context.worker.tearDown(); }); -test('sync balance failure after stake/unstake', async (t) => { - const { root, contract, alice, owner } = t.context; - const assertValidator = assertValidatorAmountHelper(t, contract, owner); - const v1 = await createStakingPool(root, 'v1'); - const v2 = await createStakingPool(root, 'v2'); - - await owner.call( - contract, - 'add_validator', - { - validator_id: v1.accountId, - weight: 10, - }, - { - gas: Gas.parse('100 Tgas'), - }, - ); - await owner.call( - contract, - 'add_validator', - { - validator_id: v2.accountId, - weight: 10, - }, - { - gas: Gas.parse('100 Tgas'), - }, - ); - - // 10 NEAR already in the contract - await alice.call( - contract, - 'deposit_and_stake', - {}, - { - attachedDeposit: NEAR.parse('50'), - }, - ); - - // -- 1. total balance diff > MAX_SYNC_BALANCE_DIFF - const diff = MAX_SYNC_BALANCE_DIFF.addn(1); - - await owner.call(v1, 'set_balance_delta', { - staked_delta: diff.toString(10), - unstaked_delta: diff.toString(10), - }); - - for (let i = 0; i < 2; i++) { - await epochStake(owner, contract); - } - - // v1 amount should not change - await assertValidator(v1, NEAR.parse('30').toString(10), '0'); - - await owner.call(contract, 'set_epoch_height', { epoch: 11 }); - - await alice.call(contract, 'unstake_all', {}); - - for (let i = 0; i < 2; i++) { - await epochUnstake(alice, contract); - } - - // v2 amount should not change - await assertValidator( - v2, - NEAR.parse('5').toString(10), - NEAR.parse('25').toString(10), - ); -}); +test( + 'sync balance failure after stake/unstake', + async (t) => { + const { root, contract, alice, owner } = t.context; + const assertValidator = assertValidatorAmountHelper(t, contract, owner); + const v1 = await createStakingPool(root, 'v1'); + const v2 = await createStakingPool(root, 'v2'); -test('sync balance after stake/unstake', async (t) => { - const { root, contract, alice, owner } = t.context; - const assertValidator = assertValidatorAmountHelper(t, contract, owner); - const v1 = await createStakingPool(root, 'v1'); - const v2 = await createStakingPool(root, 'v2'); - - await owner.call( - contract, - 'add_validator', - { - validator_id: v1.accountId, - weight: 10, - }, - { - gas: Gas.parse('100 Tgas'), - }, - ); - await owner.call( - contract, - 'add_validator', - { - validator_id: v2.accountId, - weight: 10, - }, - { - gas: Gas.parse('100 Tgas'), - }, - ); - - // 10 NEAR already in the contract - await alice.call( - contract, - 'deposit_and_stake', - {}, - { - attachedDeposit: NEAR.parse('50'), - }, - ); - - // -- amount balance diff < MAX_SYNC_BALANCE_DIFF - const diff = MAX_SYNC_BALANCE_DIFF.subn(1); - await owner.call(v2, 'set_balance_delta', { - staked_delta: diff.toString(10), - unstaked_delta: diff.toString(10), - }); - - for (let i = 0; i < 2; i++) { - await epochStake(alice, contract); - } - - await assertValidator( - v2, - NEAR.parse('30').sub(diff).toString(10), - diff.toString(10), - ); - - await owner.call(contract, 'set_epoch_height', { epoch: 11 }); - - await owner.call(v1, 'set_balance_delta', { - staked_delta: diff.toString(10), - unstaked_delta: diff.toString(10), - }); - - await alice.call(contract, 'unstake_all', {}); - - for (let i = 0; i < 2; i++) { - await epochUnstake(owner, contract); - } - - await assertValidator( - v1, - NEAR.parse('5').sub(diff).toString(10), - NEAR.parse('25').add(diff).toString(10), - ); -}); + await owner.call( + contract, + 'add_validator', + { + validator_id: v1.accountId, + weight: 10, + }, + { + gas: Gas.parse('100 Tgas'), + }, + ); + await owner.call( + contract, + 'add_validator', + { + validator_id: v2.accountId, + weight: 10, + }, + { + gas: Gas.parse('100 Tgas'), + }, + ); + + // 10 NEAR already in the contract + await alice.call( + contract, + 'deposit_and_stake', + {}, + { + attachedDeposit: NEAR.parse('50'), + }, + ); + + // -- 1. total balance diff > MAX_SYNC_BALANCE_DIFF + const diff = MAX_SYNC_BALANCE_DIFF.addn(1); + + await owner.call(v1, 'set_balance_delta', { + staked_delta: diff.toString(10), + unstaked_delta: diff.toString(10), + }); + + for (let i = 0; i < 2; i++) { + await epochStake(owner, contract); + } + + // v1 amount should not change + await assertValidator(v1, NEAR.parse('30').toString(10), '0'); + + await owner.call(contract, 'set_epoch_height', { epoch: 11 }); + + await alice.call(contract, 'unstake_all', {}); + + for (let i = 0; i < 2; i++) { + await epochUnstake(alice, contract); + } + + // v2 amount should not change + await assertValidator( + v2, + NEAR.parse('5').toString(10), + NEAR.parse('25').toString(10), + ); + }, +); + +test( + 'sync balance after stake/unstake', + async (t) => { + const { root, contract, alice, owner } = t.context; + const assertValidator = assertValidatorAmountHelper(t, contract, owner); + const v1 = await createStakingPool(root, 'v1'); + const v2 = await createStakingPool(root, 'v2'); + + await owner.call( + contract, + 'add_validator', + { + validator_id: v1.accountId, + weight: 10, + }, + { + gas: Gas.parse('100 Tgas'), + }, + ); + await owner.call( + contract, + 'add_validator', + { + validator_id: v2.accountId, + weight: 10, + }, + { + gas: Gas.parse('100 Tgas'), + }, + ); + + // 10 NEAR already in the contract + await alice.call( + contract, + 'deposit_and_stake', + {}, + { + attachedDeposit: NEAR.parse('50'), + }, + ); + + // -- amount balance diff < MAX_SYNC_BALANCE_DIFF + const diff = MAX_SYNC_BALANCE_DIFF.subn(1); + await owner.call(v2, 'set_balance_delta', { + staked_delta: diff.toString(10), + unstaked_delta: diff.toString(10), + }); + + for (let i = 0; i < 2; i++) { + await epochStake(alice, contract); + } + + await assertValidator( + v2, + NEAR.parse('30').sub(diff).toString(10), + diff.toString(10), + ); + + await owner.call(contract, 'set_epoch_height', { epoch: 11 }); + + await owner.call(v1, 'set_balance_delta', { + staked_delta: diff.toString(10), + unstaked_delta: diff.toString(10), + }); + + await alice.call(contract, 'unstake_all', {}); + + for (let i = 0; i < 2; i++) { + await epochUnstake(owner, contract); + } + + await assertValidator( + v1, + NEAR.parse('5').sub(diff).toString(10), + NEAR.parse('25').add(diff).toString(10), + ); + }, +); + +test( + 'sync balance failure', + async (t) => { + const { root, contract, alice, bob, owner } = t.context; + + const assertValidator = assertValidatorAmountHelper(t, contract, owner); + const v1 = await createStakingPool(root, 'v1'); + const v2 = await createStakingPool(root, 'v2'); + await owner.call( + contract, + 'add_validator', + { + validator_id: v1.accountId, + weight: 10, + }, + { + gas: Gas.parse('100 Tgas'), + }, + ); + await owner.call( + contract, + 'add_validator', + { + validator_id: v2.accountId, + weight: 10, + }, + { + gas: Gas.parse('100 Tgas'), + }, + ); + // 10 NEAR already in the contract + await alice.call( + contract, + 'deposit_and_stake', + {}, + { + attachedDeposit: NEAR.parse('50'), + }, + ); + + // -- 1. total balance diff > SYNC_BALANCE_DIFF_THRESHOLD + const diff = SYNC_BALANCE_DIFF_THRESHOLD.addn(1); + await owner.call(v1, 'set_balance_delta', { + staked_delta: '0', + unstaked_delta: diff.toString(10), + }); + + for (let i = 0; i < 2; i++) { + await epochStake(owner, contract); + } -test('sync balance by manager failure', async (t) => { - const { root, contract, alice, bob, owner } = t.context; - // set bob as manager - await setManager(root, contract, owner, bob); - - const assertValidator = assertValidatorAmountHelper(t, contract, owner); - const v1 = await createStakingPool(root, 'v1'); - const v2 = await createStakingPool(root, 'v2'); - await owner.call( - contract, - 'add_validator', - { - validator_id: v1.accountId, - weight: 10, - }, - { - gas: Gas.parse('100 Tgas'), - }, - ); - await owner.call( - contract, - 'add_validator', - { - validator_id: v2.accountId, - weight: 10, - }, - { - gas: Gas.parse('100 Tgas'), - }, - ); - // 10 NEAR already in the contract - await alice.call( - contract, - 'deposit_and_stake', - {}, - { - attachedDeposit: NEAR.parse('50'), - }, - ); - - // -- 1. total balance diff > MANAGER_SYNC_BALANCE_DIFF_THRESHOLD - const diff = MANAGER_SYNC_BALANCE_DIFF_THRESHOLD.addn(1); - await owner.call(v1, 'set_balance_delta', { - staked_delta: '0', - unstaked_delta: diff.toString(10), - }); - - for (let i = 0; i < 2; i++) { - await epochStake(owner, contract); - } - - // sync balance only allowed by manager - await assertFailure( - t, - alice.call( + await bob.call( contract, 'sync_balance_from_validator', { @@ -247,153 +248,142 @@ test('sync balance by manager failure', async (t) => { { gas: Gas.parse('200 Tgas'), }, - ), - 'Only manager can perform this action', - ); - - await bob.call( - contract, - 'sync_balance_from_validator', - { - validator_id: v1.accountId, - }, - { - gas: Gas.parse('200 Tgas'), - }, - ); - - // v1 amount should not change - await assertValidator(v1, '30000000000000000000000000', '0'); - - // -- 2. amount balance diff > MANAGER_SYNC_BALANCE_DIFF_THRESHOLD - await owner.call(v2, 'set_balance_delta', { - staked_delta: diff.toString(10), - unstaked_delta: diff.toString(10), - }); - - await owner.call(contract, 'set_epoch_height', { epoch: 11 }); - - await alice.call(contract, 'unstake_all', {}); - - for (let i = 0; i < 2; i++) { - await epochUnstake(alice, contract); - } - - await bob.call( - contract, - 'sync_balance_from_validator', - { - validator_id: v2.accountId, - }, - { - gas: Gas.parse('200 Tgas'), - }, - ); - - // v2 amount should not change - await assertValidator( - v2, - NEAR.parse('5').toString(10), - NEAR.parse('25').toString(10), - ); -}); + ); -test('sync balance by manager', async (t) => { - const { root, contract, alice, bob, owner } = t.context; - // set bob as manager - await setManager(root, contract, owner, bob); - - const assertValidator = assertValidatorAmountHelper(t, contract, owner); - const v1 = await createStakingPool(root, 'v1'); - const v2 = await createStakingPool(root, 'v2'); - await owner.call( - contract, - 'add_validator', - { - validator_id: v1.accountId, - weight: 10, - }, - { - gas: Gas.parse('100 Tgas'), - }, - ); - await owner.call( - contract, - 'add_validator', - { - validator_id: v2.accountId, - weight: 10, - }, - { - gas: Gas.parse('100 Tgas'), - }, - ); - // 10 NEAR already in the contract - await alice.call( - contract, - 'deposit_and_stake', - {}, - { - attachedDeposit: NEAR.parse('50'), - }, - ); - - // -- amount balance diff < MANAGER_SYNC_BALANCE_DIFF_THRESHOLD - const diff = MANAGER_SYNC_BALANCE_DIFF_THRESHOLD.subn(1); - await owner.call(v1, 'set_balance_delta', { - staked_delta: diff.toString(10), - unstaked_delta: diff.toString(10), - }); - - for (let i = 0; i < 2; i++) { - await epochStake(alice, contract); - } - - await bob.call( - contract, - 'sync_balance_from_validator', - { - validator_id: v1.accountId, - }, - { - gas: Gas.parse('200 Tgas'), - }, - ); - - await assertValidator( - v1, - NEAR.parse('30').sub(diff).toString(10), - diff.toString(10), - ); - - await owner.call(v2, 'set_balance_delta', { - staked_delta: diff.toString(10), - unstaked_delta: diff.toString(10), - }); - - await owner.call(contract, 'set_epoch_height', { epoch: 11 }); - - await alice.call(contract, 'unstake_all', {}); - - for (let i = 0; i < 2; i++) { - await epochUnstake(alice, contract); - } - - await bob.call( - contract, - 'sync_balance_from_validator', - { - validator_id: v2.accountId, - }, - { - gas: Gas.parse('200 Tgas'), - }, - ); - - // v2 amount should not change - await assertValidator( - v2, - NEAR.parse('5').sub(diff).toString(10), - NEAR.parse('25').add(diff).toString(10), - ); -}); + // v1 amount should not change + await assertValidator(v1, '30000000000000000000000000', '0'); + + // -- 2. amount balance diff > SYNC_BALANCE_DIFF_THRESHOLD + await owner.call(v2, 'set_balance_delta', { + staked_delta: diff.toString(10), + unstaked_delta: diff.toString(10), + }); + + await owner.call(contract, 'set_epoch_height', { epoch: 11 }); + + await alice.call(contract, 'unstake_all', {}); + + for (let i = 0; i < 2; i++) { + await epochUnstake(alice, contract); + } + + await bob.call( + contract, + 'sync_balance_from_validator', + { + validator_id: v2.accountId, + }, + { + gas: Gas.parse('200 Tgas'), + }, + ); + + // v2 amount should not change + await assertValidator( + v2, + NEAR.parse('5').toString(10), + NEAR.parse('25').toString(10), + ); + }, +); + +test( + 'sync balance', + async (t) => { + const { root, contract, alice, bob, owner } = t.context; + + const assertValidator = assertValidatorAmountHelper(t, contract, owner); + const v1 = await createStakingPool(root, 'v1'); + const v2 = await createStakingPool(root, 'v2'); + await owner.call( + contract, + 'add_validator', + { + validator_id: v1.accountId, + weight: 10, + }, + { + gas: Gas.parse('100 Tgas'), + }, + ); + await owner.call( + contract, + 'add_validator', + { + validator_id: v2.accountId, + weight: 10, + }, + { + gas: Gas.parse('100 Tgas'), + }, + ); + // 10 NEAR already in the contract + await alice.call( + contract, + 'deposit_and_stake', + {}, + { + attachedDeposit: NEAR.parse('50'), + }, + ); + + // -- amount balance diff < SYNC_BALANCE_DIFF_THRESHOLD + const diff = SYNC_BALANCE_DIFF_THRESHOLD.subn(1); + await owner.call(v1, 'set_balance_delta', { + staked_delta: diff.toString(10), + unstaked_delta: diff.toString(10), + }); + + for (let i = 0; i < 2; i++) { + await epochStake(alice, contract); + } + + await bob.call( + contract, + 'sync_balance_from_validator', + { + validator_id: v1.accountId, + }, + { + gas: Gas.parse('200 Tgas'), + }, + ); + + await assertValidator( + v1, + NEAR.parse('30').sub(diff).toString(10), + diff.toString(10), + ); + + await owner.call(v2, 'set_balance_delta', { + staked_delta: diff.toString(10), + unstaked_delta: diff.toString(10), + }); + + await owner.call(contract, 'set_epoch_height', { epoch: 11 }); + + await alice.call(contract, 'unstake_all', {}); + + for (let i = 0; i < 2; i++) { + await epochUnstake(alice, contract); + } + + await bob.call( + contract, + 'sync_balance_from_validator', + { + validator_id: v2.accountId, + }, + { + gas: Gas.parse('200 Tgas'), + }, + ); + + // v2 amount should not change + await assertValidator( + v2, + NEAR.parse('5').sub(diff).toString(10), + NEAR.parse('25').add(diff).toString(10), + ); + }, +); From a93ba0ca432d4afa18b090131ae31dc65955a593 Mon Sep 17 00:00:00 2001 From: dongcool <95206510+dongcool@users.noreply.github.com> Date: Fri, 18 Apr 2025 10:45:54 +0800 Subject: [PATCH 2/3] update --- contracts/linear/src/epoch_actions.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/linear/src/epoch_actions.rs b/contracts/linear/src/epoch_actions.rs index 48398bf9..90d75007 100644 --- a/contracts/linear/src/epoch_actions.rs +++ b/contracts/linear/src/epoch_actions.rs @@ -409,7 +409,6 @@ impl LiquidStakingContract { /// /// Params: /// - validator_id: the validator to sync balance - /// - post_action: sync balance is called after stake or unstake #[private] pub fn validator_get_account_callback( &mut self, From 0346038aac5d30508b17d887be9dc651130ae34d Mon Sep 17 00:00:00 2001 From: Linguists <95207870+linguists@users.noreply.github.com> Date: Fri, 18 Apr 2025 11:44:43 +0800 Subject: [PATCH 3/3] chore: update github workflow --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9e5ffcd7..1a4c27ab 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,7 +31,7 @@ jobs: - uses: Swatinem/rust-cache@v2 # Set up Node environment - name: Setup Node - uses: actions/setup-node@v3.1.1 + uses: actions/setup-node@v4 with: node-version: 20.12.0 cache: npm