Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into feat/whitelist_fee_tiers
Browse files Browse the repository at this point in the history
  • Loading branch information
jcompagni10 committed Feb 24, 2025
2 parents d48fcd1 + f7bb92f commit b755c99
Show file tree
Hide file tree
Showing 3 changed files with 307 additions and 27 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,4 @@
"engines": {
"node": ">=20.0"
}
}
}
288 changes: 283 additions & 5 deletions src/testcases/run_in_band/chain_manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
updateTokenfactoryParamsProposal,
AddSchedule,
RemoveSchedule,
updateGlobalFeeParamsProposal,
updateConsumerParamsProposal,
} from '@neutron-org/neutronjsplus/dist/proposal';
import { LocalState } from '../../helpers/local_state';
import { RunnerTestSuite, inject } from 'vitest';
Expand All @@ -23,6 +25,9 @@ import { QueryClientImpl as AdminQueryClient } from '@neutron-org/neutronjs/cosm
import { QueryClientImpl as TokenfactoryQueryClient } from '@neutron-org/neutronjs/osmosis/tokenfactory/v1beta1/query.rpc.Query';
import { QueryClientImpl as UpgradeQueryClient } from '@neutron-org/neutronjs/cosmos/upgrade/v1beta1/query.rpc.Query';
import { QueryClientImpl as DexQueryClient } from '@neutron-org/neutronjs/neutron/dex/query.rpc.Query';
import { QueryClientImpl as DynamicfeesQueryClient } from '@neutron-org/neutronjs/neutron/dynamicfees/v1/query.rpc.Query';
import { QueryClientImpl as GlobalfeeQueryClient } from '@neutron-org/neutronjs/gaia/globalfee/v1beta1/query.rpc.Query';
import { QueryClientImpl as CCVQueryClient } from '@neutron-org/neutronjs/interchain_security/ccv/consumer/v1/query.rpc.Query';
import { SigningNeutronClient } from '../../helpers/signing_neutron_client';
import config from '../../config.json';
import { Wallet } from '../../helpers/wallet';
Expand All @@ -39,6 +44,9 @@ describe('Neutron / Chain Manager', () => {
let cronQuerier: CronQueryClient;
let tokenfactoryQuerier: TokenfactoryQueryClient;
let dexQuerier: DexQueryClient;
let dynamicfeesQuerier: DynamicfeesQueryClient;
let globalfeeQuerier: GlobalfeeQueryClient;
let ccvQuerier: CCVQueryClient;
let upgradeQuerier: UpgradeQueryClient;
let chainManagerAddress: string;

Expand Down Expand Up @@ -97,6 +105,9 @@ describe('Neutron / Chain Manager', () => {
cronQuerier = new CronQueryClient(neutronRpcClient);
dexQuerier = new DexQueryClient(neutronRpcClient);
upgradeQuerier = new UpgradeQueryClient(neutronRpcClient);
dynamicfeesQuerier = new DynamicfeesQueryClient(neutronRpcClient);
globalfeeQuerier = new GlobalfeeQueryClient(neutronRpcClient);
ccvQuerier = new CCVQueryClient(neutronRpcClient);
});

// We need to do this because the real main dao has a super long voting period.
Expand Down Expand Up @@ -132,7 +143,7 @@ describe('Neutron / Chain Manager', () => {
dao: currentOverruleProposalConfig['dao'],
close_proposal_on_execution_failure:
currentOverruleProposalConfig[
'close_proposal_on_execution_failure'
'close_proposal_on_execution_failure'

Check failure on line 146 in src/testcases/run_in_band/chain_manager.test.ts

View workflow job for this annotation

GitHub Actions / Actions - lint

Insert `··`
],
},
}),
Expand Down Expand Up @@ -206,6 +217,62 @@ describe('Neutron / Chain Manager', () => {
whitelisted_lps: true,
},
},
{
update_ccv_params_permission: {
blocks_per_distribution_transmission: true,
distribution_transmission_channel: true,
provider_fee_pool_addr_str: true,
ccv_timeout_period: true,
transfer_timeout_period: true,
consumer_redistribution_fraction: true,
historical_entries: true,
unbonding_period: true,
soft_opt_out_threshold: true,
reward_denoms: true,
provider_reward_denoms: true,
retry_delay_period: true,
},
},
{
update_globalfee_params_permission: {
minimum_gas_prices: true,
bypass_min_fee_msg_types: true,
max_total_bypass_min_fee_msg_gas_usage: true,
},
},
{
update_dynamicfees_params_permission: {
ntrn_prices: true,
},
},
{
update_ccv_params_permission: {
blocks_per_distribution_transmission: true,
distribution_transmission_channel: true,
provider_fee_pool_addr_str: true,
ccv_timeout_period: true,
transfer_timeout_period: true,
consumer_redistribution_fraction: true,
historical_entries: true,
unbonding_period: true,
soft_opt_out_threshold: true,
reward_denoms: true,
provider_reward_denoms: true,
retry_delay_period: true,
},
},
{
update_globalfee_params_permission: {
minimum_gas_prices: true,
bypass_min_fee_msg_types: true,
max_total_bypass_min_fee_msg_gas_usage: true,
},
},
{
update_dynamicfees_params_permission: {
ntrn_prices: true,
},
},
],
},
},
Expand Down Expand Up @@ -252,6 +319,7 @@ describe('Neutron / Chain Manager', () => {
});

