wormhole/wormchain/interchaintest/shutdown_contracts_test.go

255 lines
13 KiB
Go

package ictest
import (
"encoding/base64"
"encoding/json"
"fmt"
"testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/strangelove-ventures/interchaintest/v4"
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
"github.com/strangelove-ventures/interchaintest/v4/ibc"
"github.com/stretchr/testify/require"
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
"github.com/wormhole-foundation/wormchain/interchaintest/helpers"
"github.com/wormhole-foundation/wormchain/interchaintest/helpers/cw_wormhole"
"github.com/wormhole-foundation/wormhole/sdk/vaa"
)
// TestShutdownCoreContract tests the endpoints of a contract in its "shutdown" state
func TestShutdownCoreContract(t *testing.T) {
// Setup chain and contract
numVals := 1
oldGuardians := guardians.CreateValSet(t, numVals)
chain := createSingleNodeCluster(t, "v2.24.2", *oldGuardians)
ctx, _ := buildSingleNodeInterchain(t, chain)
// Chains
wormchain := chain.(*cosmos.CosmosChain)
// Users
users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), 1, wormchain)
user := users[0]
// Deploy contract to wormhole
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, vaa.ChainIDWormchain, oldGuardians)
contractInfo := helpers.StoreAndInstantiateWormholeContract(t, ctx, wormchain, "faucet", "./contracts/wormhole_core.wasm", "wormhole_core", coreInstantiateMsg, oldGuardians)
contractAddr := contractInfo.Address
// Store a new version of the contract to upgrade to
wormNewCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/shutdown_wormhole_core.wasm", oldGuardians)
// Submit contract upgrade
err := cw_wormhole.SubmitContractUpgrade(t, ctx, oldGuardians, wormchain, contractAddr, wormNewCodeId)
require.NoError(t, err)
// -----------------------------------
// Try to post a message - should fail
message := []byte("test message")
messageBase64 := base64.StdEncoding.EncodeToString(message)
nonce := 1
executeMsg, err := json.Marshal(cw_wormhole.ExecuteMsg{
PostMessage: &cw_wormhole.ExecuteMsg_PostMessage{
Message: cw_wormhole.Binary(messageBase64),
Nonce: nonce,
},
})
require.NoError(t, err)
// Execute contract
_, err = wormchain.ExecuteContract(ctx, "faucet", contractAddr, string(executeMsg))
require.Error(t, err)
// -----------------------------------
// Try to set fees - should fail
_, err = cw_wormhole.SubmitFeeUpdate(t, ctx, oldGuardians, wormchain, contractAddr, "1000000", false)
require.Error(t, err)
// -----------------------------------
// Try to transfer fees - should fail
_, err = cw_wormhole.SubmitTransferFee(t, ctx, oldGuardians, wormchain, contractAddr, []byte(user.Address), "10000000000", false)
require.Error(t, err)
// -----------------------------------
// Try to submit a guardian set update - should pass
initialIndex := int(helpers.QueryConsensusGuardianSetIndex(t, wormchain, ctx))
signingGuardians := guardians.CreateValSet(t, numVals)
newGuardians := signingGuardians
err = cw_wormhole.SubmitGuardianSetUpdate(t, ctx, wormchain, contractAddr, newGuardians, uint32(initialIndex+1), oldGuardians)
require.NoError(t, err)
cw_wormhole.VerifyGuardianSet(t, ctx, wormchain, contractAddr, newGuardians, initialIndex+1)
// -----------------------------------
// Migrate contract back to original contract id
err = cw_wormhole.SubmitContractUpgrade(t, ctx, signingGuardians, wormchain, contractAddr, contractInfo.ContractInfo.CodeID)
require.NoError(t, err)
}
// TestShutdownTokenBridge tests the endpoints of a contract in its "shutdown" state
// The shutdown contract only allows the following: Upgrading the Contract & Registering a new chain.
func TestShutdownTokenBridge(t *testing.T) {
// Setup chain and contract
numVals := 1
guardians := guardians.CreateValSet(t, numVals)
chains := CreateChains(t, "v2.24.2", *guardians)
ctx, r, eRep, _ := BuildInterchain(t, chains)
// Chains
wormchain := chains[0].(*cosmos.CosmosChain)
gaia := chains[1].(*cosmos.CosmosChain)
osmosis := chains[2].(*cosmos.CosmosChain)
wormchainFaucetAddrBz, err := wormchain.GetAddress(ctx, "faucet")
require.NoError(t, err)
wormchainFaucetAddr := sdk.MustBech32ifyAddressBytes(wormchain.Config().Bech32Prefix, wormchainFaucetAddrBz)
fmt.Println("Wormchain faucet addr: ", wormchainFaucetAddr)
osmoToWormChannel, err := ibc.GetTransferChannel(ctx, r, eRep, osmosis.Config().ChainID, wormchain.Config().ChainID)
require.NoError(t, err)
wormToOsmoChannel := osmoToWormChannel.Counterparty
gaiaToWormChannel, err := ibc.GetTransferChannel(ctx, r, eRep, gaia.Config().ChainID, wormchain.Config().ChainID)
require.NoError(t, err)
wormToGaiaChannel := gaiaToWormChannel.Counterparty
users := interchaintest.GetAndFundTestUsers(t, ctx, "default", int64(10_000_000_000), gaia, osmosis, osmosis)
gaiaUser := users[0]
osmoUser1 := users[1]
osmoUser2 := users[2]
// Store wormhole core contract
coreContractCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/wormhole_core.wasm", guardians)
fmt.Println("Core contract code id: ", coreContractCodeId)
// Instantiate wormhole core contract
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, vaa.ChainIDWormchain, guardians)
coreContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", coreContractCodeId, "wormhole_core", coreInstantiateMsg, guardians)
fmt.Println("Core contract address: ", coreContractAddr)
// Store cw20_wrapped_2 contract
wrappedAssetCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/cw20_wrapped_2.wasm", guardians)
fmt.Println("CW20 wrapped_2 code id: ", wrappedAssetCodeId)
// Store token bridge contract
tbContractCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/token_bridge.wasm", guardians)
fmt.Println("Token bridge contract code id: ", tbContractCodeId)
// Instantiate token bridge contract
tbInstantiateMsg := helpers.TbContractInstantiateMsg(t, wormchainConfig, coreContractAddr, wrappedAssetCodeId)
tbContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", tbContractCodeId, "token_bridge", tbInstantiateMsg, guardians)
fmt.Println("Token bridge contract address: ", tbContractAddr)
helpers.SubmitAllowlistInstantiateContract(t, ctx, wormchain, "faucet", wormchain.Config(), tbContractAddr, wrappedAssetCodeId, guardians)
// Store a new version of the token bridge to upgrade to
tbNewCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/shutdown_token_bridge.wasm", guardians)
// Submit contract upgrade
err = cw_wormhole.SubmitContractUpgrade(t, ctx, guardians, wormchain, tbContractAddr, tbNewCodeId)
require.NoError(t, err)
// -----------------------------------
// Registering a new chain - should pass
tbRegisterChainMsg := helpers.TbRegisterChainMsg(t, ExternalChainId, ExternalChainEmitterAddr, guardians)
_, err = wormchain.ExecuteContract(ctx, "faucet", tbContractAddr, string(tbRegisterChainMsg))
require.NoError(t, err)
// -----------------------------------
// Registering a new token - should fail
tbRegisterForeignAssetMsg := helpers.TbRegisterForeignAsset(t, Asset1ContractAddr, Asset1ChainID, ExternalChainEmitterAddr, Asset1Decimals, Asset1Symbol, Asset1Name, guardians)
_, err = wormchain.ExecuteContract(ctx, "faucet", tbContractAddr, string(tbRegisterForeignAssetMsg))
require.Error(t, err)
require.ErrorContains(t, err, "InvalidVAAAction")
// -----------------------------------
// Upgrade contract back to original contract id - should pass
err = cw_wormhole.SubmitContractUpgrade(t, ctx, guardians, wormchain, tbContractAddr, tbContractCodeId)
require.NoError(t, err)
// -----------------------------------
// Setup chains in "full" mode in preparation for transfer vaas
// Now register a new token - should pass on original contract
tbRegisterForeignAssetMsg = helpers.TbRegisterForeignAsset(t, Asset1ContractAddr, Asset1ChainID, ExternalChainEmitterAddr, Asset1Decimals, Asset1Symbol, Asset1Name, guardians)
_, err = wormchain.ExecuteContract(ctx, "faucet", tbContractAddr, string(tbRegisterForeignAssetMsg))
require.NoError(t, err)
// Store ibc translator contract
ibcTranslatorCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/ibc_translator.wasm", guardians)
fmt.Println("Ibc translator code id: ", ibcTranslatorCodeId)
// Instantiate ibc translator contract
ibcTranslatorInstantiateMsg := helpers.IbcTranslatorContractInstantiateMsg(t, tbContractAddr)
ibcTranslatorContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", ibcTranslatorCodeId, "ibc_translator", ibcTranslatorInstantiateMsg, guardians)
fmt.Println("Ibc translator contract address: ", ibcTranslatorContractAddr)
helpers.SetMiddlewareContract(t, ctx, wormchain, "faucet", wormchain.Config(), ibcTranslatorContractAddr, guardians)
// Allowlist worm/osmo chain id / channel
wormOsmoAllowlistMsg := helpers.SubmitUpdateChainToChannelMapMsg(t, OsmoChainID, wormToOsmoChannel.ChannelID, guardians)
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, wormOsmoAllowlistMsg)
require.NoError(t, err)
// Allowlist worm/gaia chain id / channel
wormGaiaAllowlistMsg := helpers.SubmitUpdateChainToChannelMapMsg(t, GaiaChainID, wormToGaiaChannel.ChannelID, guardians)
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, wormGaiaAllowlistMsg)
require.NoError(t, err)
ibcHooksCodeId, err := osmosis.StoreContract(ctx, osmoUser1.KeyName, "./contracts/ibc_hooks.wasm")
require.NoError(t, err)
fmt.Println("IBC hooks code id: ", ibcHooksCodeId)
ibcHooksContractAddr, err := osmosis.InstantiateContract(ctx, osmoUser1.KeyName, ibcHooksCodeId, "{}", true)
require.NoError(t, err)
fmt.Println("IBC hooks contract addr: ", ibcHooksContractAddr)
// -----------------------------------
// Upgrade contract to shutdown contract
err = cw_wormhole.SubmitContractUpgrade(t, ctx, guardians, wormchain, tbContractAddr, tbNewCodeId)
require.NoError(t, err)
// -----------------------------------
// Send transfer vaas - all should fail
// Create and process a simple ibc payload3: Transfers 10.000_018 of asset1 from external chain through wormchain to gaia user
simplePayload := helpers.CreateGatewayIbcTokenBridgePayloadTransfer(t, GaiaChainID, gaiaUser.Bech32Address(gaia.Config().Bech32Prefix), 0, 1)
externalSender := []byte{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}
payload3 := helpers.CreatePayload3(wormchain.Config(), uint64(AmountExternalToGaiaUser1), Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, simplePayload)
completeTransferAndConvertMsg := helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
require.Error(t, err)
require.ErrorContains(t, err, "Invalid during shutdown mode")
// Create and process a simple ibc payload3: Transfers 1.000_001 of asset1 from external chain through wormchain to osmo user1
simplePayload = helpers.CreateGatewayIbcTokenBridgePayloadTransfer(t, OsmoChainID, osmoUser1.Bech32Address(osmosis.Config().Bech32Prefix), 0, 1)
payload3 = helpers.CreatePayload3(wormchain.Config(), uint64(AmountExternalToOsmoUser1), Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, simplePayload)
completeTransferAndConvertMsg = helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
require.Error(t, err)
require.ErrorContains(t, err, "Invalid during shutdown mode")
// Create and process a contract controlled ibc payload3
// Transfers 1.000_002 of asset1 from external chain through wormchain to ibc hooks contract addr
// IBC hooks is used to route the contract controlled payload to a test contract which forwards tokens to osmo user2
ibcHooksPayload := helpers.CreateIbcHooksMsg(t, ibcHooksContractAddr, osmoUser2.Bech32Address(osmosis.Config().Bech32Prefix))
contractControlledPayload := helpers.CreateGatewayIbcTokenBridgePayloadTransferWithPayload(t, OsmoChainID, ibcHooksContractAddr, ibcHooksPayload, 1)
payload3 = helpers.CreatePayload3(wormchain.Config(), uint64(AmountExternalToOsmoUser2), Asset1ContractAddr, Asset1ChainID, ibcTranslatorContractAddr, uint16(vaa.ChainIDWormchain), externalSender, contractControlledPayload)
completeTransferAndConvertMsg = helpers.IbcTranslatorCompleteTransferAndConvertMsg(t, ExternalChainId, ExternalChainEmitterAddr, payload3, guardians)
_, err = wormchain.ExecuteContract(ctx, "faucet", ibcTranslatorContractAddr, completeTransferAndConvertMsg)
require.Error(t, err)
require.ErrorContains(t, err, "Invalid during shutdown mode")
}