Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add e2e test for ibc, wasm #361

Merged
merged 7 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,10 @@ var (
// MigalooApp extended ABCI application
type MigalooApp struct {
*baseapp.BaseApp
legacyAmino *codec.LegacyAmino
appCodec codec.Codec
legacyAmino *codec.LegacyAmino
appCodec codec.Codec
txConfig client.TxConfig

interfaceRegistry types.InterfaceRegistry

invCheckPeriod uint
Expand Down Expand Up @@ -342,8 +344,9 @@ func NewMigalooApp(
wasmOpts []wasmkeeper.Option,
baseAppOptions ...func(*baseapp.BaseApp),
) *MigalooApp {
appCodec, legacyAmino, txConfig := encodingConfig.Codec, encodingConfig.Amino, encodingConfig.TxConfig
appCodec, legacyAmino := encodingConfig.Codec, encodingConfig.Amino
interfaceRegistry := encodingConfig.InterfaceRegistry
txConfig := encodingConfig.TxConfig

bApp := baseapp.NewBaseApp(appName, logger, db, encodingConfig.TxConfig.TxDecoder(), baseAppOptions...)
bApp.SetCommitMultiStoreTracer(traceStore)
Expand All @@ -368,6 +371,7 @@ func NewMigalooApp(
BaseApp: bApp,
legacyAmino: legacyAmino,
appCodec: appCodec,
txConfig: txConfig,
interfaceRegistry: interfaceRegistry,
invCheckPeriod: invCheckPeriod,
keys: keys,
Expand Down Expand Up @@ -1112,6 +1116,11 @@ func (app *MigalooApp) AppCodec() codec.Codec {
return app.appCodec
}

// TxConfig returns MigalooApp's TxConfig
func (app *MigalooApp) TxConfig() client.TxConfig {
return app.txConfig
}

// RegisterSwaggerAPI registers swagger route with API Server
func RegisterSwaggerAPI(rtr *mux.Router) {
cosmosStatikFs, err := fs.New()
Expand Down
59 changes: 36 additions & 23 deletions app/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"testing"
"time"

simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"

"cosmossdk.io/math"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/client"
Expand All @@ -18,7 +20,6 @@ import (
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"

wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
config "github.com/White-Whale-Defi-Platform/migaloo-chain/v4/app/params"
dbm "github.com/cometbft/cometbft-db"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cometbft/cometbft/libs/log"
Expand Down Expand Up @@ -108,10 +109,10 @@ func SetupApp(t *testing.T) *MigalooApp {
acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0)
balance := banktypes.Balance{
Address: acc.GetAddress().String(),
Coins: sdk.NewCoins(sdk.NewCoin(config.BaseDenom, sdk.NewInt(100000000000000))),
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))),
}

app := SetupWithGenesisValSet(t, valSet, []authtypes.GenesisAccount{acc}, balance)
app := SetupWithGenesisValSet(t, valSet, []authtypes.GenesisAccount{acc}, "", nil, balance)

return app
}
Expand All @@ -120,29 +121,36 @@ func SetupApp(t *testing.T) *MigalooApp {
// that also act as delegators. For simplicity, each validator is bonded with a delegation
// of one consensus engine unit in the default token of the app from first genesis
// account. A Nop logger is set in app.
func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) *MigalooApp {
func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, chainID string, opts []wasmkeeper.Option, balances ...banktypes.Balance) *MigalooApp {
t.Helper()

migalooApp, genesisState := setup(true)
migalooApp, genesisState := setup(true, chainID, opts...)
genesisState = genesisStateWithValSet(t, migalooApp, genesisState, valSet, genAccs, balances...)

consensusParams := simtestutil.DefaultConsensusParams
consensusParams.Block.MaxGas = 100 * simtestutil.DefaultGenTxGas

stateBytes, err := json.MarshalIndent(genesisState, "", " ")
require.NoError(t, err)

if chainID == "" {
chainID = SimAppChainID
}

// init chain will set the validator set and initialize the genesis accounts
migalooApp.InitChain(
abci.RequestInitChain{
ChainId: SimAppChainID,
ChainId: chainID,
Validators: []abci.ValidatorUpdate{},
ConsensusParams: DefaultConsensusParams,
ConsensusParams: consensusParams,
AppStateBytes: stateBytes,
},
)

// commit genesis changes
migalooApp.Commit()
migalooApp.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{
ChainID: SimAppChainID,
ChainID: chainID,
Height: migalooApp.LastBlockHeight() + 1,
AppHash: migalooApp.LastCommitID().Hash,
ValidatorsHash: valSet.Hash(),
Expand All @@ -152,10 +160,10 @@ func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs
return migalooApp
}

func setup(withGenesis bool, opts ...wasmkeeper.Option) (*MigalooApp, GenesisState) {
func setup(withGenesis bool, chainID string, opts ...wasmkeeper.Option) (*MigalooApp, GenesisState) {
db := dbm.NewMemDB()
migalooApp := NewMigalooApp(log.NewNopLogger(), db, nil, true, map[int64]bool{},
DefaultNodeHome, 5, MakeEncodingConfig(), EmptyBaseAppOptions{}, opts)
DefaultNodeHome, 5, MakeEncodingConfig(), EmptyBaseAppOptions{}, opts, baseapp.SetChainID(chainID))

if withGenesis {
return migalooApp, NewDefaultGenesisState()
Expand Down Expand Up @@ -206,31 +214,36 @@ func genesisStateWithValSet(t *testing.T,
defaultStParams.MaxValidators,
defaultStParams.MaxEntries,
defaultStParams.HistoricalEntries,
config.BaseDenom,
sdk.DefaultBondDenom,
defaultStParams.MinCommissionRate,
)

// set validators and delegations
stakingGenesis := stakingtypes.NewGenesisState(stParams, validators, delegations)
genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis)

totalSupply := sdk.NewCoins()
for _, b := range balances {
// add genesis acc tokens to total supply
totalSupply = totalSupply.Add(b.Coins...)
}

for range delegations {
// add delegated tokens to total supply
totalSupply = totalSupply.Add(sdk.NewCoin(config.BaseDenom, bondAmt))
signingInfos := make([]slashingtypes.SigningInfo, len(valSet.Validators))
for i, val := range valSet.Validators {
signingInfos[i] = slashingtypes.SigningInfo{
Address: sdk.ConsAddress(val.Address).String(),
ValidatorSigningInfo: slashingtypes.ValidatorSigningInfo{},
}
}
slashingGenesis := slashingtypes.NewGenesisState(slashingtypes.DefaultParams(), signingInfos, nil)
genesisState[slashingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(slashingGenesis)

// add bonded amount to bonded pool module account
balances = append(balances, banktypes.Balance{
Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(),
Coins: sdk.Coins{sdk.NewCoin(config.BaseDenom, bondAmt)},
Coins: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, bondAmt.MulRaw(int64(len(valSet.Validators))))},
})

totalSupply := sdk.NewCoins()
for _, b := range balances {
// add genesis acc tokens to total supply
totalSupply = totalSupply.Add(b.Coins...)
}

// update total supply
bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{},
banktypes.DefaultGenesisState().SendEnabled)
Expand Down Expand Up @@ -386,13 +399,13 @@ func (s *KeeperTestHelper) AllocateRewardsToValidator(valAddr sdk.ValAddress, re
s.Require().True(found)

// allocate reward tokens to distribution module
coins := sdk.Coins{sdk.NewCoin(config.BaseDenom, rewardAmt)}
coins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, rewardAmt)}
err := banktestutil.FundModuleAccount(s.App.BankKeeper, s.Ctx, distrtypes.ModuleName, coins)
s.Require().NoError(err)

// allocate rewards to validator
s.Ctx = s.Ctx.WithBlockHeight(s.Ctx.BlockHeight() + 1)
decTokens := sdk.DecCoins{{Denom: config.BaseDenom, Amount: sdk.NewDec(20000)}}
decTokens := sdk.DecCoins{{Denom: sdk.DefaultBondDenom, Amount: sdk.NewDec(20000)}}
s.App.DistrKeeper.AllocateTokensToValidator(s.Ctx, validator, decTokens)
}

Expand Down
41 changes: 41 additions & 0 deletions app/test_support.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package app

import (
ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper"

"github.com/cosmos/cosmos-sdk/baseapp"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"

wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
)

func (app *MigalooApp) GetIBCKeeper() *ibckeeper.Keeper {
return app.IBCKeeper
}

func (app *MigalooApp) GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper {
return app.ScopedIBCKeeper
}

func (app *MigalooApp) GetBaseApp() *baseapp.BaseApp {
return app.BaseApp
}

func (app *MigalooApp) GetBankKeeper() bankkeeper.Keeper {
return app.BankKeeper
}

func (app *MigalooApp) GetStakingKeeper() *stakingkeeper.Keeper {
return app.StakingKeeper
}

func (app *MigalooApp) GetAccountKeeper() authkeeper.AccountKeeper {
return app.AccountKeeper
}

func (app *MigalooApp) GetWasmKeeper() wasmkeeper.Keeper {
return app.WasmKeeper
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ require (

require (
cosmossdk.io/errors v1.0.1
github.com/CosmWasm/wasmvm v1.5.2
github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3
github.com/cosmos/ibc-apps/modules/async-icq/v7 v7.1.1
github.com/golang/protobuf v1.5.4
Expand All @@ -68,7 +69,6 @@ require (
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/99designs/keyring v1.2.2 // indirect
github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect
github.com/CosmWasm/wasmvm v1.5.2 // indirect
github.com/DataDog/zstd v1.5.2 // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/aws/aws-sdk-go v1.44.203 // indirect
Expand Down
139 changes: 139 additions & 0 deletions tests/e2e/gov_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package e2e_test

import (
"testing"
"time"

"github.com/White-Whale-Defi-Platform/migaloo-chain/v4/tests/e2e"

wasmvmtypes "github.com/CosmWasm/wasmvm/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
sdk "github.com/cosmos/cosmos-sdk/types"
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"

"github.com/CosmWasm/wasmd/x/wasm/ibctesting"
"github.com/White-Whale-Defi-Platform/migaloo-chain/v4/app"
)

func TestGovVoteByContract(t *testing.T) {
// Given a contract with delegation
// And a gov proposal
// When the contract sends a vote for the proposal
// Then the vote is taken into account

coord := ibctesting.NewCoordinatorX(t, 1, e2e.DefaultMigalooAppFactory)
chain := coord.GetChain(ibctesting.GetChainID(1))
contractAddr := e2e.InstantiateReflectContract(t, chain)
chain.Fund(contractAddr, sdk.NewIntFromUint64(1_000_000_000))
// a contract with a high delegation amount
delegateMsg := wasmvmtypes.CosmosMsg{
Staking: &wasmvmtypes.StakingMsg{
Delegate: &wasmvmtypes.DelegateMsg{
Validator: sdk.ValAddress(chain.Vals.Validators[0].Address).String(),
Amount: wasmvmtypes.Coin{
Denom: sdk.DefaultBondDenom,
Amount: "1000000000",
},
},
},
}
e2e.MustExecViaReflectContract(t, chain, contractAddr, delegateMsg)

signer := chain.SenderAccount.GetAddress().String()
app := chain.App.(*app.MigalooApp)
govKeeper, accountKeeper := app.GovKeeper, app.AccountKeeper
communityPoolBalance := chain.Balance(accountKeeper.GetModuleAccount(chain.GetContext(), distributiontypes.ModuleName).GetAddress(), sdk.DefaultBondDenom)
require.False(t, communityPoolBalance.IsZero())

initialDeposit := govKeeper.GetParams(chain.GetContext()).MinDeposit
govAcctAddr := govKeeper.GetGovernanceAccount(chain.GetContext()).GetAddress()

specs := map[string]struct {
vote *wasmvmtypes.VoteMsg
expPass bool
}{
"yes": {
vote: &wasmvmtypes.VoteMsg{
Vote: wasmvmtypes.Yes,
},
expPass: true,
},
"no": {
vote: &wasmvmtypes.VoteMsg{
Vote: wasmvmtypes.No,
},
expPass: false,
},
"abstain": {
vote: &wasmvmtypes.VoteMsg{
Vote: wasmvmtypes.Abstain,
},
expPass: true,
},
"no with veto": {
vote: &wasmvmtypes.VoteMsg{
Vote: wasmvmtypes.NoWithVeto,
},
expPass: false,
},
}
for name, spec := range specs {
t.Run(name, func(t *testing.T) {
// given a unique recipient
recipientAddr := sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address().Bytes())
// and a new proposal
payloadMsg := &distributiontypes.MsgCommunityPoolSpend{
Authority: govAcctAddr.String(),
Recipient: recipientAddr.String(),
Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt())),
}
msg, err := v1.NewMsgSubmitProposal(
[]sdk.Msg{payloadMsg},
initialDeposit,
signer,
"",
"my proposal",
"testing",
)
require.NoError(t, err)
rsp, gotErr := chain.SendMsgs(msg)
require.NoError(t, gotErr)
require.Len(t, rsp.MsgResponses, 1)
got, ok := rsp.MsgResponses[0].GetCachedValue().(*v1.MsgSubmitProposalResponse)
require.True(t, ok)
propID := got.ProposalId

// with other delegators voted yes
_, err = chain.SendMsgs(v1.NewMsgVote(chain.SenderAccount.GetAddress(), propID, v1.VoteOption_VOTE_OPTION_YES, ""))
require.NoError(t, err)

// when contract votes
spec.vote.ProposalId = propID
voteMsg := wasmvmtypes.CosmosMsg{
Gov: &wasmvmtypes.GovMsg{
Vote: spec.vote,
},
}
e2e.MustExecViaReflectContract(t, chain, contractAddr, voteMsg)

// then proposal executed after voting period
proposal, ok := govKeeper.GetProposal(chain.GetContext(), propID)
require.True(t, ok)
coord.IncrementTimeBy(proposal.VotingEndTime.Sub(chain.GetContext().BlockTime()) + time.Minute)
coord.CommitBlock(chain)

// and recipient balance updated
recipientBalance := chain.Balance(recipientAddr, sdk.DefaultBondDenom)
if !spec.expPass {
assert.True(t, recipientBalance.IsZero())
return
}
expBalanceAmount := sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt())
assert.Equal(t, expBalanceAmount.String(), recipientBalance.String())
})
}
}
Loading
Loading