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: leverage e2e #2233

Merged
merged 40 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
d114dc9
file
toteki Sep 7, 2023
7dad3b9
mimic egor PR #2232
toteki Sep 8, 2023
c3e94e2
leverage execute fxns
toteki Sep 8, 2023
7952740
Merge branch 'main' into adam/e2e
toteki Sep 8, 2023
3963af5
comment
toteki Sep 11, 2023
c8c7f3e
shorten functions
toteki Sep 11, 2023
b5930de
++
toteki Sep 11, 2023
62ac6c5
const
toteki Sep 11, 2023
8c905c7
add initial balances
toteki Sep 11, 2023
2f9ec2b
leverage gov setup
toteki Sep 11, 2023
a40355f
special assets pair gov setup
toteki Sep 11, 2023
39611ce
initial leverage supply
toteki Sep 11, 2023
b2352f4
lint
toteki Sep 11, 2023
ce53a5b
fix
toteki Sep 11, 2023
9ee4642
fix exceed max supply
toteki Sep 11, 2023
105d240
++
toteki Sep 11, 2023
e3a47ab
Merge branch 'main' into adam/e2e
toteki Sep 11, 2023
c0a00f9
fix
toteki Sep 11, 2023
ff21923
account tools
toteki Sep 12, 2023
9b0ae46
Merge branch 'main' into adam/e2e
toteki Sep 12, 2023
0593f53
++
toteki Sep 12, 2023
706ac62
revert accunt tools
toteki Sep 12, 2023
9a52706
revert extra balances
toteki Sep 12, 2023
8b5f451
--
toteki Sep 12, 2023
a1bc63d
--
toteki Sep 12, 2023
a2b403f
--
toteki Sep 12, 2023
d966fa7
fix
toteki Sep 12, 2023
14ab0d6
do not require historic medians for leverage e2e
toteki Sep 12, 2023
931343e
suggestion++
toteki Sep 12, 2023
69a853c
add special pairs to e2e
toteki Sep 12, 2023
99a478c
fix spelling of undercollateralized
toteki Sep 12, 2023
fe219f4
fix empty description
toteki Sep 12, 2023
77d5a04
modify amounts
toteki Sep 12, 2023
6560791
keeper tests with special pairs - AND A FIX
toteki Sep 12, 2023
4c1f858
rename suite functions
toteki Sep 12, 2023
06b1b95
change eventually to 5sec
toteki Sep 12, 2023
0dd4931
suggestion++
toteki Sep 12, 2023
5c3ae2d
Merge branch 'main' into adam/e2e
toteki Sep 12, 2023
87232e4
remove eventually
toteki Sep 12, 2023
59fb3cc
modify gov proposal (sets don't loop assets)
toteki Sep 12, 2023
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
140 changes: 140 additions & 0 deletions tests/e2e/e2e_leverage_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package e2e

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

appparams "github.com/umee-network/umee/v6/app/params"
"github.com/umee-network/umee/v6/tests/grpc"
"github.com/umee-network/umee/v6/x/leverage/fixtures"
leveragetypes "github.com/umee-network/umee/v6/x/leverage/types"
)

func (s *E2ETest) supply(addr sdk.AccAddress, denom string, amount uint64) {
toteki marked this conversation as resolved.
Show resolved Hide resolved
asset := sdk.NewCoin(denom, sdk.NewIntFromUint64(amount))
s.mustSucceedTx(leveragetypes.NewMsgSupply(addr, asset))
}

func (s *E2ETest) withdraw(addr sdk.AccAddress, denom string, amount uint64) {
toteki marked this conversation as resolved.
Show resolved Hide resolved
asset := sdk.NewCoin(denom, sdk.NewIntFromUint64(amount))
s.mustSucceedTx(leveragetypes.NewMsgWithdraw(addr, asset))
}

func (s *E2ETest) maxWithdraw(addr sdk.AccAddress, denom string) {
s.mustSucceedTx(leveragetypes.NewMsgMaxWithdraw(addr, denom))
}

func (s *E2ETest) collateralize(addr sdk.AccAddress, denom string, amount uint64) {
asset := sdk.NewCoin(denom, sdk.NewIntFromUint64(amount))
s.mustSucceedTx(leveragetypes.NewMsgCollateralize(addr, asset))
}

func (s *E2ETest) decollateralize(addr sdk.AccAddress, denom string, amount uint64) {
asset := sdk.NewCoin(denom, sdk.NewIntFromUint64(amount))
s.mustSucceedTx(leveragetypes.NewMsgDecollateralize(addr, asset))
}

func (s *E2ETest) supplyCollateral(addr sdk.AccAddress, denom string, amount uint64) {
asset := sdk.NewCoin(denom, sdk.NewIntFromUint64(amount))
s.mustSucceedTx(leveragetypes.NewMsgSupplyCollateral(addr, asset))
}

func (s *E2ETest) borrow(addr sdk.AccAddress, denom string, amount uint64) {
asset := sdk.NewCoin(denom, sdk.NewIntFromUint64(amount))
s.mustSucceedTx(leveragetypes.NewMsgBorrow(addr, asset))
}

func (s *E2ETest) maxBorrow(addr sdk.AccAddress, denom string) {
s.mustSucceedTx(leveragetypes.NewMsgMaxBorrow(addr, denom))
}

func (s *E2ETest) repay(addr sdk.AccAddress, denom string, amount uint64) {
asset := sdk.NewCoin(denom, sdk.NewIntFromUint64(amount))
s.mustSucceedTx(leveragetypes.NewMsgRepay(addr, asset))
}

func (s *E2ETest) liquidate(addr, target sdk.AccAddress, repayDenom string, repayAmount uint64, reward string) {
repay := sdk.NewCoin(repayDenom, sdk.NewIntFromUint64(repayAmount))
s.mustSucceedTx(leveragetypes.NewMsgLiquidate(addr, target, repay, reward))
}

func (s *E2ETest) leveragedLiquidate(addr, target sdk.AccAddress, repay, reward string) {
s.mustSucceedTx(leveragetypes.NewMsgLeveragedLiquidate(addr, target, repay, reward))
}

func (s *E2ETest) TestLeverageBasics() {
umeeNoMedians := fixtures.Token(appparams.BondDenom, "UMEE", 6)
umeeNoMedians.HistoricMedians = 0
updateTokens := []leveragetypes.Token{
umeeNoMedians,
}

s.Run(
"leverage update registry", func() {
s.Require().NoError(
grpc.LeverageRegistryUpdate(s.Umee, []leveragetypes.Token{}, updateTokens),
)
},
)

valAddr, err := s.Chain.Validators[0].KeyInfo.GetAddress()
s.Require().NoError(err)

s.Run(
"initial leverage supply", func() {
s.supply(valAddr, appparams.BondDenom, 100_000_000)
},
)
s.Run(
"initial leverage withdraw", func() {
s.withdraw(valAddr, "u/"+appparams.BondDenom, 10_000_000)
},
)
s.Run(
"initial leverage collateralize", func() {
s.collateralize(valAddr, "u/"+appparams.BondDenom, 80_000_000)
},
)
s.Run(
"initial leverage borrow", func() {
s.borrow(valAddr, appparams.BondDenom, 12_000_000)
},
)
s.Run(
"initial leverage repay", func() {
s.repay(valAddr, appparams.BondDenom, 2_000_000)
},
)
s.Run(
"too high leverage borrow", func() {
asset := sdk.NewCoin(
appparams.BondDenom,
sdk.NewIntFromUint64(30_000_000),
)
s.mustFailTx(leveragetypes.NewMsgBorrow(valAddr, asset), "undercollateralized")
},
)
s.Run(
"leverage add special pairs", func() {
sets := []leveragetypes.SpecialAssetSet{
{
// a set allowing UMEE to borrow more of itself
Assets: []string{appparams.BondDenom},
CollateralWeight: sdk.MustNewDecFromStr("0.75"),
LiquidationThreshold: sdk.MustNewDecFromStr("0.8"),
},
}
s.Require().NoError(
grpc.LeverageSpecialPairsUpdate(s.Umee, sets, []leveragetypes.SpecialAssetPair{}),
)
},
)
s.Run(
"special pair leverage borrow", func() {
asset := sdk.NewCoin(
appparams.BondDenom,
sdk.NewIntFromUint64(30_000_000),
)
s.mustEventuallySucceedTx(leveragetypes.NewMsgBorrow(valAddr, asset))
},
)
}
32 changes: 32 additions & 0 deletions tests/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (

"github.com/stretchr/testify/suite"

sdk "github.com/cosmos/cosmos-sdk/types"
toteki marked this conversation as resolved.
Show resolved Hide resolved

setup "github.com/umee-network/umee/v6/tests/e2e/setup"
"github.com/umee-network/umee/v6/tests/grpc"
)
Expand All @@ -18,6 +20,36 @@ func TestE2ETestSuite(t *testing.T) {
suite.Run(t, new(E2ETest))
}

// mustEventuallySucceedTx executes an sdk.Msg, retrying several times if receiving any error,
// and requires that the transaction eventually succeeded with nil error. Since this function
// retries for 30 seconds and ignores errors, it is suitable for scenario setup transaction or
// those which might require time elapsing before they succeed.
func (s *E2ETest) mustEventuallySucceedTx(msg sdk.Msg) {
s.Require().Eventually(
func() bool {
return s.BroadcastTxWithRetry(msg) == nil
},
30*time.Second,
toteki marked this conversation as resolved.
Show resolved Hide resolved
500*time.Millisecond,
)
}

// mustSucceedTx executes an sdk.Msg (retrying several times if receiving incorrect account sequence) and
// requires that the error returned is nil.
func (s *E2ETest) mustSucceedTx(msg sdk.Msg) {
s.Require().NoError(s.BroadcastTxWithRetry(msg))
}

// mustFailTx executes an sdk.Msg (retrying several times if receiving incorrect account sequence) and
// requires that the error returned contains a given substring. If the substring is empty, simply requires
// non-nil error.
func (s *E2ETest) mustFailTx(msg sdk.Msg, errSubstring string) {
s.Require().ErrorContains(
s.BroadcastTxWithRetry(msg),
errSubstring,
)
}

