From 0e6eb78dd62a386ab8a61881cc87466d0637041f Mon Sep 17 00:00:00 2001 From: Noah Prince Date: Thu, 9 Jan 2025 13:13:15 -0800 Subject: [PATCH 1/2] More bugfixes for veHNT and 138 --- .../delegation/extend_expiration_ts_v0.rs | 14 +- programs/helium-sub-daos/src/utils.rs | 2 +- tests/helium-sub-daos.ts | 130 +++++++++++------- 3 files changed, 93 insertions(+), 53 deletions(-) diff --git a/programs/helium-sub-daos/src/instructions/delegation/extend_expiration_ts_v0.rs b/programs/helium-sub-daos/src/instructions/delegation/extend_expiration_ts_v0.rs index 173269285..6324865ab 100644 --- a/programs/helium-sub-daos/src/instructions/delegation/extend_expiration_ts_v0.rs +++ b/programs/helium-sub-daos/src/instructions/delegation/extend_expiration_ts_v0.rs @@ -105,16 +105,20 @@ pub fn handler(ctx: Context) -> Result<()> { .get_current_season(registrar.clock_unix_timestamp()) .unwrap() .end; - ctx.accounts.delegated_position.expiration_ts = expiration_ts; let epoch = current_epoch(registrar.clock_unix_timestamp()); // Calculate vehnt info once + msg!( + "Calculating vehnt info for old expiration ts {}", + ctx.accounts.delegated_position.expiration_ts + ); let vehnt_info_old = caclulate_vhnt_info( ctx.accounts.delegated_position.start_ts, position, voting_mint_config, - i64::MAX, + ctx.accounts.delegated_position.expiration_ts, )?; + ctx.accounts.delegated_position.expiration_ts = expiration_ts; let vehnt_info_new = caclulate_vhnt_info( ctx.accounts.delegated_position.start_ts, position, @@ -181,10 +185,14 @@ pub fn handler(ctx: Context) -> Result<()> { let genesis_end_is_closing = ctx.accounts.genesis_end_sub_dao_epoch_info.key() == ctx.accounts.closing_time_sub_dao_epoch_info.key(); - if !ctx.accounts.genesis_end_sub_dao_epoch_info.data_len() == 0 { + let genesis_end_is_old_closing = ctx.accounts.genesis_end_sub_dao_epoch_info.key() + == ctx.accounts.old_closing_time_sub_dao_epoch_info.key(); + if ctx.accounts.genesis_end_sub_dao_epoch_info.data_len() > 0 { let mut parsed: Account; let genesis_end_sdei: &mut Account = if genesis_end_is_closing { &mut ctx.accounts.closing_time_sub_dao_epoch_info + } else if genesis_end_is_old_closing { + &mut ctx.accounts.old_closing_time_sub_dao_epoch_info } else { parsed = Account::try_from( &ctx diff --git a/programs/helium-sub-daos/src/utils.rs b/programs/helium-sub-daos/src/utils.rs index 4e157da50..bc629e220 100644 --- a/programs/helium-sub-daos/src/utils.rs +++ b/programs/helium-sub-daos/src/utils.rs @@ -325,7 +325,7 @@ pub fn caclulate_vhnt_info( .checked_add(i64::try_from(seconds_to_genesis).unwrap()) .unwrap(), )?; - let vehnt_at_genesis_end_exact = if has_genesis && position.genesis_end < expiration_ts { + let vehnt_at_genesis_end_exact = if has_genesis { position.voting_power_precise(voting_mint_config, position.genesis_end)? } else { position.voting_power_precise(voting_mint_config, curr_ts)? diff --git a/tests/helium-sub-daos.ts b/tests/helium-sub-daos.ts index d2c4ed4ad..51f662f39 100644 --- a/tests/helium-sub-daos.ts +++ b/tests/helium-sub-daos.ts @@ -247,7 +247,7 @@ describe("helium-sub-daos", () => { daoKey(hntMint)[0], genesisVotePowerMultiplierExpirationTs, 3, - proxySeasonEnd, + proxySeasonEnd )); ({ @@ -879,7 +879,9 @@ describe("helium-sub-daos", () => { const preMobileBalance = AccountLayout.decode( (await provider.connection.getAccountInfo(rewardsEscrow))?.data! ).amount; - const { pubkeys: { prevSubDaoEpochInfo, daoEpochInfo } } = await program.methods + const { + pubkeys: { prevSubDaoEpochInfo, daoEpochInfo }, + } = await program.methods .issueRewardsV0({ epoch, }) @@ -888,9 +890,20 @@ describe("helium-sub-daos", () => { }) .rpcAndKeys({ skipPreflight: true }); - console.log("subDaoEpochInfo", await program.account.subDaoEpochInfoV0.fetch(subDaoEpochInfo!)); - console.log("prevSubDaoEpochInfo", await program.account.subDaoEpochInfoV0.fetch(prevSubDaoEpochInfo!)); - console.log("daoEpochInfo", await program.account.daoEpochInfoV0.fetch(daoEpochInfo!)); + console.log( + "subDaoEpochInfo", + await program.account.subDaoEpochInfoV0.fetch(subDaoEpochInfo!) + ); + console.log( + "prevSubDaoEpochInfo", + await program.account.subDaoEpochInfoV0.fetch( + prevSubDaoEpochInfo! + ) + ); + console.log( + "daoEpochInfo", + await program.account.daoEpochInfoV0.fetch(daoEpochInfo!) + ); const postBalance = AccountLayout.decode( (await provider.connection.getAccountInfo(treasury))?.data! @@ -1232,9 +1245,11 @@ describe("helium-sub-daos", () => { }); it("allows adding expiration ts", async () => { - const registrarAcc = await vsrProgram.account.registrar.fetch(registrar); + const registrarAcc = await vsrProgram.account.registrar.fetch( + registrar + ); const proxyConfig = registrarAcc.proxyConfig; - + ({ position, vault } = await createPosition( vsrProgram, provider, @@ -1248,7 +1263,9 @@ describe("helium-sub-daos", () => { }, positionAuthorityKp )); - const { pubkeys: { closingTimeSubDaoEpochInfo, genesisEndSubDaoEpochInfo } } = await program.methods + const { + pubkeys: { closingTimeSubDaoEpochInfo, genesisEndSubDaoEpochInfo }, + } = await program.methods .delegateV0() .accounts({ position, @@ -1257,34 +1274,36 @@ describe("helium-sub-daos", () => { }) .signers([positionAuthorityKp]) .rpcAndKeys({ skipPreflight: true }); - const seasonEnd = new BN( - new Date().valueOf() / 1000 + EPOCH_LENGTH * 5 - ); - await proxyProgram.methods - .updateProxyConfigV0({ - maxProxyTime: null, - seasons: [ - { - start: new BN(0), - end: seasonEnd, - }, - ], - }) - .accounts({ - proxyConfig, - authority: me, - }) - .rpc({ skipPreflight: true }); + const seasonEnd = new BN( + new Date().valueOf() / 1000 + EPOCH_LENGTH * 5 + ); + await proxyProgram.methods + .updateProxyConfigV0({ + maxProxyTime: null, + seasons: [ + { + start: new BN(0), + end: seasonEnd, + }, + ], + }) + .accounts({ + proxyConfig, + authority: me, + }) + .rpc({ skipPreflight: true }); const subDaoEpochInfo = await program.account.subDaoEpochInfoV0.fetch( closingTimeSubDaoEpochInfo! ); - const expectedFallRates = subDaoEpochInfo.fallRatesFromClosingPositions.toString(); - const expectedVehntInClosingPositions = subDaoEpochInfo.vehntInClosingPositions.toString(); - + const expectedFallRates = + subDaoEpochInfo.fallRatesFromClosingPositions.toString(); + const expectedVehntInClosingPositions = + subDaoEpochInfo.vehntInClosingPositions.toString(); const newClosingTimeSubDaoEpochInfo = subDaoEpochInfoKey( subDao, seasonEnd - )[0] + )[0]; + await program.methods .extendExpirationTsV0() .accounts({ @@ -1297,28 +1316,41 @@ describe("helium-sub-daos", () => { .signers([positionAuthorityKp]) .rpc({ skipPreflight: true }); - const oldSubDaoEpochInfo = await program.account.subDaoEpochInfoV0.fetch(closingTimeSubDaoEpochInfo!); - expect(oldSubDaoEpochInfo.fallRatesFromClosingPositions.toNumber()).to.eq(0); - expect(oldSubDaoEpochInfo.vehntInClosingPositions.toNumber()).to.eq(0); - - const newSubDaoEpochInfo = - await program.account.subDaoEpochInfoV0.fetch( - newClosingTimeSubDaoEpochInfo! - ); - expect(newSubDaoEpochInfo.fallRatesFromClosingPositions.toString()).to.eq(expectedFallRates); - - const genesisEndEpoch = await program.account.subDaoEpochInfoV0.fetch( - genesisEndSubDaoEpochInfo! + console.log( + closingTimeSubDaoEpochInfo!.toBase58(), + newClosingTimeSubDaoEpochInfo!.toBase58() + ); + const oldSubDaoEpochInfo = + await program.account.subDaoEpochInfoV0.fetch( + closingTimeSubDaoEpochInfo! ); - expect(genesisEndEpoch.fallRatesFromClosingPositions.toNumber()).to.eq(0); - expect(genesisEndEpoch.vehntInClosingPositions.toNumber()).to.eq(0); + expect( + oldSubDaoEpochInfo.fallRatesFromClosingPositions.toNumber() + ).to.eq(0); + expect(oldSubDaoEpochInfo.vehntInClosingPositions.toNumber()).to.eq(0); + + const newSubDaoEpochInfo = + await program.account.subDaoEpochInfoV0.fetch( + newClosingTimeSubDaoEpochInfo! + ); + expect( + newSubDaoEpochInfo.fallRatesFromClosingPositions.toString() + ).to.eq(expectedFallRates); + + const genesisEndEpoch = await program.account.subDaoEpochInfoV0.fetch( + genesisEndSubDaoEpochInfo! + ); + expect(genesisEndEpoch.fallRatesFromClosingPositions.toNumber()).to.eq( + 0 + ); + expect(genesisEndEpoch.vehntInClosingPositions.toNumber()).to.eq(0); }); describe("with proxy season that ends before genesis end", () => { before(async () => { // 15 days from now proxySeasonEnd = new BN( - new Date().valueOf() / 1000 + (15 * EPOCH_LENGTH) + new Date().valueOf() / 1000 + 15 * EPOCH_LENGTH ); }); @@ -1446,7 +1478,7 @@ describe("helium-sub-daos", () => { subDaoEpochInfo = await getCurrEpochInfo(); let currTime = subDaoEpochInfo.epoch.toNumber() * EPOCH_LENGTH; let timeStaked = currTime - stakeTime.toNumber(); - let expected = 0 + let expected = 0; expect(toNumber(subDaoEpochInfo.vehntAtEpochStart, 8)).to.be.closeTo( // Fall rates aren't a perfect measurement, we divide the total fall of the position by // the total time staked. Imagine the total fall was 1 and the total time was 3. We would have @@ -1461,7 +1493,7 @@ describe("helium-sub-daos", () => { subDaoEpochInfo = await getCurrEpochInfo(); currTime = subDaoEpochInfo.epoch.toNumber() * EPOCH_LENGTH; timeStaked = currTime - stakeTime.toNumber(); - expected = 0 + expected = 0; expect(toNumber(subDaoEpochInfo.vehntAtEpochStart, 8)).to.be.closeTo( expected, 0.0000001 @@ -1473,7 +1505,7 @@ describe("helium-sub-daos", () => { subDaoEpochInfo = await getCurrEpochInfo(); currTime = subDaoEpochInfo.epoch.toNumber() * EPOCH_LENGTH; timeStaked = currTime - stakeTime.toNumber(); - expected = 0 + expected = 0; expect(toNumber(subDaoEpochInfo.vehntAtEpochStart, 8)).to.be.closeTo( expected, 0.0000001 @@ -1488,7 +1520,7 @@ describe("helium-sub-daos", () => { subDaoEpochInfo = await getCurrEpochInfo(); currTime = subDaoEpochInfo.epoch.toNumber() * EPOCH_LENGTH; timeStaked = currTime - stakeTime.toNumber(); - expected = 0 + expected = 0; expect(toNumber(subDaoEpochInfo.vehntAtEpochStart, 8)).to.be.closeTo( expected, 0.0000001 From c6e8b2bf1ee8e799360b7e85674c0c98735c94b0 Mon Sep 17 00:00:00 2001 From: Noah Prince Date: Thu, 9 Jan 2025 13:58:23 -0800 Subject: [PATCH 2/2] Fix tests --- programs/helium-sub-daos/src/utils.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/programs/helium-sub-daos/src/utils.rs b/programs/helium-sub-daos/src/utils.rs index bc629e220..6fbab666d 100644 --- a/programs/helium-sub-daos/src/utils.rs +++ b/programs/helium-sub-daos/src/utils.rs @@ -340,12 +340,16 @@ pub fn caclulate_vhnt_info( let pre_genesis_end_fall_rate = calculate_fall_rate(vehnt_at_curr_ts, vehnt_at_genesis_end, seconds_to_genesis).unwrap(); - let post_genesis_end_fall_rate = calculate_fall_rate( - vehnt_at_genesis_end_exact, - vehnt_at_delegation_end, - seconds_from_genesis_to_end, - ) - .unwrap(); + let post_genesis_end_fall_rate = if position.genesis_end < delegation_end_ts { + calculate_fall_rate( + vehnt_at_genesis_end_exact, + vehnt_at_delegation_end, + seconds_from_genesis_to_end, + ) + .unwrap() + } else { + 0 + }; let mut genesis_end_vehnt_correction = 0; let mut genesis_end_fall_rate_correction = 0;