Skip to content

Commit

Permalink
feat: add tokenfactory in wasm v0.45.0
Browse files Browse the repository at this point in the history
  • Loading branch information
hoank101 committed Dec 27, 2023
1 parent 7165e41 commit 3f85475
Show file tree
Hide file tree
Showing 70 changed files with 11,803 additions and 78 deletions.
21 changes: 20 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ import (
"github.com/CosmWasm/wasmd/x/wasm"
wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"

// token factory
"github.com/CosmWasm/wasmd/x/tokenfactory"
tokenfactorykeeper "github.com/CosmWasm/wasmd/x/tokenfactory/keeper"
tokenfactorytypes "github.com/CosmWasm/wasmd/x/tokenfactory/types"
)

const appName = "WasmApp"
Expand Down Expand Up @@ -257,6 +262,7 @@ type WasmApp struct {
ICAHostKeeper icahostkeeper.Keeper
TransferKeeper ibctransferkeeper.Keeper
WasmKeeper wasmkeeper.Keeper
TokenFactoryKeeper tokenfactorykeeper.Keeper

ScopedIBCKeeper capabilitykeeper.ScopedKeeper
ScopedICAHostKeeper capabilitykeeper.ScopedKeeper
Expand Down Expand Up @@ -307,6 +313,7 @@ func NewWasmApp(
ibcexported.StoreKey, ibctransfertypes.StoreKey, ibcfeetypes.StoreKey,
wasmtypes.StoreKey, icahosttypes.StoreKey,
icacontrollertypes.StoreKey,
tokenfactorytypes.StoreKey,
)

tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey)
Expand Down Expand Up @@ -405,6 +412,14 @@ func NewWasmApp(
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)

app.TokenFactoryKeeper = tokenfactorykeeper.NewKeeper(
keys[tokenfactorytypes.StoreKey],
app.GetSubspace(tokenfactorytypes.ModuleName),
app.AccountKeeper,
app.BankKeeper,
app.DistrKeeper,
)

invCheckPeriod := cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod))
app.CrisisKeeper = crisiskeeper.NewKeeper(
appCodec,
Expand Down Expand Up @@ -653,6 +668,7 @@ func NewWasmApp(
transfer.NewAppModule(app.TransferKeeper),
ibcfee.NewAppModule(app.IBCFeeKeeper),
ica.NewAppModule(&app.ICAControllerKeeper, &app.ICAHostKeeper),
tokenfactory.NewAppModule(app.TokenFactoryKeeper, app.AccountKeeper, app.BankKeeper),
crisis.NewAppModule(app.CrisisKeeper, skipGenesisInvariants, app.GetSubspace(crisistypes.ModuleName)), // always be last to make sure that it checks for all invariants and not only part of them
)

Expand All @@ -673,6 +689,7 @@ func NewWasmApp(
icatypes.ModuleName,
ibcfeetypes.ModuleName,
wasmtypes.ModuleName,
tokenfactorytypes.ModuleName,
)

app.ModuleManager.SetOrderEndBlockers(
Expand All @@ -688,6 +705,7 @@ func NewWasmApp(
icatypes.ModuleName,
ibcfeetypes.ModuleName,
wasmtypes.ModuleName,
tokenfactorytypes.ModuleName,
)

// NOTE: The genutils module must occur after staking so that pools are
Expand All @@ -711,6 +729,7 @@ func NewWasmApp(
ibcfeetypes.ModuleName,
// wasm after ibc transfer
wasmtypes.ModuleName,
tokenfactorytypes.ModuleName,
}
app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...)
app.ModuleManager.SetOrderExportGenesis(genesisModuleOrder...)
Expand Down Expand Up @@ -1026,6 +1045,6 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino
paramsKeeper.Subspace(icahosttypes.SubModuleName)
paramsKeeper.Subspace(icacontrollertypes.SubModuleName)
paramsKeeper.Subspace(wasmtypes.ModuleName)

paramsKeeper.Subspace(tokenfactorytypes.ModuleName)
return paramsKeeper
}
17 changes: 17 additions & 0 deletions app/apptesting/events.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package apptesting

import sdk "github.com/cosmos/cosmos-sdk/types"

// AssertEventEmitted asserts that ctx's event manager has emitted the given number of events
// of the given type.
func (s *KeeperTestHelper) AssertEventEmitted(ctx sdk.Context, eventTypeExpected string, numEventsExpected int) {
allEvents := ctx.EventManager().Events()
// filter out other events
actualEvents := make([]sdk.Event, 0)
for _, event := range allEvents {
if event.Type == eventTypeExpected {
actualEvents = append(actualEvents, event)
}
}
s.Equal(numEventsExpected, len(actualEvents))
}
298 changes: 298 additions & 0 deletions app/apptesting/test_suite.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
package apptesting

import (
"encoding/json"
"fmt"
"os"
"testing"
"time"

"cosmossdk.io/math"
dbm "github.com/cometbft/cometbft-db"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cometbft/cometbft/crypto/ed25519"
"github.com/cometbft/cometbft/libs/log"
tmtypes "github.com/cometbft/cometbft/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
cdctypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/store/rootmulti"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/authz"
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"

authzcodec "github.com/CosmWasm/wasmd/x/tokenfactory/types/authzcodec"

"github.com/CosmWasm/wasmd/app"
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
)

type KeeperTestHelper struct {
suite.Suite

App *app.WasmApp
Ctx sdk.Context
QueryHelper *baseapp.QueryServiceTestHelper
TestAccs []sdk.AccAddress
}

var (
SecondaryDenom = "uion"
SecondaryAmount = sdk.NewInt(100000000)
)

// Setup sets up basic environment for suite (App, Ctx, and test accounts)
func (s *KeeperTestHelper) Setup() {
s.App = app.Setup(s.T())
s.Ctx = s.App.BaseApp.NewContext(false, tmtypes.Header{Height: 1, ChainID: "osmosis-1", Time: time.Now().UTC()})
s.QueryHelper = &baseapp.QueryServiceTestHelper{
GRPCQueryRouter: s.App.GRPCQueryRouter(),
Ctx: s.Ctx,
}
s.TestAccs = CreateRandomAccounts(3)
}

func (s *KeeperTestHelper) SetupTestForInitGenesis() {
db := dbm.NewMemDB()
s.App = app.NewWasmAppWithCustomOptions(s.T(), true, app.SetupOptions{
Logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)),
DB: db,
AppOpts: simtestutil.NewAppOptionsWithFlagHome(s.T().TempDir()),
})
s.Ctx = s.App.BaseApp.NewContext(true, tmtypes.Header{})
}

// CreateTestContext creates a test context.
func (s *KeeperTestHelper) CreateTestContext() sdk.Context {
ctx, _ := s.CreateTestContextWithMultiStore()
return ctx
}

// CreateTestContextWithMultiStore creates a test context and returns it together with multi store.
func (s *KeeperTestHelper) CreateTestContextWithMultiStore() (sdk.Context, sdk.CommitMultiStore) {
db := dbm.NewMemDB()
logger := log.NewNopLogger()

ms := rootmulti.NewStore(db, logger)

return sdk.NewContext(ms, tmtypes.Header{}, false, logger), ms
}

// CreateTestContext creates a test context.
func (s *KeeperTestHelper) Commit() {
oldHeight := s.Ctx.BlockHeight()
oldHeader := s.Ctx.BlockHeader()
s.App.Commit()
newHeader := tmtypes.Header{Height: oldHeight + 1, ChainID: oldHeader.ChainID, Time: oldHeader.Time.Add(time.Second)}
s.App.BeginBlock(abci.RequestBeginBlock{Header: newHeader})
s.Ctx = s.App.NewContext(false, newHeader)
}

// FundAcc funds target address with specified amount.
func (s *KeeperTestHelper) FundAcc(acc sdk.AccAddress, amounts sdk.Coins) {
err := app.FundAccount(s.App.BankKeeper, s.Ctx, acc, amounts)
s.Require().NoError(err)
}

// FundModuleAcc funds target modules with specified amount.
func (s *KeeperTestHelper) FundModuleAcc(moduleName string, amounts sdk.Coins) {
err := app.FundModuleAccount(s.App.BankKeeper, s.Ctx, moduleName, amounts)
s.Require().NoError(err)
}

func (s *KeeperTestHelper) MintCoins(coins sdk.Coins) {
err := s.App.BankKeeper.MintCoins(s.Ctx, minttypes.ModuleName, coins)
s.Require().NoError(err)
}

// SetupValidator sets up a validator and returns the ValAddress.
func (s *KeeperTestHelper) SetupValidator(bondStatus stakingtypes.BondStatus) sdk.ValAddress {
valPub := secp256k1.GenPrivKey().PubKey()
valAddr := sdk.ValAddress(valPub.Address())
bondDenom := s.App.StakingKeeper.GetParams(s.Ctx).BondDenom
selfBond := sdk.NewCoins(sdk.Coin{Amount: sdk.DefaultPowerReduction, Denom: bondDenom})

s.FundAcc(sdk.AccAddress(valAddr), selfBond)

stakingCoin := sdk.NewCoin(sdk.DefaultBondDenom, selfBond[0].Amount)
ZeroCommission := stakingtypes.NewCommissionRates(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec())
_, err := stakingtypes.NewMsgCreateValidator(valAddr, valPub, stakingCoin, stakingtypes.Description{}, ZeroCommission, sdk.OneInt())
s.Require().NoError(err)

val, found := s.App.StakingKeeper.GetValidator(s.Ctx, valAddr)
s.Require().True(found)

val = val.UpdateStatus(bondStatus)
s.App.StakingKeeper.SetValidator(s.Ctx, val)

consAddr, err := val.GetConsAddr()
s.Suite.Require().NoError(err)

signingInfo := slashingtypes.NewValidatorSigningInfo(
consAddr,
s.Ctx.BlockHeight(),
0,
time.Unix(0, 0),
false,
0,
)
s.App.SlashingKeeper.SetValidatorSigningInfo(s.Ctx, consAddr, signingInfo)

return valAddr
}

// BeginNewBlock starts a new block.
func (s *KeeperTestHelper) BeginNewBlock() {
var valAddr []byte

validators := s.App.StakingKeeper.GetAllValidators(s.Ctx)
if len(validators) >= 1 {
valAddrFancy, err := validators[0].GetConsAddr()
s.Require().NoError(err)
valAddr = valAddrFancy.Bytes()
} else {
valAddrFancy := s.SetupValidator(stakingtypes.Bonded)
validator, _ := s.App.StakingKeeper.GetValidator(s.Ctx, valAddrFancy)
valAddr2, _ := validator.GetConsAddr()
valAddr = valAddr2.Bytes()
}

s.BeginNewBlockWithProposer(valAddr)
}

// BeginNewBlockWithProposer begins a new block with a proposer.
func (s *KeeperTestHelper) BeginNewBlockWithProposer(proposer sdk.ValAddress) {
validator, found := s.App.StakingKeeper.GetValidator(s.Ctx, proposer)
s.Assert().True(found)

valConsAddr, err := validator.GetConsAddr()
s.Require().NoError(err)

valAddr := valConsAddr.Bytes()

newBlockTime := s.Ctx.BlockTime().Add(5 * time.Second)

header := tmtypes.Header{Height: s.Ctx.BlockHeight() + 1, Time: newBlockTime}
newCtx := s.Ctx.WithBlockTime(newBlockTime).WithBlockHeight(s.Ctx.BlockHeight() + 1)
s.Ctx = newCtx
lastCommitInfo := abci.CommitInfo{
Votes: []abci.VoteInfo{{
Validator: abci.Validator{Address: valAddr, Power: 1000},
SignedLastBlock: true,
}},
}
reqBeginBlock := abci.RequestBeginBlock{Header: header, LastCommitInfo: lastCommitInfo}

fmt.Println("beginning block ", s.Ctx.BlockHeight())
s.App.BeginBlocker(s.Ctx, reqBeginBlock)
}

// EndBlock ends the block.
func (s *KeeperTestHelper) EndBlock() {
reqEndBlock := abci.RequestEndBlock{Height: s.Ctx.BlockHeight()}
s.App.EndBlocker(s.Ctx, reqEndBlock)
}

