diff --git a/src/helpers/cosmos.ts b/src/helpers/cosmos.ts index 2d07d950..641da855 100644 --- a/src/helpers/cosmos.ts +++ b/src/helpers/cosmos.ts @@ -92,6 +92,10 @@ cosmosclient.codec.register( '/cosmos.adminmodule.adminmodule.MsgSubmitProposal', adminmodule.MsgSubmitProposal, ); +cosmosclient.codec.register( + '/cosmos.adminmodule.adminmodule.MsgSubmitProposalLegacy', + adminmodule.MsgSubmitProposalLegacy, +); cosmosclient.codec.register( '/ibc.lightclients.tendermint.v1.ClientState', ibcProto.lightclients.tendermint.v1.ClientState, @@ -674,7 +678,7 @@ export class WalletWrapper { mode: cosmosclient.rest.tx.BroadcastTxMode = cosmosclient.rest.tx .BroadcastTxMode.Sync, ): Promise { - const msg = new adminmodule.MsgSubmitProposal({ + const msg = new adminmodule.MsgSubmitProposalLegacy({ content: cosmosclient.codec.instanceToProtoAny( new cosmosclient.proto.cosmos.params.v1beta1.ParameterChangeProposal({ title: 'mock', diff --git a/src/helpers/dao.ts b/src/helpers/dao.ts index ed10fe73..962daf42 100644 --- a/src/helpers/dao.ts +++ b/src/helpers/dao.ts @@ -1,5 +1,6 @@ import axios from 'axios'; import { + ADMIN_MODULE_ADDRESS, CosmosWrapper, createBankMessage, getEventAttribute, @@ -22,6 +23,7 @@ import { clientUpdateProposal, paramChangeProposal, ParamChangeProposalInfo, + pinCodesCustomAutrhorityProposal, pinCodesProposal, removeSchedule, SendProposalInfo, @@ -831,7 +833,7 @@ export class DaoMember { proposal_execute_message: { message: JSON.stringify({ '@type': '/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade', - authority: 'neutron1hxskfdxpp5hqgtjj6am6nkjefhfzj359x0ar3z', + authority: ADMIN_MODULE_ADDRESS, plan: { name, height, @@ -880,6 +882,36 @@ export class DaoMember { deposit, ); } + /** + * submitCancelSoftwareUpgradeProposal creates proposal. + */ + async submitBankUpdateParamsProposal( + title: string, + description: string, + deposit: string, + ): Promise { + const message = { + custom: { + submit_admin_proposal: { + admin_proposal: { + proposal_execute_message: { + message: JSON.stringify({ + '@type': '/cosmos.bank.v1beta1.MsgUpdateParams', + authority: ADMIN_MODULE_ADDRESS, + params: { default_send_enabled: false }, + }), + }, + }, + }, + }, + }; + return await this.submitSingleChoiceProposal( + title, + description, + [message], + deposit, + ); + } async supportAndExecuteProposal( proposalId: number, @@ -1127,6 +1159,32 @@ export class DaoMember { ); } + /** + * submitPinCodesCustomAuthorityProposal creates proposal which pins given code ids to wasmvm. + */ + async submitPinCodesCustomAuthorityProposal( + title: string, + description: string, + codesIds: number[], + amount: string, + authority: string, + ): Promise { + const message = pinCodesCustomAutrhorityProposal( + { + title, + description, + codes_ids: codesIds, + }, + authority, + ); + return await this.submitSingleChoiceProposal( + title, + description, + [message], + amount, + ); + } + /** * submitUnpinCodesProposal creates proposal which unpins given code ids to wasmvm. */ diff --git a/src/helpers/proposal.ts b/src/helpers/proposal.ts index 0933cadf..b7f986cf 100644 --- a/src/helpers/proposal.ts +++ b/src/helpers/proposal.ts @@ -157,6 +157,25 @@ export const pinCodesProposal = (info: PinCodesInfo): any => ({ }, }); +export const pinCodesCustomAutrhorityProposal = ( + info: PinCodesInfo, + authority: string, +): any => ({ + custom: { + submit_admin_proposal: { + admin_proposal: { + proposal_execute_message: { + message: JSON.stringify({ + '@type': '/cosmwasm.wasm.v1.MsgPinCodes', + authority: authority, + code_ids: info.codes_ids, + }), + }, + }, + }, + }, +}); + export const unpinCodesProposal = (info: PinCodesInfo): any => ({ custom: { submit_admin_proposal: { diff --git a/src/testcases/parallel/governance.test.ts b/src/testcases/parallel/governance.test.ts index dabad8f6..ddc00b2a 100644 --- a/src/testcases/parallel/governance.test.ts +++ b/src/testcases/parallel/governance.test.ts @@ -347,6 +347,24 @@ describe('Neutron / Governance', () => { ); }); + test('create proposal #18, will pass', async () => { + await daoMember1.submitPinCodesCustomAuthorityProposal( + 'Proposal #18', + 'Pin codes proposal with wrong authority. This one will pass & fail on execution', + [1, 2], + '1000', + daoMember1.user.wallet.address.toString(), + ); + }); + + test('create proposal #19, will pass', async () => { + await daoMember1.submitBankUpdateParamsProposal( + 'Proposal #19', + 'Update params for bank module proposal. This one will pass & fail on execution due type is not whitelisted', + '1000', + ); + }); + test('create multi-choice proposal #1, will be picked choice 1', async () => { await daoMember1.submitMultiChoiceParameterChangeProposal( [ @@ -954,19 +972,78 @@ describe('Neutron / Governance', () => { expect(queryResult).toEqual(null); }); }); + + describe('vote for proposal #18 (no, yes, yes)', () => { + const proposalId = 18; + test('vote NO from wallet 1', async () => { + await daoMember1.voteNo(proposalId); + }); + test('vote YES from wallet 2', async () => { + await daoMember2.voteYes(proposalId); + }); + test('vote YES from wallet 3', async () => { + await daoMember3.voteYes(proposalId); + }); + }); + + describe('execute proposal #18', () => { + const proposalId = 18; + test('check if proposal is passed', async () => { + await dao.checkPassedProposal(proposalId); + }); + test('execute passed proposal, should fail', async () => { + let rawLog: any; + try { + rawLog = (await daoMember1.executeProposal(proposalId)).raw_log; + } catch (e) { + rawLog = e.message; + } + expect( + rawLog.includes( + 'authority in incoming msg is not equal to admin module', + ), + ); + }); + }); + + describe('vote for proposal #19 (no, yes, yes)', () => { + const proposalId = 19; + test('vote NO from wallet 1', async () => { + await daoMember1.voteNo(proposalId); + }); + test('vote YES from wallet 2', async () => { + await daoMember2.voteYes(proposalId); + }); + test('vote YES from wallet 3', async () => { + await daoMember3.voteYes(proposalId); + }); + }); + + describe('execute proposal #19', () => { + const proposalId = 19; + test('check if proposal is passed', async () => { + await dao.checkPassedProposal(proposalId); + }); + test('execute passed proposal, should fail', async () => { + let rawLog: any; + try { + rawLog = (await daoMember1.executeProposal(proposalId)).raw_log; + } catch (e) { + rawLog = e.message; + } + console.log('IMPORTANT' + rawLog); + expect(rawLog.includes('sdk.Msg is not whitelisted')); + }); + }); + describe('check that only admin can create valid proposals', () => { test('submit admin proposal from non-admin addr, should fail', async () => { - console.log('1'); - const hostStatus = await neutronChain.queryHostEnabled(); - expect(hostStatus).toEqual(false); - console.log('2'); const res = await daoMember1.user.msgSendDirectProposal( 'icahost', 'HostEnabled', 'true', ); expect(res.code).toEqual(1); // must be admin to submit proposals to admin-module - console.log('3'); const afterProposalHostStatus = await neutronChain.queryHostEnabled(); expect(afterProposalHostStatus).toEqual(false); });