test('execute timelocked: success', async () => {
const cronParamsBefore = await cronQuerier.params();
await waitSeconds(10);

await subdaoMember1.executeTimelockedProposal(proposalId);
Expand All @@ -262,6 +330,12 @@ describe('Neutron / Chain Manager', () => {

const cronParams = await cronQuerier.params();
expect(cronParams.params.limit).toEqual(42n);
// check that every params field before proposal execution differs from the field after proposal execution
expect(
Object.keys(cronParamsBefore).every(
(key) => cronParamsBefore[key] !== cronParams[key],
),
).toBeTrue();
});
});

Expand All @@ -287,15 +361,16 @@ describe('Neutron / Chain Manager', () => {
'1000',
);

const timelockedProp =
await subdaoMember1.supportAndExecuteProposal(proposalId);

const timelockedProp = await subdaoMember1.supportAndExecuteProposal(
proposalId,
);
expect(timelockedProp.id).toEqual(proposalId);
expect(timelockedProp.status).toEqual('timelocked');
expect(timelockedProp.msgs).toHaveLength(1);
});

test('execute timelocked: success', async () => {
const tokenfactoryParamsBefore = await tokenfactoryQuerier.params();
await waitSeconds(10);

await subdaoMember1.executeTimelockedProposal(proposalId);
Expand All @@ -318,13 +393,21 @@ describe('Neutron / Chain Manager', () => {
denomCreator: 'neutron1m9l358xunhhwds0568za49mzhvuxx9ux8xafx2',
},
]);
// check that every params field before proposal execution differs from the field after proposal execution
expect(
Object.keys(tokenfactoryParamsBefore).every(
(key) => tokenfactoryParamsBefore[key] !== tokenfactoryParams[key],
),
).toBeTrue();
});
});