// AllocateRewardsToValidator allocates reward tokens to a distribution module then allocates rewards to the validator address.
func (s *KeeperTestHelper) AllocateRewardsToValidator(valAddr sdk.ValAddress, rewardAmt math.Int) {
validator, found := s.App.StakingKeeper.GetValidator(s.Ctx, valAddr)
s.Require().True(found)

// allocate reward tokens to distribution module
coins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, rewardAmt)}
err := app.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: sdk.DefaultBondDenom, Amount: sdk.NewDec(20000)}}
s.App.DistrKeeper.AllocateTokensToValidator(s.Ctx, validator, decTokens)
}

// BuildTx builds a transaction.
func (s *KeeperTestHelper) BuildTx(
txBuilder client.TxBuilder,
msgs []sdk.Msg,
sigV2 signing.SignatureV2,
memo string, txFee sdk.Coins,
gasLimit uint64,
) authsigning.Tx {
err := txBuilder.SetMsgs(msgs[0])
s.Require().NoError(err)

err = txBuilder.SetSignatures(sigV2)
s.Require().NoError(err)

txBuilder.SetMemo(memo)
txBuilder.SetFeeAmount(txFee)
txBuilder.SetGasLimit(gasLimit)

return txBuilder.GetTx()
}

// CreateRandomAccounts is a function return a list of randomly generated AccAddresses
func CreateRandomAccounts(numAccts int) []sdk.AccAddress {
testAddrs := make([]sdk.AccAddress, numAccts)
for i := 0; i < numAccts; i++ {
pk := ed25519.GenPrivKey().PubKey()
testAddrs[i] = sdk.AccAddress(pk.Address())
}

return testAddrs
}

func TestMessageAuthzSerialization(t *testing.T, msg sdk.Msg) {
someDate := time.Date(1, 1, 1, 1, 1, 1, 1, time.UTC)
var expire *time.Time

const (
mockGranter string = "cosmos1abc"
mockGrantee string = "cosmos1xyz"
)

var (
mockMsgGrant authz.MsgGrant
mockMsgRevoke authz.MsgRevoke
mockMsgExec authz.MsgExec
)

// Authz: Grant Msg
typeURL := sdk.MsgTypeURL(msg)
grant, err := authz.NewGrant(someDate, authz.NewGenericAuthorization(typeURL), expire)
require.NoError(t, err)

msgGrant := authz.MsgGrant{Granter: mockGranter, Grantee: mockGrantee, Grant: grant}
msgGrantBytes := json.RawMessage(sdk.MustSortJSON(authzcodec.ModuleCdc.MustMarshalJSON(&msgGrant)))
err = authzcodec.ModuleCdc.UnmarshalJSON(msgGrantBytes, &mockMsgGrant)
require.NoError(t, err)

// Authz: Revoke Msg
msgRevoke := authz.MsgRevoke{Granter: mockGranter, Grantee: mockGrantee, MsgTypeUrl: typeURL}
msgRevokeByte := json.RawMessage(sdk.MustSortJSON(authzcodec.ModuleCdc.MustMarshalJSON(&msgRevoke)))
err = authzcodec.ModuleCdc.UnmarshalJSON(msgRevokeByte, &mockMsgRevoke)
require.NoError(t, err)

// Authz: Exec Msg
msgAny, err := cdctypes.NewAnyWithValue(msg)
require.NoError(t, err)
msgExec := authz.MsgExec{Grantee: mockGrantee, Msgs: []*cdctypes.Any{msgAny}}
execMsgByte := json.RawMessage(sdk.MustSortJSON(authzcodec.ModuleCdc.MustMarshalJSON(&msgExec)))
err = authzcodec.ModuleCdc.UnmarshalJSON(execMsgByte, &mockMsgExec)
require.NoError(t, err)
require.Equal(t, msgExec.Msgs[0].Value, mockMsgExec.Msgs[0].Value)
}

func GenerateTestAddrs() (string, string) {
pk1 := ed25519.GenPrivKey().PubKey()
validAddr := sdk.AccAddress(pk1.Address()).String()
invalidAddr := sdk.AccAddress("invalid").String()
return validAddr, invalidAddr
}
Loading

0 comments on commit 3f85475

Please sign in to comment.