Skip to content

Commit

Permalink
v5.0.2 upgrade handler + tokenfactory tests + increasage of tf gas li…
Browse files Browse the repository at this point in the history
…mit call
  • Loading branch information
pr0n00gler committed Nov 22, 2024
1 parent a3e373a commit 7753d04
Show file tree
Hide file tree
Showing 11 changed files with 331 additions and 1 deletion.
2 changes: 2 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"path/filepath"
"time"

v502 "github.com/neutron-org/neutron/v5/app/upgrades/v5.0.2"
dynamicfeestypes "github.com/neutron-org/neutron/v5/x/dynamicfees/types"

"github.com/skip-mev/feemarket/x/feemarket"
Expand Down Expand Up @@ -228,6 +229,7 @@ const (
var (
Upgrades = []upgrades.Upgrade{
v500.Upgrade,
v502.Upgrade,
}

// DefaultNodeHome default home directories for the application daemon
Expand Down
18 changes: 18 additions & 0 deletions app/upgrades/v5.0.2/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package v502

import (
storetypes "cosmossdk.io/store/types"

"github.com/neutron-org/neutron/v5/app/upgrades"
)

const (
// UpgradeName defines the on-chain upgrade name.
UpgradeName = "v5.0.2"
)

var Upgrade = upgrades.Upgrade{
UpgradeName: UpgradeName,
CreateUpgradeHandler: CreateUpgradeHandler,
StoreUpgrades: storetypes.StoreUpgrades{},
}
30 changes: 30 additions & 0 deletions app/upgrades/v5.0.2/upgrades.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package v502

import (
"context"
"fmt"

upgradetypes "cosmossdk.io/x/upgrade/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"

"github.com/neutron-org/neutron/v5/app/upgrades"
)

func CreateUpgradeHandler(
_ *module.Manager,
_ module.Configurator,
_ *upgrades.UpgradeKeepers,
_ upgrades.StoreKeys,
_ codec.Codec,
) upgradetypes.UpgradeHandler {
return func(c context.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
ctx := sdk.UnwrapSDKContext(c)

ctx.Logger().Info("Starting module migrations...")

ctx.Logger().Info(fmt.Sprintf("Migration {%s} applied", UpgradeName))
return vm, nil
}
}
37 changes: 37 additions & 0 deletions app/upgrades/v5.0.2/upgrades_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package v502_test

import (
"testing"

upgradetypes "cosmossdk.io/x/upgrade/types"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"

v502 "github.com/neutron-org/neutron/v5/app/upgrades/v5.0.2"
"github.com/neutron-org/neutron/v5/testutil"
)

type UpgradeTestSuite struct {
testutil.IBCConnectionTestSuite
}

func TestKeeperTestSuite(t *testing.T) {
suite.Run(t, new(UpgradeTestSuite))
}

func (suite *UpgradeTestSuite) SetupTest() {
suite.IBCConnectionTestSuite.SetupTest()
}

func (suite *UpgradeTestSuite) TestOracleUpgrade() {
app := suite.GetNeutronZoneApp(suite.ChainA)
ctx := suite.ChainA.GetContext().WithChainID("neutron-1")
t := suite.T()

upgrade := upgradetypes.Plan{
Name: v502.UpgradeName,
Info: "some text here",
Height: 100,
}
require.NoError(t, app.UpgradeKeeper.ApplyUpgrade(ctx, upgrade))
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ require (
)

replace (
cosmossdk.io/math => cosmossdk.io/math v1.4.0
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
github.com/CosmWasm/wasmd => github.com/neutron-org/wasmd v0.53.0-neutron
github.com/cometbft/cometbft => github.com/neutron-org/cometbft v0.0.0-20241111105801-a7fe160b0b62
Expand Down
10 changes: 10 additions & 0 deletions testutil/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,16 @@ func (suite *IBCConnectionTestSuite) FundAcc(acc sdk.AccAddress, amounts sdk.Coi
suite.Require().NoError(err)
}

// FundModuleAcc funds target modules with specified amount.
func (suite *IBCConnectionTestSuite) FundModuleAcc(moduleName string, amounts sdk.Coins) {
bankKeeper := suite.GetNeutronZoneApp(suite.ChainA).BankKeeper
err := bankKeeper.MintCoins(suite.ChainA.GetContext(), tokenfactorytypes.ModuleName, amounts)
suite.Require().NoError(err)

err = bankKeeper.SendCoinsFromModuleToModule(suite.ChainA.GetContext(), tokenfactorytypes.ModuleName, moduleName, amounts)
suite.Require().NoError(err)
}

// update CCV path with correct info
func SetupCCVPath(path *ibctesting.Path, suite *IBCConnectionTestSuite) {
// - set provider endpoint's clientID
Expand Down
222 changes: 222 additions & 0 deletions x/tokenfactory/keeper/before_send_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ package keeper_test

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

"cosmossdk.io/math"
storetypes "cosmossdk.io/store/types"
wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"

dextypes "github.com/neutron-org/neutron/v5/x/dex/types"
icqtypes "github.com/neutron-org/neutron/v5/x/interchainqueries/types"
"github.com/neutron-org/neutron/v5/x/tokenfactory/types"
)

Expand Down Expand Up @@ -46,6 +51,127 @@ func (suite *KeeperTestSuite) initBalanceTrackContract(denom string) (sdk.AccAdd
return cosmwasmAddress, codeID, factoryDenom
}

type SendMsgTestCase struct {
desc string
msg func(denom string) *banktypes.MsgSend
expectPass bool
}

func (suite *KeeperTestSuite) TestBeforeSendHook() {
for _, tc := range []struct {
desc string
wasmFile string
sendMsgs []SendMsgTestCase
}{
{
desc: "should not allow sending 100 amount of *any* denom",
wasmFile: "./testdata/no100.wasm",
sendMsgs: []SendMsgTestCase{
{
desc: "sending 1 of factorydenom should not error",
msg: func(factorydenom string) *banktypes.MsgSend {
return banktypes.NewMsgSend(
suite.TestAccs[0],
suite.TestAccs[1],
sdk.NewCoins(sdk.NewInt64Coin(factorydenom, 1)),
)
},
expectPass: true,
},
{
desc: "sending 1 of non-factorydenom should not error",
msg: func(factorydenom string) *banktypes.MsgSend {
return banktypes.NewMsgSend(
suite.TestAccs[0],
suite.TestAccs[1],
sdk.NewCoins(sdk.NewInt64Coin("foo", 1)),
)
},
expectPass: true,
},
{
desc: "sending 100 of factorydenom should error",
msg: func(factorydenom string) *banktypes.MsgSend {
return banktypes.NewMsgSend(
suite.TestAccs[0],
suite.TestAccs[1],
sdk.NewCoins(sdk.NewInt64Coin(factorydenom, 100)),
)
},
expectPass: false,
},
{
desc: "sending 100 of non-factorydenom should work",
msg: func(factorydenom string) *banktypes.MsgSend {
return banktypes.NewMsgSend(
suite.TestAccs[0],
suite.TestAccs[1],
sdk.NewCoins(sdk.NewInt64Coin("foo", 100)),
)
},
expectPass: true,
},
{
desc: "having 100 coin within coins should not work",
msg: func(factorydenom string) *banktypes.MsgSend {
return banktypes.NewMsgSend(
suite.TestAccs[0],
suite.TestAccs[1],
sdk.NewCoins(sdk.NewInt64Coin(factorydenom, 100), sdk.NewInt64Coin("foo", 1)),
)
},
expectPass: false,
},
},
},
} {
suite.Run(fmt.Sprintf("Case %suite", tc.desc), func() {
// setup test
suite.Setup()

senderAddress := suite.ChainA.SenderAccounts[0].SenderAccount.GetAddress()
suite.TopUpWallet(suite.ChainA.GetContext(), senderAddress, suite.TestAccs[0])

// upload and instantiate wasm code
wasmCode, err := os.ReadFile(tc.wasmFile)
suite.Require().NoError(err, "test: %v", tc.desc)
codeID, _, err := suite.contractKeeper.Create(suite.ChainA.GetContext(), suite.TestAccs[0], wasmCode, nil)
suite.Require().NoError(err, "test: %v", tc.desc)
cosmwasmAddress, _, err := suite.contractKeeper.Instantiate(suite.ChainA.GetContext(), codeID, suite.TestAccs[0], suite.TestAccs[0], []byte("{}"), "", sdk.NewCoins())
suite.Require().NoError(err, "test: %v", tc.desc)

// create new denom
res, err := suite.msgServer.CreateDenom(suite.ChainA.GetContext(), types.NewMsgCreateDenom(suite.TestAccs[0].String(), "bitcoin"))
suite.Require().NoError(err, "test: %v", tc.desc)
denom := res.GetNewTokenDenom()

// mint enough coins to the creator
_, err = suite.msgServer.Mint(suite.ChainA.GetContext(), types.NewMsgMint(suite.TestAccs[0].String(), sdk.NewInt64Coin(denom, 1000000000)))
suite.Require().NoError(err)
// mint some non token factory denom coins for testing
suite.FundAcc(sdk.MustAccAddressFromBech32(suite.TestAccs[0].String()), sdk.Coins{sdk.NewInt64Coin("foo", 100000000000)})

params := types.DefaultParams()
params.WhitelistedHooks = []*types.WhitelistedHook{{DenomCreator: suite.TestAccs[0].String(), CodeID: 1}}
err = suite.GetNeutronZoneApp(suite.ChainA).TokenFactoryKeeper.SetParams(suite.ChainA.GetContext(), params)
suite.Require().NoError(err)

// set beforesend hook to the new denom
_, err = suite.msgServer.SetBeforeSendHook(suite.ChainA.GetContext(), types.NewMsgSetBeforeSendHook(suite.TestAccs[0].String(), denom, cosmwasmAddress.String()))
suite.Require().NoError(err, "test: %v", tc.desc)

for _, sendTc := range tc.sendMsgs {
_, err := suite.bankMsgServer.Send(suite.ChainA.GetContext(), sendTc.msg(denom))
if sendTc.expectPass {
suite.Require().NoError(err, "test: %v", sendTc.desc)
} else {
suite.Require().Error(err, "test: %v", sendTc.desc)
}
}
})
}
}

func (suite *KeeperTestSuite) TestTrackBeforeSendWasm() {
suite.Setup()

Expand Down Expand Up @@ -115,3 +241,99 @@ func (suite *KeeperTestSuite) TestNonWhitelistedHooksNotCalled() {
// Whitelisted contract is not called
suite.Require().Equal("\"0\"", string(queryResp))
}

// TestInfiniteTrackBeforeSend tests gas metering with infinite loop contract
// to properly test if we are gas metering trackBeforeSend properly.
func (suite *KeeperTestSuite) TestInfiniteTrackBeforeSend() {
for _, tc := range []struct {
name string
wasmFile string
tokenToSend sdk.Coins
useFactoryDenom bool
blockBeforeSend bool
expectedError bool
}{
{
name: "sending tokenfactory denom from module to module with infinite contract should panic",
wasmFile: "./testdata/infinite_track_beforesend.wasm",
useFactoryDenom: true,
},
{
name: "sending tokenfactory denom from account to account with infinite contract should panic",
wasmFile: "./testdata/infinite_track_beforesend.wasm",
useFactoryDenom: true,
blockBeforeSend: true,
},
{
name: "sending non-tokenfactory denom from module to module with infinite contract should not panic",
wasmFile: "./testdata/infinite_track_beforesend.wasm",
tokenToSend: sdk.NewCoins(sdk.NewInt64Coin("foo", 1000000)),
useFactoryDenom: false,
},
{
name: "Try using no 100",
wasmFile: "./testdata/no100.wasm",
useFactoryDenom: true,
},
} {
suite.Run(fmt.Sprintf("Case %suite", tc.name), func() {
// setup test
suite.Setup()

// load wasm file
wasmCode, err := os.ReadFile(tc.wasmFile)
suite.Require().NoError(err)

// instantiate wasm code
codeID, _, err := suite.contractKeeper.Create(suite.ChainA.GetContext(), suite.ChainA.SenderAccounts[0].SenderAccount.GetAddress(), wasmCode, nil)
suite.Require().NoError(err, "test: %v", tc.name)
cosmwasmAddress, _, err := suite.contractKeeper.Instantiate(suite.ChainA.GetContext(), codeID, suite.TestAccs[0], suite.ChainA.SenderAccounts[0].SenderAccount.GetAddress(), []byte("{}"), "", sdk.NewCoins())
suite.Require().NoError(err, "test: %v", tc.name)

params := types.DefaultParams()
params.WhitelistedHooks = []*types.WhitelistedHook{{DenomCreator: suite.ChainA.SenderAccounts[0].SenderAccount.GetAddress().String(), CodeID: 1}}
err = suite.GetNeutronZoneApp(suite.ChainA).TokenFactoryKeeper.SetParams(suite.ChainA.GetContext(), params)
suite.Require().NoError(err)

// create new denom
res, err := suite.msgServer.CreateDenom(suite.ChainA.GetContext(), types.NewMsgCreateDenom(suite.ChainA.SenderAccounts[0].SenderAccount.GetAddress().String(), "bitcoin"))
suite.Require().NoError(err, "test: %v", tc.name)
factoryDenom := res.GetNewTokenDenom()

var tokenToSend sdk.Coins
if tc.useFactoryDenom {
tokenToSend = sdk.NewCoins(sdk.NewInt64Coin(factoryDenom, 100))
} else {
tokenToSend = tc.tokenToSend
}

// send the mint module tokenToSend
if tc.blockBeforeSend {
suite.FundAcc(suite.ChainA.SenderAccounts[0].SenderAccount.GetAddress(), tokenToSend)
} else {
suite.FundModuleAcc(icqtypes.ModuleName, tokenToSend)
}

// set beforesend hook to the new denom
// we register infinite loop contract here to test if we are gas metering properly
_, err = suite.msgServer.SetBeforeSendHook(suite.ChainA.GetContext(), types.NewMsgSetBeforeSendHook(suite.ChainA.SenderAccounts[0].SenderAccount.GetAddress().String(), factoryDenom, cosmwasmAddress.String()))
suite.Require().NoError(err, "test: %v", tc.name)

ctx := suite.ChainA.GetContext().WithGasMeter(storetypes.NewGasMeter(30_000_000))

if tc.blockBeforeSend {
err = suite.GetNeutronZoneApp(suite.ChainA).BankKeeper.SendCoins(ctx, suite.ChainA.SenderAccounts[0].SenderAccount.GetAddress(), suite.ChainA.SenderAccounts[1].SenderAccount.GetAddress(), tokenToSend)
suite.Require().Error(err)
} else {
// track before send suppresses in any case, thus we expect no error
err = suite.GetNeutronZoneApp(suite.ChainA).BankKeeper.SendCoinsFromModuleToModule(ctx, icqtypes.ModuleName, dextypes.ModuleName, tokenToSend)
suite.Require().NoError(err)

// send should happen regardless of trackBeforeSend results
distributionModuleAddress := suite.GetNeutronZoneApp(suite.ChainA).AccountKeeper.GetModuleAddress("dex")
distributionModuleBalances := suite.GetNeutronZoneApp(suite.ChainA).BankKeeper.GetAllBalances(suite.ChainA.GetContext(), distributionModuleAddress)
suite.Require().True(distributionModuleBalances.Equal(tokenToSend))
}
})
}
}
Loading

0 comments on commit 7753d04

Please sign in to comment.