// TestMedians queries for the oracle params, collects historical
// prices based on those params, checks that the stored medians and
// medians deviations are correct, updates the oracle params with
Expand Down
14 changes: 5 additions & 9 deletions tests/e2e/setup/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,20 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/go-bip39"

appparams "github.com/umee-network/umee/v6/app/params"
"github.com/umee-network/umee/v6/x/metoken/mocks"
)

const (
ATOM = "ATOM"
ATOMBaseDenom = "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2"
ATOMExponent = 6

PhotonDenom = "photon"
InitBalanceStr = "510000000000" + appparams.BondDenom + ",100000000000" + PhotonDenom + ",100000000000" + mocks.USDTBaseDenom
GaiaChainID = "test-gaia-chain"

EthChainID uint = 15
EthMinerPK = "0xb1bab011e03a9862664706fc3bbaa1b16651528e5f0e7fbfcbfdd8be302a13e7"

PriceFeederContainerRepo = "ghcr.io/umee-network/price-feeder-umee"
PriceFeederServerPort = "7171/tcp"
PriceFeederMaxStartupTime = 20 // seconds
Expand All @@ -32,12 +34,6 @@ var (
stakeAmountCoin2 = sdk.NewCoin(appparams.BondDenom, stakeAmount2)
)

var (
ATOM = "ATOM"
ATOMBaseDenom = "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2"
ATOMExponent = 6
)

func createMnemonic() (string, error) {
entropySeed, err := bip39.NewEntropy(256)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions tests/e2e/setup/metoken.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (s *E2ETestSuite) TxMetokenSwap(umeeAddr string, asset sdk.Coin, meTokenDen
MetokenDenom: meTokenDenom,
}

return s.broadcastTxWithRetry(req)
return s.BroadcastTxWithRetry(req)
}

func (s *E2ETestSuite) TxMetokenRedeem(umeeAddr string, meToken sdk.Coin, assetDenom string) error {
Expand All @@ -39,5 +39,5 @@ func (s *E2ETestSuite) TxMetokenRedeem(umeeAddr string, meToken sdk.Coin, assetD
AssetDenom: assetDenom,
}

return s.broadcastTxWithRetry(req)
return s.BroadcastTxWithRetry(req)
}
5 changes: 5 additions & 0 deletions tests/e2e/setup/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ func (s *E2ETestSuite) initNodes() {
)
}

// TODO:
// create non-validator accounts which can be used for testing.
// since they don't vote for price feeder, these accounts are
// much less vulnerable to "incorrect account sequence" problems.

// copy the genesis file to the remaining validators
for _, val := range s.Chain.Validators[1:] {
_, err := copyFile(
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/setup/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ func (s *E2ETestSuite) QueryUmeeBalance(
return umeeBalance, umeeAddr
}

func (s *E2ETestSuite) broadcastTxWithRetry(msg sdk.Msg) error {
func (s *E2ETestSuite) BroadcastTxWithRetry(msg sdk.Msg) error {
var err error
for retry := 0; retry < 3; retry++ {
// retry if txs fails, because sometimes account sequence mismatch occurs due to txs pending
Expand Down
26 changes: 26 additions & 0 deletions tests/grpc/gov.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,32 @@ func LeverageRegistryUpdate(umeeClient client.Client, addTokens, updateTokens []
return MakeVoteAndCheckProposal(umeeClient, *resp)
}

// LeverageSpecialPairsUpdate submits a gov transaction to update leverage special assets,
// votes, and waits for proposal to pass.
func LeverageSpecialPairsUpdate(
umeeClient client.Client,
sets []ltypes.SpecialAssetSet,
pairs []ltypes.SpecialAssetPair,
) error {
msg := ltypes.MsgGovUpdateSpecialAssets{
Authority: checkers.GovModuleAddr,
Description: "Special Assets Proposal",
Sets: sets,
Pairs: pairs,
}

resp, err := umeeClient.Tx.TxSubmitProposalWithMsg([]sdk.Msg{&msg})
if err != nil {
return err
}

if len(resp.Logs) == 0 {
return fmt.Errorf("no logs in response")
}

return MakeVoteAndCheckProposal(umeeClient, *resp)
}

// MetokenRegistryUpdate submits a gov transaction to update metoken registry, votes, and waits for proposal to pass.
func MetokenRegistryUpdate(umeeClient client.Client, addIndexes, updateIndexes []metoken.Index) error {
msg := metoken.MsgGovUpdateRegistry{
Expand Down
2 changes: 1 addition & 1 deletion x/leverage/keeper/borrows.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func (k Keeper) assertBorrowerHealth(ctx sdk.Context, borrowerAddr sdk.AccAddres
borrowedValue := position.BorrowedValue()
borrowLimit := position.Limit()
if borrowedValue.GT(borrowLimit.Mul(maxUsage)) {
return types.ErrUndercollaterized.Wrapf(
return types.ErrUndercollateralized.Wrapf(
"borrowed: %s, limit: %s, max usage %s", borrowedValue, borrowLimit, maxUsage,
)
}
Expand Down
Loading
Loading