describe('ALLOW_ONLY: change DEX parameters', () => {
let proposalId: number;
const newParams = {
fee_tiers: [1, 2, 99],
// types mixed on purpose, to check contract parser.
// Numeric types in neutron-std can be deserialized from both number and string
fee_tiers: ['1', '2', 99],
paused: true,
max_jits_per_block: 11,
good_til_purge_allowance: 50000,
Expand All @@ -351,6 +434,7 @@ describe('Neutron / Chain Manager', () => {
});

test('execute timelocked: success', async () => {
const dexParamsBefore = await dexQuerier.params();
await waitSeconds(10);

await subdaoMember1.executeTimelockedProposal(proposalId);
Expand All @@ -368,6 +452,200 @@ describe('Neutron / Chain Manager', () => {
'neutron10h9stc5v6ntgeygf5xf945njqq5h32r54rf7kf',
'neutron16yn2gcz24s9qwpuxvrhl3xed0pmhrgwx2mz40zrazfc0pt5kq0psucs6xl',
]);
// check that every params field before proposal execution differs from the field after proposal execution
expect(
Object.keys(dexParamsBefore).every(
(key) => dexParamsBefore[key] !== dexParams[key],
),
).toBeTrue();
});
});

describe('ALLOW_ONLY: change Dynamicfees parameters', () => {
let proposalId: number;
beforeAll(async () => {
proposalId = await subdaoMember1.submitDynamicfeesChangeParamsProposal(
chainManagerAddress,
'Proposal #2',
'Dynamicfees update params proposal. Will pass',
'1000',
{
ntrn_prices: [{ denom: 'newdenom', amount: '0.5' }],
},
);

const timelockedProp = await subdaoMember1.supportAndExecuteProposal(
proposalId,
);

expect(timelockedProp.id).toEqual(proposalId);
expect(timelockedProp.status).toEqual('timelocked');
expect(timelockedProp.msgs).toHaveLength(1);
});

test('execute timelocked: success', async () => {
const dynamicfeesParamsBefore = await dynamicfeesQuerier.params();
await waitSeconds(10);

await subdaoMember1.executeTimelockedProposal(proposalId);
const timelockedProp = await subDao.getTimelockedProposal(proposalId);
expect(timelockedProp.id).toEqual(proposalId);
expect(timelockedProp.status).toEqual('executed');
expect(timelockedProp.msgs).toHaveLength(1);

const dynamicfeesParams = await dynamicfeesQuerier.params();
expect(dynamicfeesParams.params.ntrnPrices).toEqual([
{ denom: 'newdenom', amount: '0.5' },
]);
// check that every params field before proposal execution differs from the field after proposal execution
expect(
Object.keys(dynamicfeesParamsBefore).every(
(key) => dynamicfeesParamsBefore[key] !== dynamicfeesParams[key],
),
).toBeTrue();
});
});

describe('ALLOW_ONLY: change Globalfee parameters', () => {
let proposalId: number;
beforeAll(async () => {
proposalId = await subdaoMember1.submitUpdateParamsGlobalfeeProposal(
chainManagerAddress,
'Proposal #3',
'Globalfee update params proposal. Will pass',
updateGlobalFeeParamsProposal({
minimum_gas_prices: [{ denom: 'untrn', amount: '0.00111' }],
bypass_min_fee_msg_types: ['/gaia.globalfee.v1beta1.MsgUpdateParams'],
max_total_bypass_min_fee_msg_gas_usage: '12345',
}),
'1000',
);

const timelockedProp = await subdaoMember1.supportAndExecuteProposal(
proposalId,
);

expect(timelockedProp.id).toEqual(proposalId);
expect(timelockedProp.status).toEqual('timelocked');
expect(timelockedProp.msgs).toHaveLength(1);
});

test('execute timelocked: success', async () => {
const globalfeeParamsBefore = await globalfeeQuerier.params();
await waitSeconds(10);

await subdaoMember1.executeTimelockedProposal(proposalId);
const timelockedProp = await subDao.getTimelockedProposal(proposalId);
expect(timelockedProp.id).toEqual(proposalId);
expect(timelockedProp.status).toEqual('executed');
expect(timelockedProp.msgs).toHaveLength(1);

const globalfeeParams = await globalfeeQuerier.params();
expect(globalfeeParams.params.minimumGasPrices).toEqual([
{ denom: 'untrn', amount: '0.00111' },
]);
expect(globalfeeParams.params.bypassMinFeeMsgTypes).toEqual([
'/gaia.globalfee.v1beta1.MsgUpdateParams',
]);
expect(globalfeeParams.params.maxTotalBypassMinFeeMsgGasUsage).toEqual(
12345n,
);
// check that every params field before proposal execution differs from the field after proposal execution
expect(
Object.keys(globalfeeParamsBefore).every(
(key) => globalfeeParamsBefore[key] !== globalfeeParams[key],
),
).toBeTrue();
});
});

describe('ALLOW_ONLY: change ccv consumer parameters', () => {
let proposalId: number;
beforeAll(async () => {
proposalId = await subdaoMember1.submitUpdateParamsConsumerProposal(
chainManagerAddress,
'Proposal #4',
'Consumer update params proposal. Will pass',
updateConsumerParamsProposal({
enabled: true,
blocks_per_distribution_transmission: 321,
distribution_transmission_channel: 'channel-23',
provider_fee_pool_addr_str: chainManagerAddress,
ccv_timeout_period: '32s',
transfer_timeout_period: '23s',
consumer_redistribution_fraction: '0.33',
historical_entries: 123,
unbonding_period: '43s',
soft_opt_out_threshold: '0.55',
reward_denoms: ['tia'],
provider_reward_denoms: ['tia'],
retry_delay_period: '43s',
}),
'1000',
);

const timelockedProp = await subdaoMember1.supportAndExecuteProposal(
proposalId,
);

expect(timelockedProp.id).toEqual(proposalId);
expect(timelockedProp.status).toEqual('timelocked');
expect(timelockedProp.msgs).toHaveLength(1);
});

test('execute timelocked: success', async () => {
const ccvParamsBefore = await ccvQuerier.queryParams();
await waitSeconds(10);

await subdaoMember1.executeTimelockedProposal(proposalId);
console.log(
'subdao',
subdaoMember1.dao.contracts.proposals['single'].pre_propose.timelock
.address,
);
const timelockedProp = await subDao.getTimelockedProposal(proposalId);
expect(timelockedProp.id).toEqual(proposalId);
expect(timelockedProp.status).toEqual('executed');
expect(timelockedProp.msgs).toHaveLength(1);

const ccvParams = await ccvQuerier.queryParams();
expect(ccvParams.params.enabled).toEqual(true);
expect(ccvParams.params.blocksPerDistributionTransmission).toEqual(321n);
expect(ccvParams.params.distributionTransmissionChannel).toEqual(
'channel-23',
);
expect(ccvParams.params.providerFeePoolAddrStr).toEqual(
chainManagerAddress,
);
expect(ccvParams.params.ccvTimeoutPeriod).toEqual({
nanos: 0,
seconds: 32n,
});
expect(ccvParams.params.transferTimeoutPeriod).toEqual({
nanos: 0,
seconds: 23n,
});
expect(ccvParams.params.consumerRedistributionFraction).toEqual('0.33');
expect(ccvParams.params.historicalEntries).toEqual(123n);
expect(ccvParams.params.unbondingPeriod).toEqual({
nanos: 0,
seconds: 43n,
});
expect(ccvParams.params.softOptOutThreshold).toEqual('0.55');
expect(ccvParams.params.rewardDenoms).toEqual(['tia']);
expect(ccvParams.params.providerRewardDenoms).toEqual(['tia']);
expect(ccvParams.params.retryDelayPeriod).toEqual({
nanos: 0,
seconds: 43n,
});
// field 'enabled' is readonly, and should not be changed, always equals true
delete ccvParamsBefore['enabled'];
// check that every params field before proposal execution differs from the field after proposal execution
expect(
Object.keys(ccvParamsBefore).every(
(key) => ccvParamsBefore[key] !== ccvParams[key],
),
).toBeTrue();
});
});

Expand Down
Loading

0 comments on commit b755c99

Please sign in to comment.