Unverified Commit fd59f430 authored by Adam Tucker's avatar Adam Tucker Committed by GitHub
Browse files

feat: addToExistingLock e2e tests (#2571)

* add addToExistingLock tests

* second test pass

* clean up unused

* address Roman's suggestions
parent 60726078
Showing with 196 additions and 63 deletions
+196 -63
......@@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/require"
coretypes "github.com/tendermint/tendermint/rpc/core/types"
appparams "github.com/osmosis-labs/osmosis/v11/app/params"
"github.com/osmosis-labs/osmosis/v11/tests/e2e/configurer/config"
"github.com/osmosis-labs/osmosis/v11/tests/e2e/containers"
......@@ -140,6 +141,35 @@ func (c *Config) SendIBC(dstChain *Config, recipient string, token sdk.Coin) {
c.t.Log("successfully sent IBC tokens")
}
func (c *Config) EnableSuperfluidAsset(denom string) {
chain, err := c.GetDefaultNode()
require.NoError(c.t, err)
chain.SubmitSuperfluidProposal(denom, sdk.NewCoin(appparams.BaseCoinUnit, sdk.NewInt(config.InitialMinDeposit)))
c.LatestProposalNumber += 1
chain.DepositProposal(c.LatestProposalNumber, false)
for _, node := range c.NodeConfigs {
node.VoteYesProposal(initialization.ValidatorWalletName, c.LatestProposalNumber)
}
}
func (c *Config) LockAndAddToExistingLock(amount sdk.Int, denom, lockupWalletAddr, lockupWalletSuperfluidAddr string) {
chain, err := c.GetDefaultNode()
require.NoError(c.t, err)
// lock tokens
chain.LockTokens(fmt.Sprintf("%v%s", amount, denom), "240s", lockupWalletAddr)
c.LatestLockNumber += 1
// add to existing lock
chain.AddToExistingLock(amount, denom, "240s", lockupWalletAddr)
// superfluid lock tokens
chain.LockTokens(fmt.Sprintf("%v%s", amount, denom), "240s", lockupWalletSuperfluidAddr)
c.LatestLockNumber += 1
chain.SuperfluidDelegate(c.LatestLockNumber, c.NodeConfigs[1].OperatorAddress, lockupWalletSuperfluidAddr)
// add to existing lock
chain.AddToExistingLock(amount, denom, "240s", lockupWalletSuperfluidAddr)
}
// GetDefaultNode returns the default node of the chain.
// The default node is the first one created. Returns error if no
// ndoes created.
......
......@@ -9,17 +9,31 @@ import (
appparams "github.com/osmosis-labs/osmosis/v11/app/params"
"github.com/osmosis-labs/osmosis/v11/tests/e2e/configurer/config"
"github.com/osmosis-labs/osmosis/v11/tests/e2e/util"
gammtypes "github.com/osmosis-labs/osmosis/v11/x/gamm/types"
lockuptypes "github.com/osmosis-labs/osmosis/v11/x/lockup/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
)
func (n *NodeConfig) CreatePool(poolFile, from string) {
func (n *NodeConfig) CreatePool(poolFile, from string) uint64 {
n.LogActionF("creating pool from file %s", poolFile)
cmd := []string{"osmosisd", "tx", "gamm", "create-pool", fmt.Sprintf("--pool-file=/osmosis/%s", poolFile), fmt.Sprintf("--from=%s", from)}
_, _, err := n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd)
require.NoError(n.t, err)
n.LogActionF("successfully created pool")
path := "osmosis/gamm/v1beta1/num_pools"
bz, err := n.QueryGRPCGateway(path)
require.NoError(n.t, err)
var numPools gammtypes.QueryNumPoolsResponse
err = util.Cdc.UnmarshalJSON(bz, &numPools)
require.NoError(n.t, err)
poolID := numPools.NumPools
n.LogActionF("successfully created pool %d", poolID)
return poolID
}
func (n *NodeConfig) SubmitUpgradeProposal(upgradeVersion string, upgradeHeight int64, initialDeposit sdk.Coin) {
......@@ -85,6 +99,46 @@ func (n *NodeConfig) LockTokens(tokens string, duration string, from string) {
n.LogActionF("successfully created lock")
}
func (n *NodeConfig) AddToExistingLock(tokens sdk.Int, denom, duration, from string) {
n.LogActionF("retrieving existing lock ID")
durationPath := fmt.Sprintf("/osmosis/lockup/v1beta1/account_locked_longer_duration/%s?duration=%s", from, duration)
bz, err := n.QueryGRPCGateway(durationPath)
require.NoError(n.t, err)
var accountLockedDurationResp lockuptypes.AccountLockedDurationResponse
err = util.Cdc.UnmarshalJSON(bz, &accountLockedDurationResp)
require.NoError(n.t, err)
var lockID string
for _, periodLock := range accountLockedDurationResp.Locks {
if periodLock.Coins.AmountOf(denom).GT(sdk.ZeroInt()) {
lockID = fmt.Sprintf("%v", periodLock.ID)
break
}
}
n.LogActionF("noting previous lockup amount")
path := fmt.Sprintf("/osmosis/lockup/v1beta1/locked_by_id/%s", lockID)
bz, err = n.QueryGRPCGateway(path)
require.NoError(n.t, err)
var lockedResp lockuptypes.LockedResponse
err = util.Cdc.UnmarshalJSON(bz, &lockedResp)
require.NoError(n.t, err)
previousLockupAmount := lockedResp.Lock.Coins.AmountOf(denom)
n.LogActionF("previous lockup amount is %v", previousLockupAmount)
n.LogActionF("locking %s for %s", tokens, duration)
cmd := []string{"osmosisd", "tx", "lockup", "lock-tokens", fmt.Sprintf("%s%s", tokens, denom), fmt.Sprintf("--duration=%s", duration), fmt.Sprintf("--from=%s", from)}
_, _, err = n.containerManager.ExecTxCmd(n.t, n.chainId, n.Name, cmd)
require.NoError(n.t, err)
n.LogActionF("noting new lockup amount")
bz, err = n.QueryGRPCGateway(path)
require.NoError(n.t, err)
err = util.Cdc.UnmarshalJSON(bz, &lockedResp)
require.NoError(n.t, err)
newLockupAmount := lockedResp.Lock.Coins.AmountOf(denom)
n.LogActionF("new lockup amount is %v", newLockupAmount)
lockupDelta := newLockupAmount.Sub(previousLockupAmount)
require.True(n.t, lockupDelta.Equal(tokens))
n.LogActionF("successfully added to existing lock")
}
func (n *NodeConfig) SuperfluidDelegate(lockNumber int, valAddress string, from string) {
lockStr := strconv.Itoa(lockNumber)
n.LogActionF("superfluid delegating lock %s to %s", lockStr, valAddress)
......@@ -114,6 +168,18 @@ func (n *NodeConfig) CreateWallet(walletName string) string {
return walletAddr
}
func (n *NodeConfig) GetWallet(walletName string) string {
n.LogActionF("retrieving wallet %s", walletName)
cmd := []string{"osmosisd", "keys", "show", walletName, "--keyring-backend=test"}
outBuf, _, err := n.containerManager.ExecCmd(n.t, n.Name, cmd, "")
require.NoError(n.t, err)
re := regexp.MustCompile("osmo1(.{38})")
walletAddr := fmt.Sprintf("%s\n", re.FindString(outBuf.String()))
walletAddr = strings.TrimSuffix(walletAddr, "\n")
n.LogActionF("wallet %s found, waller address - %s", walletName, walletAddr)
return walletAddr
}
func (n *NodeConfig) QueryPropStatusTimed(proposalNumber int, desiredStatus string, totalTime chan time.Duration) {
start := time.Now()
require.Eventually(
......
......@@ -106,6 +106,9 @@ func (uc *UpgradeConfigurer) ConfigureChain(chainConfig *chain.Config) error {
}
func (uc *UpgradeConfigurer) CreatePreUpgradeState() error {
const lockupWallet = "lockup-wallet"
const lockupWalletSuperfluid = "lockup-wallet-superfluid"
chainA := uc.chainConfigs[0]
chainANode, err := chainA.GetDefaultNode()
if err != nil {
......@@ -124,6 +127,18 @@ func (uc *UpgradeConfigurer) CreatePreUpgradeState() error {
chainANode.CreatePool("pool1A.json", initialization.ValidatorWalletName)
chainBNode.CreatePool("pool1B.json", initialization.ValidatorWalletName)
// enable superfluid assets on chainA
chainA.EnableSuperfluidAsset("gamm/pool/1")
// setup wallets and send gamm tokens to these wallets (only chainA)
lockupWalletAddrA, lockupWalletSuperfluidAddrA := chainANode.CreateWallet(lockupWallet), chainANode.CreateWallet(lockupWalletSuperfluid)
chainANode.BankSend("10000000000000000000gamm/pool/1", chainA.NodeConfigs[0].PublicAddress, lockupWalletAddrA)
chainANode.BankSend("10000000000000000000gamm/pool/1", chainA.NodeConfigs[0].PublicAddress, lockupWalletSuperfluidAddrA)
// test lock and add to existing lock for both regular and superfluid lockups (only chainA)
chainA.LockAndAddToExistingLock(sdk.NewInt(1000000000000000000), "gamm/pool/1", lockupWalletAddrA, lockupWalletSuperfluidAddrA)
return nil
}
......
......@@ -62,7 +62,7 @@ func (s *IntegrationTestSuite) SetupSuite() {
s.skipUpgrade, err = strconv.ParseBool(str)
s.Require().NoError(err)
if s.skipUpgrade {
s.T().Log(fmt.Sprintf("%s was true, skipping upgrade tests", skipIBCEnv))
s.T().Log(fmt.Sprintf("%s was true, skipping upgrade tests", skipUpgradeEnv))
}
}
upgradeSettings.IsEnabled = !s.skipUpgrade
......
......@@ -19,16 +19,14 @@ import (
)
// Test01IBCTokenTransfer tests that IBC token transfers work as expected.
// This test must preceed Test02CreatePoolPostUpgrade. That's why it is prefixed with "01"
// This test must precede Test02CreatePoolPostUpgrade. That's why it is prefixed with "01"
// to ensure correct ordering. See Test02CreatePoolPostUpgrade for more details.
func (s *IntegrationTestSuite) Test01IBCTokenTransfer() {
if s.skipIBC {
s.T().Skip("Skipping IBC tests")
}
chainA := s.configurer.GetChainConfig(0)
chainB := s.configurer.GetChainConfig(1)
chainA.SendIBC(chainB, chainB.NodeConfigs[0].PublicAddress, initialization.OsmoToken)
chainB.SendIBC(chainA, chainA.NodeConfigs[0].PublicAddress, initialization.OsmoToken)
chainA.SendIBC(chainB, chainB.NodeConfigs[0].PublicAddress, initialization.StakeToken)
......@@ -41,67 +39,58 @@ func (s *IntegrationTestSuite) Test01IBCTokenTransfer() {
// This is the reason for prefixing the name with 02 to ensure
// correct order.
func (s *IntegrationTestSuite) Test02CreatePool() {
chain := s.configurer.GetChainConfig(0)
node, err := chain.GetDefaultNode()
chainA := s.configurer.GetChainConfig(0)
chainANode, err := chainA.GetDefaultNode()
s.NoError(err)
node.CreatePool("nativeDenomPool.json", initialization.ValidatorWalletName)
chainANode.CreatePool("nativeDenomPool.json", initialization.ValidatorWalletName)
if s.skipIBC {
s.T().Log("skipping creating pool with IBC denoms because IBC tests are disabled")
return
}
node.CreatePool("ibcDenomPool.json", initialization.ValidatorWalletName)
chainANode.CreatePool("ibcDenomPool.json", initialization.ValidatorWalletName)
}
// Test03SuperfluidVoting tests that superfluid voting is functioning as expected.
// It does so by doing the following:
//- creating a pool
// - attempting to submit a proposal to enable superfluid voring in that pool
// - attempting to submit a proposal to enable superfluid voting in that pool
// - voting yes on the proposal from the validator wallet
// - voting no on the proposal from the delegator wallet
// - ensuring that delegator's wallet overwrites the validator's vote
// This test depends on pool creation to function correctly.
// As a result, it is prefixed by 03 to run after Test02CreatePool.
func (s *IntegrationTestSuite) Test03SuperfluidVoting() {
const walletName = "superfluid-wallet"
chain := s.configurer.GetChainConfig(0)
node, err := chain.GetDefaultNode()
func (s *IntegrationTestSuite) TestSuperfluidVoting() {
chainA := s.configurer.GetChainConfig(0)
chainANode, err := chainA.GetDefaultNode()
s.NoError(err)
// enable superfluid via proposal.
node.SubmitSuperfluidProposal("gamm/pool/1", sdk.NewCoin(appparams.BaseCoinUnit, sdk.NewInt(config.InitialMinDeposit)))
chain.LatestProposalNumber += 1
node.DepositProposal(chain.LatestProposalNumber, false)
for _, node := range chain.NodeConfigs {
node.VoteYesProposal(initialization.ValidatorWalletName, chain.LatestProposalNumber)
}
poolId := chainANode.CreatePool("nativeDenomPool.json", chainA.NodeConfigs[0].PublicAddress)
// enable superfluid assets
chainA.EnableSuperfluidAsset(fmt.Sprintf("gamm/pool/%d", poolId))
walletAddr := node.CreateWallet(walletName)
// send gamm tokens to node's other wallet (non self-delegation wallet)
node.BankSend("100000000000000000000gamm/pool/1", chain.NodeConfigs[0].PublicAddress, walletAddr)
// lock tokens from node 0 on chain A
node.LockTokens("100000000000000000000gamm/pool/1", "240s", walletName)
chain.LatestLockNumber += 1
// superfluid delegate from non self-delegation wallet to validator 1 on chain.
node.SuperfluidDelegate(chain.LatestLockNumber, chain.NodeConfigs[1].OperatorAddress, walletName)
// setup wallets and send gamm tokens to these wallets (both chains)
superfluildVotingWallet := chainANode.CreateWallet("Test03SuperfluidVoting")
chainANode.BankSend(fmt.Sprintf("10000000000000000000gamm/pool/%d", poolId), chainA.NodeConfigs[0].PublicAddress, superfluildVotingWallet)
chainANode.LockTokens(fmt.Sprintf("%v%s", sdk.NewInt(1000000000000000000), fmt.Sprintf("gamm/pool/%d", poolId)), "240s", superfluildVotingWallet)
chainA.LatestLockNumber += 1
chainANode.SuperfluidDelegate(chainA.LatestLockNumber, chainA.NodeConfigs[1].OperatorAddress, superfluildVotingWallet)
// create a text prop, deposit and vote yes
node.SubmitTextProposal("superfluid vote overwrite test", sdk.NewCoin(appparams.BaseCoinUnit, sdk.NewInt(config.InitialMinDeposit)), false)
chain.LatestProposalNumber += 1
node.DepositProposal(chain.LatestProposalNumber, false)
for _, node := range chain.NodeConfigs {
node.VoteYesProposal(initialization.ValidatorWalletName, chain.LatestProposalNumber)
chainANode.SubmitTextProposal("superfluid vote overwrite test", sdk.NewCoin(appparams.BaseCoinUnit, sdk.NewInt(config.InitialMinDeposit)), false)
chainA.LatestProposalNumber += 1
chainANode.DepositProposal(chainA.LatestProposalNumber, false)
for _, node := range chainA.NodeConfigs {
node.VoteYesProposal(initialization.ValidatorWalletName, chainA.LatestProposalNumber)
}
// set delegator vote to no
node.VoteNoProposal(walletName, chain.LatestProposalNumber)
chainANode.VoteNoProposal(superfluildVotingWallet, chainA.LatestProposalNumber)
s.Eventually(
func() bool {
noTotal, yesTotal, noWithVetoTotal, abstainTotal, err := node.QueryPropTally(chain.LatestProposalNumber)
noTotal, yesTotal, noWithVetoTotal, abstainTotal, err := chainANode.QueryPropTally(chainA.LatestProposalNumber)
if err != nil {
return false
}
......@@ -114,13 +103,13 @@ func (s *IntegrationTestSuite) Test03SuperfluidVoting() {
10*time.Millisecond,
"Osmosis node failed to retrieve prop tally",
)
noTotal, _, _, _, _ := node.QueryPropTally(chain.LatestProposalNumber)
noTotal, _, _, _, _ := chainANode.QueryPropTally(chainA.LatestProposalNumber)
noTotalFinal, err := strconv.Atoi(noTotal.String())
s.NoError(err)
s.Eventually(
func() bool {
intAccountBalance, err := node.QueryIntermediaryAccount("gamm/pool/1", chain.NodeConfigs[1].OperatorAddress)
intAccountBalance, err := chainANode.QueryIntermediaryAccount(fmt.Sprintf("gamm/pool/%d", poolId), chainA.NodeConfigs[1].OperatorAddress)
s.Require().NoError(err)
if err != nil {
return false
......@@ -137,16 +126,50 @@ func (s *IntegrationTestSuite) Test03SuperfluidVoting() {
)
}
// TestAddToExistingLockPostUpgrade ensures addToExistingLock works for locks created preupgrade.
func (s *IntegrationTestSuite) TestAddToExistingLockPostUpgrade() {
if s.skipUpgrade {
s.T().Skip("Skipping AddToExistingLockPostUpgrade test")
}
chainA := s.configurer.GetChainConfig(0)
chainANode, err := chainA.GetDefaultNode()
s.NoError(err)
// ensure we can add to existing locks and superfluid locks that existed pre upgrade on chainA
// we use the hardcoded gamm/pool/1 and these specific wallet names to match what was created pre upgrade
lockupWalletAddr, lockupWalletSuperfluidAddr := chainANode.GetWallet("lockup-wallet"), chainANode.GetWallet("lockup-wallet-superfluid")
chainANode.AddToExistingLock(sdk.NewInt(1000000000000000000), "gamm/pool/1", "240s", lockupWalletAddr)
chainANode.AddToExistingLock(sdk.NewInt(1000000000000000000), "gamm/pool/1", "240s", lockupWalletSuperfluidAddr)
}
// TestAddToExistingLock tests lockups to both regular and superfluid locks.
func (s *IntegrationTestSuite) TestAddToExistingLock() {
chainA := s.configurer.GetChainConfig(0)
chainANode, err := chainA.GetDefaultNode()
s.NoError(err)
// ensure we can add to new locks and superfluid locks
// create pool and enable superfluid assets
poolId := chainANode.CreatePool("nativeDenomPool.json", chainA.NodeConfigs[0].PublicAddress)
chainA.EnableSuperfluidAsset(fmt.Sprintf("gamm/pool/%d", poolId))
// setup wallets and send gamm tokens to these wallets on chainA
lockupWalletAddr, lockupWalletSuperfluidAddr := chainANode.CreateWallet("TestAddToExistingLock"), chainANode.CreateWallet("TestAddToExistingLockSuperfluid")
chainANode.BankSend(fmt.Sprintf("10000000000000000000gamm/pool/%d", poolId), chainA.NodeConfigs[0].PublicAddress, lockupWalletAddr)
chainANode.BankSend(fmt.Sprintf("10000000000000000000gamm/pool/%d", poolId), chainA.NodeConfigs[0].PublicAddress, lockupWalletSuperfluidAddr)
// ensure we can add to new locks and superfluid locks on chainA
chainA.LockAndAddToExistingLock(sdk.NewInt(1000000000000000000), fmt.Sprintf("gamm/pool/%d", poolId), lockupWalletAddr, lockupWalletSuperfluidAddr)
}
func (s *IntegrationTestSuite) TestStateSync() {
if s.skipStateSync {
s.T().Skip()
}
chain := s.configurer.GetChainConfig(0)
runningNode, err := chain.GetDefaultNode()
chainA := s.configurer.GetChainConfig(0)
runningNode, err := chainA.GetDefaultNode()
s.Require().NoError(err)
persistenrPeers := chain.GetPersistentPeers()
persistentPeers := chainA.GetPersistentPeers()
stateSyncHostPort := fmt.Sprintf("%s:26657", runningNode.Name)
stateSyncRPCServers := []string{stateSyncHostPort, stateSyncHostPort}
......@@ -172,20 +195,20 @@ func (s *IntegrationTestSuite) TestStateSync() {
// configure genesis and config files for the state-synchin node.
nodeInit, err := initialization.InitSingleNode(
chain.Id,
chainA.Id,
tempDir,
filepath.Join(runningNode.ConfigDir, "config", "genesis.json"),
stateSynchingNodeConfig,
time.Duration(chain.VotingPeriod),
//time.Duration(chain.ExpeditedVotingPeriod),
time.Duration(chainA.VotingPeriod),
//time.Duration(chainA.ExpeditedVotingPeriod),
trustHeight,
trustHash,
stateSyncRPCServers,
persistenrPeers,
persistentPeers,
)
s.Require().NoError(err)
stateSynchingNode := chain.CreateNode(nodeInit)
stateSynchingNode := chainA.CreateNode(nodeInit)
// ensure that the running node has snapshots at a height > trustHeight.
hasSnapshotsAvailable := func(syncInfo coretypes.SyncInfo) bool {
......@@ -228,7 +251,7 @@ func (s *IntegrationTestSuite) TestStateSync() {
)
// stop the state synching node.
err = chain.RemoveNode(stateSynchingNode.Name)
err = chainA.RemoveNode(stateSynchingNode.Name)
s.NoError(err)
}
......@@ -237,17 +260,17 @@ func (s *IntegrationTestSuite) TestExpeditedProposals() {
s.T().Skip("this can be re-enabled post v12")
}
chain := s.configurer.GetChainConfig(0)
node, err := chain.GetDefaultNode()
chainA := s.configurer.GetChainConfig(0)
chainANode, err := chainA.GetDefaultNode()
s.NoError(err)
node.SubmitTextProposal("expedited text proposal", sdk.NewCoin(appparams.BaseCoinUnit, sdk.NewInt(config.InitialMinExpeditedDeposit)), true)
chain.LatestProposalNumber += 1
node.DepositProposal(chain.LatestProposalNumber, true)
chainANode.SubmitTextProposal("expedited text proposal", sdk.NewCoin(appparams.BaseCoinUnit, sdk.NewInt(config.InitialMinExpeditedDeposit)), true)
chainA.LatestProposalNumber += 1
chainANode.DepositProposal(chainA.LatestProposalNumber, true)
totalTimeChan := make(chan time.Duration, 1)
go node.QueryPropStatusTimed(chain.LatestProposalNumber, "PROPOSAL_STATUS_PASSED", totalTimeChan)
for _, node := range chain.NodeConfigs {
node.VoteYesProposal(initialization.ValidatorWalletName, chain.LatestProposalNumber)
go chainANode.QueryPropStatusTimed(chainA.LatestProposalNumber, "PROPOSAL_STATUS_PASSED", totalTimeChan)
for _, node := range chainA.NodeConfigs {
node.VoteYesProposal(initialization.ValidatorWalletName, chainA.LatestProposalNumber)
}
// if querying proposal takes longer than timeoutPeriod, stop the goroutine and error
var elapsed time.Duration
......@@ -260,11 +283,10 @@ func (s *IntegrationTestSuite) TestExpeditedProposals() {
}
// compare the time it took to reach pass status to expected expedited voting period
expeditedVotingPeriodDuration := time.Duration(chain.ExpeditedVotingPeriod * float32(time.Second))
expeditedVotingPeriodDuration := time.Duration(chainA.ExpeditedVotingPeriod * float32(time.Second))
timeDelta := elapsed - expeditedVotingPeriodDuration
// ensure delta is within one second of expected time
// ensure delta is within two seconds of expected time
s.Require().Less(timeDelta, 2*time.Second)
s.T().Logf("expeditedVotingPeriodDuration within one second of expected time: %v", timeDelta)
s.T().Logf("expeditedVotingPeriodDuration within two seconds of expected time: %v", timeDelta)
close(totalTimeChan)
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment