mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-26 16:25:21 +00:00
c511c56560
* ibc v3 upgrade * ibc no longer uses confio * add proofs proto for ibc/v3 * wip add ethermint module * update cosmos to 0.45.0 * add ethermint proto & bug fixes * remove todo * update docs * fix a number of bugs * minor comments update * fix breaking tests * Wrap bank keeper for EVM to convert decimals (#1154) * Add bankkeeper wrapper for evm * Remove agas from init-new-chain.sh, use ukava for evm_denom * Fix sdk.Coins conversion, require min 1 coin amount * Remove gas from init script idk how this happened lol * Remove debug logging stmt * Restore original init ukava amounts * Fix inplace coins conversion * Use evmtypes.BankKeeper interface insteadof banktypes * Add TestGetBalance * Add doc comments, remove temp actualAmt vars actualAmt vars replaced with inline calls to make it more clear that the converted value is being used, as opposed to accidentally reusing the raw EVM amt. * Add TestSetBalance * Add TestIdempotentConversion * Panic if converted coin from EVM is 0 This happens if a value is less than 1ukava * Deep copy coins instead of in place modification * Update test coins amount * Add panic tests for small EVM amounts * Use evmtypes.BankKeeper as NewEVMBankKeeper param * Tidy test setup * ensure sdk config is set when creating new apps * Respond EVM bank keeper GetBalance with SpendableCoins Co-authored-by: Nick DeLuca <nickdeluca08@gmail.com> * further speed up docker builds * feat: restore previous keys add defaults, add eth flag (#1172) * feat: restore previous keys add defaults, add eth flag * remove outdated comment * fix: remove redundant flag default * evm bank keeper with akava handling * fix issues * add remaining tests * add emv module to app * add missing imports * clean up comments * wip akava keeper * evm keeper * fix genesis import * reduce module permissions * add bank keeper tests * cleanup tests * genesis tests * change defaults * add eth faucet key & fix issues * switch to kava ethermint * add a lot of tests * add balances invariant * add evm tests * Remove panic if Swagger disabled in config (#1155) (#1183) Co-authored-by: Derrick Lee <derrick@dlee.dev> * add invariant to catch any akava balance > 1 ukava * clarify name of balances invariant * connect invariants to app * fix evmbankkeeper akava issues * add spec for evmutil * remove zero balance accounts from state * minor adustments * update to ethermint 0.10.0 * fix eth ante * add missing godoc comment * Update x/evmutil/spec/01_concepts.md Co-authored-by: Kevin Davis <karzak@users.noreply.github.com> * Update x/evmutil/spec/01_concepts.md Co-authored-by: Kevin Davis <karzak@users.noreply.github.com> * Update ethermint to v0.12 (#1203) * update to ethermint v0.12.2 * use app.Options for new evm options * fix missed references to app.Options * use ethermint branch while waiting on upstream fix * evm migrations for tesnet alpha 2 (#1206) * update to ethermint v0.12.2 * use app.Options for new evm options * fix missed references to app.Options * use ethermint branch while waiting on upstream fix * add upgrade handler for evm-alpha testnet 2 * v17 migration setup + evm modules * refactor migrate states * x/feemarket migration * v17 migrations setup + evm modules migration (#1210) * v17 migration setup + evm modules * refactor migrate states * update gen time * fix: update genesis time in test output Co-authored-by: karzak <kjydavis3@gmail.com> * add savings module to app blockers Co-authored-by: Derrick Lee <derrick@dlee.dev> Co-authored-by: Nick DeLuca <nickdeluca08@gmail.com> Co-authored-by: rhuairahrighairigh <ruaridh.odonnell@gmail.com> Co-authored-by: Kevin Davis <karzak@users.noreply.github.com> Co-authored-by: Ruaridh <rhuairahrighairidh@users.noreply.github.com> Co-authored-by: karzak <kjydavis3@gmail.com>
294 lines
12 KiB
Go
294 lines
12 KiB
Go
package testutil
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"time"
|
|
|
|
"github.com/kava-labs/kava/app"
|
|
"github.com/kava-labs/kava/x/swap/keeper"
|
|
"github.com/kava-labs/kava/x/swap/types"
|
|
|
|
"github.com/cosmos/cosmos-sdk/simapp"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
|
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
|
|
BankKeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
|
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
|
"github.com/stretchr/testify/suite"
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
|
tmtime "github.com/tendermint/tendermint/types/time"
|
|
ethermint "github.com/tharsis/ethermint/types"
|
|
)
|
|
|
|
var defaultSwapFee = sdk.MustNewDecFromStr("0.003")
|
|
|
|
// Suite implements a test suite for the swap module integration tests
|
|
type Suite struct {
|
|
suite.Suite
|
|
Keeper keeper.Keeper
|
|
App app.TestApp
|
|
Ctx sdk.Context
|
|
BankKeeper BankKeeper.Keeper
|
|
AccountKeeper authkeeper.AccountKeeper
|
|
}
|
|
|
|
// SetupTest instantiates a new app, keepers, and sets suite state
|
|
func (suite *Suite) SetupTest() {
|
|
tApp := app.NewTestApp()
|
|
ctx := tApp.NewContext(true, tmproto.Header{Height: 1, Time: tmtime.Now()})
|
|
|
|
suite.Ctx = ctx
|
|
suite.App = tApp
|
|
suite.Keeper = tApp.GetSwapKeeper()
|
|
suite.BankKeeper = tApp.GetBankKeeper()
|
|
suite.AccountKeeper = tApp.GetAccountKeeper()
|
|
}
|
|
|
|
// GetEvents returns emitted events on the sdk context
|
|
func (suite *Suite) GetEvents() sdk.Events {
|
|
return suite.Ctx.EventManager().Events()
|
|
}
|
|
|
|
// AddCoinsToModule adds coins to the swap module account
|
|
func (suite *Suite) AddCoinsToModule(amount sdk.Coins) {
|
|
// Does not use suite.BankKeeper.MintCoins as module account would not have permission to mint
|
|
err := simapp.FundModuleAccount(suite.BankKeeper, suite.Ctx, types.ModuleName, amount)
|
|
suite.Require().NoError(err)
|
|
}
|
|
|
|
// RemoveCoinsFromModule removes coins to the swap module account
|
|
func (suite *Suite) RemoveCoinsFromModule(amount sdk.Coins) {
|
|
// Swap module does not have BurnCoins permission so we need to transfer to gov first to burn
|
|
err := suite.BankKeeper.SendCoinsFromModuleToModule(suite.Ctx, types.ModuleAccountName, govtypes.ModuleName, amount)
|
|
suite.Require().NoError(err)
|
|
err = suite.BankKeeper.BurnCoins(suite.Ctx, govtypes.ModuleName, amount)
|
|
suite.Require().NoError(err)
|
|
}
|
|
|
|
// // GetAccount gets an existing account
|
|
// func (suite *Suite) GetAccount(addr sdk.AccAddress) authexported.Account {
|
|
// ak := suite.App.GetAccountKeeper()
|
|
// return ak.GetAccount(suite.Ctx, addr)
|
|
// }
|
|
|
|
// CreateAccount creates a new account from the provided balance
|
|
func (suite *Suite) CreateAccount(initialBalance sdk.Coins) authtypes.AccountI {
|
|
_, addrs := app.GeneratePrivKeyAddressPairs(1)
|
|
ak := suite.App.GetAccountKeeper()
|
|
|
|
acc := ak.NewAccountWithAddress(suite.Ctx, addrs[0])
|
|
ak.SetAccount(suite.Ctx, acc)
|
|
|
|
err := simapp.FundAccount(suite.BankKeeper, suite.Ctx, acc.GetAddress(), initialBalance)
|
|
suite.Require().NoError(err)
|
|
|
|
return acc
|
|
}
|
|
|
|
// NewAccountFromAddr creates a new account from the provided address with the provided balance
|
|
func (suite *Suite) NewAccountFromAddr(addr sdk.AccAddress, balance sdk.Coins) authtypes.AccountI {
|
|
ak := suite.App.GetAccountKeeper()
|
|
|
|
acc := ak.NewAccountWithAddress(suite.Ctx, addr)
|
|
ak.SetAccount(suite.Ctx, acc)
|
|
|
|
err := simapp.FundAccount(suite.BankKeeper, suite.Ctx, acc.GetAddress(), balance)
|
|
suite.Require().NoError(err)
|
|
|
|
return acc
|
|
}
|
|
|
|
// CreateVestingAccount creates a new vesting account from the provided balance and vesting balance
|
|
func (suite *Suite) CreateVestingAccount(initialBalance sdk.Coins, vestingBalance sdk.Coins) authtypes.AccountI {
|
|
acc := suite.CreateAccount(initialBalance)
|
|
bacc := acc.(*ethermint.EthAccount)
|
|
|
|
periods := vestingtypes.Periods{
|
|
vestingtypes.Period{
|
|
Length: 31556952,
|
|
Amount: vestingBalance,
|
|
},
|
|
}
|
|
vacc := vestingtypes.NewPeriodicVestingAccount(bacc.BaseAccount, initialBalance, time.Now().Unix(), periods) // TODO is initialBalance correct for originalVesting?
|
|
|
|
return vacc
|
|
}
|
|
|
|
// CreatePool creates a pool and stores it in state with the provided reserves
|
|
func (suite *Suite) CreatePool(reserves sdk.Coins) error {
|
|
depositor := suite.CreateAccount(reserves)
|
|
pool := types.NewAllowedPool(reserves[0].Denom, reserves[1].Denom)
|
|
suite.Require().NoError(pool.Validate())
|
|
suite.Keeper.SetParams(suite.Ctx, types.NewParams(types.AllowedPools{pool}, defaultSwapFee))
|
|
|
|
return suite.Keeper.Deposit(suite.Ctx, depositor.GetAddress(), reserves[0], reserves[1], sdk.MustNewDecFromStr("1"))
|
|
}
|
|
|
|
// AccountBalanceEqual asserts that the coins match the account balance
|
|
func (suite *Suite) AccountBalanceEqual(addr sdk.AccAddress, coins sdk.Coins) {
|
|
balance := suite.BankKeeper.GetAllBalances(suite.Ctx, addr)
|
|
suite.Equal(coins, balance, fmt.Sprintf("expected account balance to equal coins %s, but got %s", coins, balance))
|
|
}
|
|
|
|
// // AccountBalanceDelta asserts that the coins are within delta of the account balance
|
|
// func (suite *Suite) AccountBalanceDelta(acc authexported.Account, coins sdk.Coins, delta float64) {
|
|
// ak := suite.App.GetAccountKeeper()
|
|
// acc = ak.GetAccount(suite.Ctx, acc.GetAddress())
|
|
// accCoins := acc.GetCoins()
|
|
// allCoins := coins.Add(accCoins...)
|
|
// for _, coin := range allCoins {
|
|
// suite.InDelta(
|
|
// coins.AmountOf(coin.Denom).Int64(),
|
|
// accCoins.AmountOf(coin.Denom).Int64(),
|
|
// delta,
|
|
// fmt.Sprintf("expected module account balance to be in delta %f of coins %s, but got %s", delta, coins, accCoins),
|
|
// )
|
|
// }
|
|
// }
|
|
|
|
// ModuleAccountBalanceEqual asserts that the swap module account balance matches the provided coins
|
|
func (suite *Suite) ModuleAccountBalanceEqual(coins sdk.Coins) {
|
|
balance := suite.BankKeeper.GetAllBalances(
|
|
suite.Ctx,
|
|
suite.AccountKeeper.GetModuleAddress(types.ModuleAccountName),
|
|
)
|
|
suite.Equal(coins, balance, fmt.Sprintf("expected module account balance to equal coins %s, but got %s", coins, balance))
|
|
}
|
|
|
|
// // ModuleAccountBalanceDelta asserts that the swap module account balance is within acceptable delta of the provided coins
|
|
// func (suite *Suite) ModuleAccountBalanceDelta(coins sdk.Coins, delta float64) {
|
|
// macc, _ := suite.supplyKeeper.GetModuleAccountAndPermissions(suite.Ctx, types.ModuleName)
|
|
// suite.Require().NotNil(macc, "expected module account to be defined")
|
|
|
|
// allCoins := coins.Add(macc.GetCoins()...)
|
|
// for _, coin := range allCoins {
|
|
// suite.InDelta(
|
|
// coins.AmountOf(coin.Denom).Int64(),
|
|
// macc.GetCoins().AmountOf(coin.Denom).Int64(),
|
|
// delta,
|
|
// fmt.Sprintf("expected module account balance to be in delta %f of coins %s, but got %s", delta, coins, macc.GetCoins()),
|
|
// )
|
|
// }
|
|
// }
|
|
|
|
// PoolLiquidityEqual asserts that the pool matching the provided coins has those reserves
|
|
func (suite *Suite) PoolLiquidityEqual(coins sdk.Coins) {
|
|
poolRecord, ok := suite.Keeper.GetPool(suite.Ctx, types.PoolIDFromCoins(coins))
|
|
suite.Require().True(ok, "expected pool to exist")
|
|
reserves := sdk.NewCoins(poolRecord.ReservesA, poolRecord.ReservesB)
|
|
suite.Equal(coins, reserves, fmt.Sprintf("expected pool reserves of %s, got %s", coins, reserves))
|
|
}
|
|
|
|
// PoolDeleted asserts that the pool does not exist
|
|
func (suite *Suite) PoolDeleted(denomA, denomB string) {
|
|
_, ok := suite.Keeper.GetPool(suite.Ctx, types.PoolID(denomA, denomB))
|
|
suite.Require().False(ok, "expected pool to not exist")
|
|
}
|
|
|
|
// // PoolLiquidityDelta asserts that the pool matching the provided coins has those reserves within delta
|
|
// func (suite *Suite) PoolLiquidityDelta(coins sdk.Coins, delta float64) {
|
|
// poolRecord, ok := suite.Keeper.GetPool(suite.Ctx, types.PoolIDFromCoins(coins))
|
|
// suite.Require().True(ok, "expected pool to exist")
|
|
|
|
// suite.InDelta(
|
|
// poolRecord.ReservesA.Amount.Int64(),
|
|
// coins.AmountOf(poolRecord.ReservesA.Denom).Int64(),
|
|
// delta,
|
|
// fmt.Sprintf("expected pool reserves within delta %f of %s, got %s", delta, coins, poolRecord.Reserves()),
|
|
// )
|
|
// suite.InDelta(
|
|
// poolRecord.ReservesB.Amount.Int64(),
|
|
// coins.AmountOf(poolRecord.ReservesB.Denom).Int64(),
|
|
// delta,
|
|
// fmt.Sprintf("expected pool reserves within delta %f of %s, got %s", delta, coins, poolRecord.Reserves()),
|
|
// )
|
|
// }
|
|
|
|
// PoolShareTotalEqual asserts the total shares match the stored pool
|
|
func (suite *Suite) PoolShareTotalEqual(poolID string, totalShares sdk.Int) {
|
|
poolRecord, found := suite.Keeper.GetPool(suite.Ctx, poolID)
|
|
suite.Require().True(found, fmt.Sprintf("expected pool %s to exist", poolID))
|
|
suite.Equal(totalShares, poolRecord.TotalShares, "expected pool total shares to be equal")
|
|
}
|
|
|
|
// PoolDepositorSharesEqual asserts the depositor owns the shares for the provided pool
|
|
func (suite *Suite) PoolDepositorSharesEqual(depositor sdk.AccAddress, poolID string, shares sdk.Int) {
|
|
shareRecord, found := suite.Keeper.GetDepositorShares(suite.Ctx, depositor, poolID)
|
|
suite.Require().True(found, fmt.Sprintf("expected share record to exist for depositor %s and pool %s", depositor.String(), poolID))
|
|
suite.Equal(shares, shareRecord.SharesOwned)
|
|
}
|
|
|
|
// PoolReservesEqual assets the stored pool reserves are equal to the provided reserves
|
|
func (suite *Suite) PoolReservesEqual(poolID string, reserves sdk.Coins) {
|
|
poolRecord, found := suite.Keeper.GetPool(suite.Ctx, poolID)
|
|
suite.Require().True(found, fmt.Sprintf("expected pool %s to exist", poolID))
|
|
suite.Equal(reserves, poolRecord.Reserves(), "expected pool reserves to be equal")
|
|
}
|
|
|
|
// PoolShareValueEqual asserts that the depositor shares are in state and the value matches the expected coins
|
|
func (suite *Suite) PoolShareValueEqual(depositor authtypes.AccountI, pool types.AllowedPool, coins sdk.Coins) {
|
|
poolRecord, ok := suite.Keeper.GetPool(suite.Ctx, pool.Name())
|
|
suite.Require().True(ok, fmt.Sprintf("expected pool %s to exist", pool.Name()))
|
|
shares, ok := suite.Keeper.GetDepositorShares(suite.Ctx, depositor.GetAddress(), poolRecord.PoolID)
|
|
suite.Require().True(ok, fmt.Sprintf("expected shares to exist for depositor %s", depositor.GetAddress()))
|
|
|
|
storedPool, err := types.NewDenominatedPoolWithExistingShares(sdk.NewCoins(poolRecord.ReservesA, poolRecord.ReservesB), poolRecord.TotalShares)
|
|
suite.Nil(err)
|
|
value := storedPool.ShareValue(shares.SharesOwned)
|
|
suite.Equal(coins, value, fmt.Sprintf("expected shares to equal %s, but got %s", coins, value))
|
|
}
|
|
|
|
// // PoolShareValueDelta asserts that the depositor shares are in state and the value is within delta of the expected coins
|
|
// func (suite *Suite) PoolShareValueDelta(depositor authexported.Account, pool types.AllowedPool, coins sdk.Coins, delta float64) {
|
|
// poolRecord, ok := suite.Keeper.GetPool(suite.Ctx, pool.Name())
|
|
// suite.Require().True(ok, fmt.Sprintf("expected pool %s to exist", pool.Name()))
|
|
// shares, ok := suite.Keeper.GetDepositorShares(suite.Ctx, depositor.GetAddress(), poolRecord.PoolID)
|
|
// suite.Require().True(ok, fmt.Sprintf("expected shares to exist for depositor %s", depositor.GetAddress()))
|
|
|
|
// storedPool, err := types.NewDenominatedPoolWithExistingShares(sdk.NewCoins(poolRecord.ReservesA, poolRecord.ReservesB), poolRecord.TotalShares)
|
|
// suite.Nil(err)
|
|
// value := storedPool.ShareValue(shares.SharesOwned)
|
|
|
|
// for _, coin := range coins {
|
|
// suite.InDelta(
|
|
// coin.Amount.Int64(),
|
|
// value.AmountOf(coin.Denom).Int64(),
|
|
// delta,
|
|
// fmt.Sprintf("expected shares to be within delta %f of %s, but got %s", delta, coins, value),
|
|
// )
|
|
// }
|
|
// }
|
|
|
|
// PoolSharesDeleted asserts that the pool shares have been removed
|
|
func (suite *Suite) PoolSharesDeleted(depositor sdk.AccAddress, denomA, denomB string) {
|
|
_, ok := suite.Keeper.GetDepositorShares(suite.Ctx, depositor, types.PoolID(denomA, denomB))
|
|
suite.Require().False(ok, "expected pool shares to not exist")
|
|
}
|
|
|
|
// EventsContains asserts that the expected event is in the provided events
|
|
func (suite *Suite) EventsContains(events sdk.Events, expectedEvent sdk.Event) {
|
|
foundMatch := false
|
|
for _, event := range events {
|
|
if event.Type == expectedEvent.Type {
|
|
if reflect.DeepEqual(attrsToMap(expectedEvent.Attributes), attrsToMap(event.Attributes)) {
|
|
foundMatch = true
|
|
}
|
|
}
|
|
}
|
|
|
|
suite.True(foundMatch, fmt.Sprintf("event of type %s not found or did not match", expectedEvent.Type))
|
|
}
|
|
|
|
func attrsToMap(attrs []abci.EventAttribute) []sdk.Attribute { // new cosmos changed the event attribute type
|
|
out := []sdk.Attribute{}
|
|
|
|
for _, attr := range attrs {
|
|
out = append(out, sdk.NewAttribute(string(attr.Key), string(attr.Value)))
|
|
}
|
|
|
|
return out
|
|
}
|