wormchain: pulled in the pre-release cw_wormhole ict/integration test
This commit is contained in:
parent
42c5c141b0
commit
a7b06d6660
|
@ -30,6 +30,7 @@ jobs:
|
||||||
- "ictest-upgrade"
|
- "ictest-upgrade"
|
||||||
- "ictest-wormchain"
|
- "ictest-wormchain"
|
||||||
- "ictest-ibc-receiver"
|
- "ictest-ibc-receiver"
|
||||||
|
- "ictest-cw-wormhole"
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
|
@ -105,4 +105,7 @@ ictest-wormchain: rm-testcache
|
||||||
ictest-ibc-receiver: rm-testcache
|
ictest-ibc-receiver: rm-testcache
|
||||||
cd interchaintest && go test -race -v -run ^TestIbcReceiver ./...
|
cd interchaintest && go test -race -v -run ^TestIbcReceiver ./...
|
||||||
|
|
||||||
.PHONY: ictest-cancel-upgrade ictest-malformed-payload ictest-upgrade-failure ictest-upgrade ictest-wormchain ictest-ibc-receiver
|
ictest-cw-wormhole: rm-testcache
|
||||||
|
cd interchaintest && go test -race -v -run ^TestCWWormhole ./...
|
||||||
|
|
||||||
|
.PHONY: ictest-cancel-upgrade ictest-malformed-payload ictest-upgrade-failure ictest-upgrade ictest-wormchain ictest-ibc-receiver ictest-cw-wormhole
|
Binary file not shown.
|
@ -0,0 +1,492 @@
|
||||||
|
package ictest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/docker/client"
|
||||||
|
"github.com/strangelove-ventures/interchaintest/v4"
|
||||||
|
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
|
||||||
|
"github.com/strangelove-ventures/interchaintest/v4/ibc"
|
||||||
|
"github.com/strangelove-ventures/interchaintest/v4/testutil"
|
||||||
|
"go.uber.org/zap/zaptest"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
func createSingleNodeCluster(t *testing.T, wormchainVersion string, guardians guardians.ValSet) ibc.Chain {
|
||||||
|
numWormchainVals := len(guardians.Vals)
|
||||||
|
numFullNodes := 0
|
||||||
|
|
||||||
|
wormchainConfig.Images[0].Version = wormchainVersion
|
||||||
|
wormchainConfig.ModifyGenesis = ModifyGenesis(votingPeriod, maxDepositPeriod, guardians, true)
|
||||||
|
|
||||||
|
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
|
||||||
|
{
|
||||||
|
ChainName: "wormchain",
|
||||||
|
ChainConfig: wormchainConfig,
|
||||||
|
NumValidators: &numWormchainVals,
|
||||||
|
NumFullNodes: &numFullNodes,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Get chains from the chain factory
|
||||||
|
chains, err := cf.Chains(t.Name())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return chains[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildSingleNodeInterchain(t *testing.T, chain ibc.Chain) (context.Context, *client.Client) {
|
||||||
|
ic := interchaintest.NewInterchain()
|
||||||
|
ic.AddChain(chain)
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
client, network := interchaintest.DockerSetup(t)
|
||||||
|
|
||||||
|
err := ic.Build(ctx, nil, interchaintest.InterchainBuildOptions{
|
||||||
|
TestName: t.Name(),
|
||||||
|
Client: client,
|
||||||
|
NetworkID: network,
|
||||||
|
SkipPathCreation: true,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_ = ic.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
return ctx, client
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCWWormholeQueries tests the query functions of the cw_wormhole contract
|
||||||
|
func TestCWWormholeQueries(t *testing.T) {
|
||||||
|
// Base setup
|
||||||
|
numVals := 1
|
||||||
|
guardians := guardians.CreateValSet(t, numVals)
|
||||||
|
|
||||||
|
chain := createSingleNodeCluster(t, "v2.24.2", *guardians)
|
||||||
|
ctx, _ := buildSingleNodeInterchain(t, chain)
|
||||||
|
|
||||||
|
wormchain := chain.(*cosmos.CosmosChain)
|
||||||
|
|
||||||
|
// Instantiate the cw_wormhole contract
|
||||||
|
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, vaa.ChainIDWormchain, guardians)
|
||||||
|
wormchainCoreContractInfo := helpers.StoreAndInstantiateWormholeContract(t, ctx, wormchain, "faucet", "./contracts/cw_wormhole.wasm", "wormhole_core", coreInstantiateMsg, guardians)
|
||||||
|
contractAddr := wormchainCoreContractInfo.Address
|
||||||
|
|
||||||
|
// Query the contract to check that the guardian set is correct
|
||||||
|
var guardianSetResp cw_wormhole.GuardianSetQueryResponse
|
||||||
|
err := wormchain.QueryContract(ctx, contractAddr, cw_wormhole.QueryMsg{
|
||||||
|
GuardianSetInfo: &cw_wormhole.QueryMsg_GuardianSetInfo{},
|
||||||
|
}, &guardianSetResp)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, numVals, len(guardianSetResp.Data.Addresses), "guardian set should have the correct number of guardians")
|
||||||
|
// Check that all the guardians from the query are the ones in the running valset
|
||||||
|
for _, val := range guardians.Vals {
|
||||||
|
found := false
|
||||||
|
for _, guardian := range guardianSetResp.Data.Addresses {
|
||||||
|
decoded, err := base64.StdEncoding.DecodeString(string(guardian.Bytes))
|
||||||
|
require.NoError(t, err)
|
||||||
|
guardianDecodedBytes := []byte(decoded)
|
||||||
|
if bytes.Equal(val.Addr, guardianDecodedBytes) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.True(t, found, "guardian not found in guardian set")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the core contract fee is set to 0uworm
|
||||||
|
var stateResp cw_wormhole.GetStateQueryResponse
|
||||||
|
err = wormchain.QueryContract(ctx, contractAddr, cw_wormhole.QueryMsg{
|
||||||
|
GetState: &cw_wormhole.QueryMsg_GetState{},
|
||||||
|
}, &stateResp)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "uworm", stateResp.Data.Fee.Denom, "core contract fee should be in uworm")
|
||||||
|
require.Equal(t, cw_wormhole.Uint128("0"), stateResp.Data.Fee.Amount, "core contract fee should be 0")
|
||||||
|
|
||||||
|
// Check that hex addresse are able to be queried
|
||||||
|
var hexAddressResp cw_wormhole.QueryAddressHexQueryResponse
|
||||||
|
err = wormchain.QueryContract(ctx, contractAddr, cw_wormhole.QueryMsg{
|
||||||
|
QueryAddressHex: &cw_wormhole.QueryMsg_QueryAddressHex{
|
||||||
|
Address: "wormhole14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9srrg465",
|
||||||
|
},
|
||||||
|
}, &hexAddressResp)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.IsType(t, "", hexAddressResp.Data.Hex, "hex address should be a string")
|
||||||
|
|
||||||
|
// Check that the core contract can properly verify a VAA
|
||||||
|
guardianSetIndex := helpers.QueryConsensusGuardianSetIndex(t, wormchain, ctx)
|
||||||
|
vaa := helpers.GenerateGovernanceVaa(uint32(guardianSetIndex), guardians, []byte("test"))
|
||||||
|
vaaBz, err := vaa.Marshal()
|
||||||
|
require.NoError(t, err)
|
||||||
|
encodedVaa := base64.StdEncoding.EncodeToString(vaaBz)
|
||||||
|
vaaBinary := cw_wormhole.Binary(encodedVaa)
|
||||||
|
|
||||||
|
currentWormchainBlock, err := wormchain.Height(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var parsedVaaResponse cw_wormhole.VerifyVAAQueryResponse
|
||||||
|
err = wormchain.QueryContract(ctx, contractAddr, cw_wormhole.QueryMsg{
|
||||||
|
VerifyVaa: &cw_wormhole.QueryMsg_VerifyVAA{
|
||||||
|
BlockTime: int(currentWormchainBlock),
|
||||||
|
Vaa: vaaBinary,
|
||||||
|
},
|
||||||
|
}, &parsedVaaResponse)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, parsedVaaResponse.Data, "VAA should be verified")
|
||||||
|
require.Equal(t, "test", string(parsedVaaResponse.Data.Payload), "VAA payload should be what we passed in")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCWWormholePostMessage tests the PostMessage function of the cw_wormhole contract
|
||||||
|
func TestCWWormholePostMessage(t *testing.T) {
|
||||||
|
numVals := 1
|
||||||
|
guardians := guardians.CreateValSet(t, numVals)
|
||||||
|
chain := createSingleNodeCluster(t, "v2.24.2", *guardians)
|
||||||
|
ctx, _ := buildSingleNodeInterchain(t, chain)
|
||||||
|
wormchain := chain.(*cosmos.CosmosChain)
|
||||||
|
|
||||||
|
// Instantiate contract
|
||||||
|
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, vaa.ChainIDWormchain, guardians)
|
||||||
|
contractInfo := helpers.StoreAndInstantiateWormholeContract(t, ctx, wormchain, "faucet", "./contracts/cw_wormhole.wasm", "wormhole_core", coreInstantiateMsg, guardians)
|
||||||
|
contractAddr := contractInfo.Address
|
||||||
|
|
||||||
|
// Create message and encode to base64
|
||||||
|
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
|
||||||
|
txHash, err := wormchain.ExecuteContract(ctx, "faucet", contractAddr, string(executeMsg))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Wait 2 blocks
|
||||||
|
err = testutil.WaitForBlocks(ctx, 2, wormchain)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Query and parse the response
|
||||||
|
txResult, _, err := wormchain.Validators[0].ExecQuery(ctx, "tx", txHash)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var txResponse cw_wormhole.TxResponse
|
||||||
|
err = json.Unmarshal(txResult, &txResponse)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Verify event attributes
|
||||||
|
cw_wormhole.VerifyEventAttributes(t, &txResponse, map[string]string{
|
||||||
|
"_contract_address": contractAddr,
|
||||||
|
"message.message": hex.EncodeToString(message),
|
||||||
|
"message.nonce": "1",
|
||||||
|
"message.sequence": "0",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCWWormholeUpdateGuardianSet tests the UpdateGuardianSet function of the cw_wormhole contract
|
||||||
|
func TestCWWormholeUpdateGuardianSet(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)
|
||||||
|
wormchain := chain.(*cosmos.CosmosChain)
|
||||||
|
|
||||||
|
// Deploy contract
|
||||||
|
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, vaa.ChainIDWormchain, oldGuardians)
|
||||||
|
contractInfo := helpers.StoreAndInstantiateWormholeContract(t, ctx, wormchain, "faucet", "./contracts/cw_wormhole.wasm", "wormhole_core", coreInstantiateMsg, oldGuardians)
|
||||||
|
contractAddr := contractInfo.Address
|
||||||
|
|
||||||
|
// Get initial guardian set index
|
||||||
|
initialIndex := int(helpers.QueryConsensusGuardianSetIndex(t, wormchain, ctx))
|
||||||
|
signingGuardians := guardians.CreateValSet(t, numVals+1)
|
||||||
|
|
||||||
|
t.Run("successful update", func(t *testing.T) {
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("invalid guardian set index", func(t *testing.T) {
|
||||||
|
// Try to update with non-sequential index
|
||||||
|
newGuardians := guardians.CreateValSet(t, numVals+1)
|
||||||
|
err := cw_wormhole.SubmitGuardianSetUpdate(t, ctx, wormchain, contractAddr, newGuardians, uint32(initialIndex+3), signingGuardians)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// Try to update with same index
|
||||||
|
err = cw_wormhole.SubmitGuardianSetUpdate(t, ctx, wormchain, contractAddr, newGuardians, uint32(initialIndex), signingGuardians)
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("empty guardian set", func(t *testing.T) {
|
||||||
|
emptyGuardians := guardians.CreateValSet(t, 0)
|
||||||
|
err := cw_wormhole.SubmitGuardianSetUpdate(t, ctx, wormchain, contractAddr, emptyGuardians, uint32(initialIndex+1), signingGuardians)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "GuardianSignatureError")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("duplicate guardians", func(t *testing.T) {
|
||||||
|
// Create guardian set with duplicate addresses
|
||||||
|
dupGuardians := guardians.CreateValSet(t, 1)
|
||||||
|
dupGuardians.Vals = append(dupGuardians.Vals, dupGuardians.Vals[0])
|
||||||
|
dupGuardians.Total = 2
|
||||||
|
|
||||||
|
err := cw_wormhole.SubmitGuardianSetUpdate(t, ctx, wormchain, contractAddr, dupGuardians, uint32(initialIndex+1), signingGuardians)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "GuardianSignatureError")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("wrong signing guardian set", func(t *testing.T) {
|
||||||
|
// Create new guardians and try to use them to sign the update
|
||||||
|
wrongSigners := guardians.CreateValSet(t, numVals)
|
||||||
|
newGuardians := guardians.CreateValSet(t, numVals+1)
|
||||||
|
|
||||||
|
err := cw_wormhole.SubmitGuardianSetUpdate(t, ctx, wormchain, contractAddr, newGuardians, uint32(initialIndex+1), wrongSigners)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "governance VAAs must be signed by the current guardian set")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("insufficient signatures", func(t *testing.T) {
|
||||||
|
// Create a guardian set with only one signer (below quorum)
|
||||||
|
insufficientSigners := guardians.CreateValSet(t, 1)
|
||||||
|
newGuardians := guardians.CreateValSet(t, numVals+1)
|
||||||
|
|
||||||
|
err := cw_wormhole.SubmitGuardianSetUpdate(t, ctx, wormchain, contractAddr, newGuardians, uint32(initialIndex+1), insufficientSigners)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "governance VAAs must be signed by the current guardian set")
|
||||||
|
|
||||||
|
// too many signatures
|
||||||
|
insufficientSigners = guardians.CreateValSet(t, numVals+2)
|
||||||
|
err = cw_wormhole.SubmitGuardianSetUpdate(t, ctx, wormchain, contractAddr, newGuardians, uint32(initialIndex+1), insufficientSigners)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "GuardianSignatureError")
|
||||||
|
})
|
||||||
|
|
||||||
|
// Verify signing validators did not change
|
||||||
|
cw_wormhole.VerifyGuardianSet(t, ctx, wormchain, contractAddr, signingGuardians, initialIndex+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCWWormholeContractUpgrade tests the SubmitContractUpgrade function of the cw_wormhole contract
|
||||||
|
func TestCWWormholeContractUpgrade(t *testing.T) {
|
||||||
|
// Setup chain and contract
|
||||||
|
numVals := 1
|
||||||
|
guardians := guardians.CreateValSet(t, numVals)
|
||||||
|
chains := CreateChains(t, "v2.24.2", *guardians)
|
||||||
|
ctx, _, _, _ := BuildInterchain(t, chains)
|
||||||
|
|
||||||
|
// Chains
|
||||||
|
wormchain := chains[0].(*cosmos.CosmosChain)
|
||||||
|
|
||||||
|
// Deploy contract to wormhole
|
||||||
|
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, vaa.ChainIDWormchain, guardians)
|
||||||
|
contractInfo := helpers.StoreAndInstantiateWormholeContract(t, ctx, wormchain, "faucet", "./contracts/cw_wormhole.wasm", "wormhole_core", coreInstantiateMsg, guardians)
|
||||||
|
wormContractAddr := contractInfo.Address
|
||||||
|
|
||||||
|
// Store a new version of the contract to upgrade to
|
||||||
|
wormNewCodeId := helpers.StoreContract(t, ctx, wormchain, "faucet", "./contracts/cw_wormhole.wasm", guardians)
|
||||||
|
|
||||||
|
t.Run("successful upgrade", func(t *testing.T) {
|
||||||
|
err := cw_wormhole.SubmitContractUpgrade(t, ctx, guardians, wormchain, wormContractAddr, wormNewCodeId)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
contractInfo = helpers.QueryContractInfo(t, wormchain, ctx, wormContractAddr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, wormNewCodeId, contractInfo.ContractInfo.CodeID)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("invalid code id", func(t *testing.T) {
|
||||||
|
err := cw_wormhole.SubmitContractUpgrade(t, ctx, guardians, wormchain, wormContractAddr, "999999")
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
// VAA payload to upgrade contract is not allowed on Wormchain, must use the wormhole module
|
||||||
|
t.Run("upgrade wormhole contract with vaa: fails - use x/wormhole", func(t *testing.T) {
|
||||||
|
// Submit VAA
|
||||||
|
err := cw_wormhole.SubmitContractUpgradeWithVaa(t, ctx, guardians, 0, vaa.ChainIDWormchain, wormchain, wormContractAddr, wormNewCodeId, "faucet")
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "must use x/wormhole")
|
||||||
|
})
|
||||||
|
|
||||||
|
// Test osmo chain
|
||||||
|
osmo := chains[2].(*cosmos.CosmosChain)
|
||||||
|
users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), 10_000_000_000, osmo)
|
||||||
|
osmoUser := users[0]
|
||||||
|
|
||||||
|
// Deploy contract to osmo
|
||||||
|
osmoCodeId, err := osmo.StoreContract(ctx, osmoUser.KeyName, "./contracts/cw_wormhole.wasm")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
instantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, vaa.ChainIDOsmosis, guardians)
|
||||||
|
|
||||||
|
osmoContractAddr, err := osmo.InstantiateContract(ctx, osmoUser.KeyName, osmoCodeId, instantiateMsg, false, "--admin", osmoUser.Bech32Address("osmo"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Update admin to contract addr
|
||||||
|
_, err = osmo.GetFullNode().ExecTx(ctx, osmoUser.KeyName, "wasm", "set-contract-admin", osmoContractAddr, osmoContractAddr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = testutil.WaitForBlocks(ctx, 2, osmo)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Verify new admin is contract
|
||||||
|
contractInfo = helpers.QueryContractInfo(t, osmo, ctx, osmoContractAddr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, osmoContractAddr, contractInfo.ContractInfo.Admin)
|
||||||
|
|
||||||
|
// Store a new version of the contract to upgrade to
|
||||||
|
osmoNewCodeId, err := osmo.StoreContract(ctx, osmoUser.KeyName, "./contracts/cw_wormhole.wasm")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Run("migrate osmosis via payload", func(t *testing.T) {
|
||||||
|
// Submit VAA
|
||||||
|
err := cw_wormhole.SubmitContractUpgradeWithVaa(t, ctx, guardians, 0, vaa.ChainIDOsmosis, osmo, osmoContractAddr, osmoNewCodeId, osmoUser.KeyName)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
contractInfo := helpers.QueryContractInfo(t, osmo, ctx, osmoContractAddr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, osmoNewCodeId, contractInfo.ContractInfo.CodeID)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCWWormholeSetFee tests the SetFee function of the cw_wormhole contract
|
||||||
|
func TestCWWormholeSetFee(t *testing.T) {
|
||||||
|
// Setup chain and contract
|
||||||
|
numVals := 1
|
||||||
|
guardians := guardians.CreateValSet(t, numVals)
|
||||||
|
chain := createSingleNodeCluster(t, "v2.24.2", *guardians)
|
||||||
|
ctx, _ := buildSingleNodeInterchain(t, chain)
|
||||||
|
wormchain := chain.(*cosmos.CosmosChain)
|
||||||
|
|
||||||
|
// Deploy contract
|
||||||
|
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, vaa.ChainIDWormchain, guardians)
|
||||||
|
contractInfo := helpers.StoreAndInstantiateWormholeContract(t, ctx, wormchain, "faucet", "./contracts/cw_wormhole.wasm", "wormhole_core", coreInstantiateMsg, guardians)
|
||||||
|
contractAddr := contractInfo.Address
|
||||||
|
|
||||||
|
// wrapper around helper function for cleaner test code
|
||||||
|
submitFeeUpdate := func(amount string, replay bool) (*cw_wormhole.TxResponse, error) {
|
||||||
|
return cw_wormhole.SubmitFeeUpdate(t, ctx, guardians, wormchain, contractAddr, amount, replay)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("successful fee update", func(t *testing.T) {
|
||||||
|
txResponse, err := submitFeeUpdate("1000000", true) // Set fee to 1 WORM (1000000 uworm)
|
||||||
|
require.NoError(t, err)
|
||||||
|
cw_wormhole.VerifyEventAttributes(t, txResponse, map[string]string{
|
||||||
|
"action": "fee_change",
|
||||||
|
"new_fee.amount": "1000000",
|
||||||
|
"new_fee.denom": "uworm",
|
||||||
|
})
|
||||||
|
cw_wormhole.VerifyFee(t, ctx, wormchain, contractAddr, "1000000")
|
||||||
|
|
||||||
|
// post a message with fee under the new fee
|
||||||
|
err = cw_wormhole.PostMessageWithFee(t, ctx, wormchain, contractAddr, "message1", 999999)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "FeeTooLow")
|
||||||
|
|
||||||
|
// post a message with fee equal to the new fee
|
||||||
|
err = cw_wormhole.PostMessageWithFee(t, ctx, wormchain, contractAddr, "message2", 1000000)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// post a message with fee above the new fee
|
||||||
|
err = cw_wormhole.PostMessageWithFee(t, ctx, wormchain, contractAddr, "message3", 1000001)
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("zero fee", func(t *testing.T) {
|
||||||
|
txResponse, err := submitFeeUpdate("0", false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
cw_wormhole.VerifyEventAttributes(t, txResponse, map[string]string{
|
||||||
|
"action": "fee_change",
|
||||||
|
"new_fee.amount": "0",
|
||||||
|
"new_fee.denom": "uworm",
|
||||||
|
})
|
||||||
|
cw_wormhole.VerifyFee(t, ctx, wormchain, contractAddr, "0")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("very large fee", func(t *testing.T) {
|
||||||
|
txResponse, err := submitFeeUpdate("1000000000000", false) // 1M WORM
|
||||||
|
require.NoError(t, err)
|
||||||
|
cw_wormhole.VerifyEventAttributes(t, txResponse, map[string]string{
|
||||||
|
"action": "fee_change",
|
||||||
|
"new_fee.amount": "1000000000000",
|
||||||
|
"new_fee.denom": "uworm",
|
||||||
|
})
|
||||||
|
cw_wormhole.VerifyFee(t, ctx, wormchain, contractAddr, "1000000000000")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCWWormholeTransferFees tests transferring the accumulated fees to the core contract
|
||||||
|
func TestCWWormholeTransferFees(t *testing.T) {
|
||||||
|
// Setup chain and contract
|
||||||
|
numVals := 1
|
||||||
|
guardians := guardians.CreateValSet(t, numVals)
|
||||||
|
chain := createSingleNodeCluster(t, "v2.24.2", *guardians)
|
||||||
|
ctx, _ := buildSingleNodeInterchain(t, chain)
|
||||||
|
wormchain := chain.(*cosmos.CosmosChain)
|
||||||
|
|
||||||
|
// Deploy contract
|
||||||
|
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, vaa.ChainIDWormchain, guardians)
|
||||||
|
contractInfo := helpers.StoreAndInstantiateWormholeContract(t, ctx, wormchain, "faucet", "./contracts/cw_wormhole.wasm", "wormhole_core", coreInstantiateMsg, guardians)
|
||||||
|
contractAddr := contractInfo.Address
|
||||||
|
|
||||||
|
users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), 1, wormchain)
|
||||||
|
user := users[0]
|
||||||
|
userAddr := user.Bech32Address("wormhole")
|
||||||
|
|
||||||
|
t.Run("successful fee transfer", func(t *testing.T) {
|
||||||
|
// Set fee to 1000000 uworm
|
||||||
|
_, err := cw_wormhole.SubmitFeeUpdate(t, ctx, guardians, wormchain, contractAddr, "1000000", false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Post some messages with fees to build up balance
|
||||||
|
err = cw_wormhole.PostMessageWithFee(t, ctx, wormchain, contractAddr, "message1", 1000000)
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = cw_wormhole.PostMessageWithFee(t, ctx, wormchain, contractAddr, "message2", 1000000)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Get recipient's initial balance
|
||||||
|
initialBalance, err := cw_wormhole.GetUwormBalance(t, ctx, wormchain, userAddr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Transfer 1500000 uworm
|
||||||
|
_, err = cw_wormhole.SubmitTransferFee(t, ctx, guardians, wormchain, contractAddr, []byte(user.Address), "1500000", true)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Verify successful transfer
|
||||||
|
finalBalance, err := cw_wormhole.GetUwormBalance(t, ctx, wormchain, userAddr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, initialBalance+1500000, finalBalance)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("transfer more than balance", func(t *testing.T) {
|
||||||
|
_, err := cw_wormhole.SubmitTransferFee(t, ctx, guardians, wormchain, contractAddr, []byte(user.Address), "10000000000", false)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "insufficient funds")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("invalid recipient", func(t *testing.T) {
|
||||||
|
_, err := cw_wormhole.SubmitTransferFee(t, ctx, guardians, wormchain, contractAddr, []byte("invalid"), "1000000", false)
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("zero amount - invalid coins", func(t *testing.T) {
|
||||||
|
_, err := cw_wormhole.SubmitTransferFee(t, ctx, guardians, wormchain, contractAddr, []byte(user.Address), "0", false)
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
/* Code generated by github.com/srdtrk/go-codegen, DO NOT EDIT. */
|
||||||
|
package cw_wormhole
|
||||||
|
|
||||||
|
// The instantiation parameters of the core bridge contract. See [`crate::state::ConfigInfo`] for more details on what these fields mean.
|
||||||
|
type InstantiateMsg struct {
|
||||||
|
FeeDenom string `json:"fee_denom"`
|
||||||
|
GovAddress Binary `json:"gov_address"`
|
||||||
|
GovChain int `json:"gov_chain"`
|
||||||
|
GuardianSetExpirity int `json:"guardian_set_expirity"`
|
||||||
|
// Guardian set to initialise the contract with.
|
||||||
|
InitialGuardianSet GuardianSetInfo `json:"initial_guardian_set"`
|
||||||
|
ChainId int `json:"chain_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExecuteMsg struct {
|
||||||
|
SubmitVaa *ExecuteMsg_SubmitVAA `json:"submit_v_a_a,omitempty"`
|
||||||
|
PostMessage *ExecuteMsg_PostMessage `json:"post_message,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type QueryMsg struct {
|
||||||
|
GuardianSetInfo *QueryMsg_GuardianSetInfo `json:"guardian_set_info,omitempty"`
|
||||||
|
VerifyVaa *QueryMsg_VerifyVAA `json:"verify_v_a_a,omitempty"`
|
||||||
|
GetState *QueryMsg_GetState `json:"get_state,omitempty"`
|
||||||
|
QueryAddressHex *QueryMsg_QueryAddressHex `json:"query_address_hex,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExecuteMsg_PostMessage struct {
|
||||||
|
Message Binary `json:"message"`
|
||||||
|
Nonce int `json:"nonce"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GuardianSetInfoResponse struct {
|
||||||
|
Addresses []GuardianAddress `json:"addresses"`
|
||||||
|
GuardianSetIndex int `json:"guardian_set_index"`
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
Use `from` to create instances of this and `u128` to get the value out:
|
||||||
|
|
||||||
|
``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);
|
||||||
|
|
||||||
|
let b = Uint128::from(42u64); assert_eq!(b.u128(), 42);
|
||||||
|
|
||||||
|
let c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```
|
||||||
|
*/
|
||||||
|
type Uint128 string
|
||||||
|
|
||||||
|
type GetStateResponse struct {
|
||||||
|
Fee Coin `json:"fee"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GuardianAddress struct {
|
||||||
|
Bytes Binary `json:"bytes"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type QueryMsg_GetState struct{}
|
||||||
|
|
||||||
|
type QueryMsg_QueryAddressHex struct {
|
||||||
|
Address string `json:"address"`
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Binary is a wrapper around Vec<u8> to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.
|
||||||
|
|
||||||
|
This is only needed as serde-json-{core,wasm} has a horrible encoding for Vec<u8>. See also <https://github.com/CosmWasm/cosmwasm/blob/main/docs/MESSAGE_TYPES.md>.
|
||||||
|
*/
|
||||||
|
type Binary string
|
||||||
|
|
||||||
|
type ExecuteMsg_SubmitVAA struct {
|
||||||
|
Vaa Binary `json:"vaa"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type QueryMsg_VerifyVAA struct {
|
||||||
|
BlockTime int `json:"block_time"`
|
||||||
|
Vaa Binary `json:"vaa"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ParsedVAA struct {
|
||||||
|
ConsistencyLevel int `json:"consistency_level"`
|
||||||
|
EmitterAddress []int `json:"emitter_address"`
|
||||||
|
Hash []int `json:"hash"`
|
||||||
|
LenSigners int `json:"len_signers"`
|
||||||
|
Timestamp int `json:"timestamp"`
|
||||||
|
Version int `json:"version"`
|
||||||
|
EmitterChain int `json:"emitter_chain"`
|
||||||
|
GuardianSetIndex int `json:"guardian_set_index"`
|
||||||
|
Nonce int `json:"nonce"`
|
||||||
|
Payload []byte `json:"payload"`
|
||||||
|
Sequence int `json:"sequence"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Coin struct {
|
||||||
|
Amount Uint128 `json:"amount"`
|
||||||
|
Denom string `json:"denom"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GuardianSetInfo struct {
|
||||||
|
Addresses []GuardianAddress `json:"addresses"`
|
||||||
|
ExpirationTime int `json:"expiration_time"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetAddressHexResponse struct {
|
||||||
|
Hex string `json:"hex"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type QueryMsg_GuardianSetInfo struct{}
|
|
@ -0,0 +1,408 @@
|
||||||
|
package cw_wormhole
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/json"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
|
||||||
|
"github.com/strangelove-ventures/interchaintest/v4/testutil"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||||
|
"github.com/wormhole-foundation/wormchain/interchaintest/helpers"
|
||||||
|
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GuardianSetQueryResponse struct {
|
||||||
|
Data GuardianSetInfoResponse `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type VerifyVAAQueryResponse struct {
|
||||||
|
Data ParsedVAA `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetStateQueryResponse struct {
|
||||||
|
Data GetStateResponse `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type QueryAddressHexQueryResponse struct {
|
||||||
|
Data GetAddressHexResponse `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom response type to handle string numbers
|
||||||
|
type TxResponse struct {
|
||||||
|
Code uint32 `json:"code"`
|
||||||
|
Logs sdk.ABCIMessageLogs `json:"logs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubmitGuardianSetUpdate submits a VAA to update the guardian set
|
||||||
|
func SubmitGuardianSetUpdate(
|
||||||
|
t *testing.T,
|
||||||
|
ctx context.Context,
|
||||||
|
wormchain *cosmos.CosmosChain,
|
||||||
|
contractAddr string,
|
||||||
|
newGuardians *guardians.ValSet,
|
||||||
|
newIndex uint32,
|
||||||
|
signingGuardians *guardians.ValSet,
|
||||||
|
) error {
|
||||||
|
// Create guardian set update payload
|
||||||
|
guardianKeys := make([]common.Address, len(newGuardians.Vals))
|
||||||
|
for i, g := range newGuardians.Vals {
|
||||||
|
copy(guardianKeys[i][:], g.Addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMsg := vaa.BodyGuardianSetUpdate{
|
||||||
|
Keys: guardianKeys,
|
||||||
|
NewIndex: newIndex,
|
||||||
|
}
|
||||||
|
|
||||||
|
payload, err := updateMsg.Serialize()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Generate and sign the governance VAA using the signing guardian set
|
||||||
|
guardianSetIndex := helpers.QueryConsensusGuardianSetIndex(t, wormchain, ctx)
|
||||||
|
govVaa := helpers.GenerateGovernanceVaa(uint32(guardianSetIndex), signingGuardians, payload)
|
||||||
|
vaaBz, err := govVaa.Marshal()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
encodedVaa := base64.StdEncoding.EncodeToString(vaaBz)
|
||||||
|
executeVAAPayload, err := json.Marshal(ExecuteMsg{
|
||||||
|
SubmitVaa: &ExecuteMsg_SubmitVAA{
|
||||||
|
Vaa: Binary(encodedVaa),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Submit VAA
|
||||||
|
_, err = wormchain.ExecuteContract(ctx, "faucet", contractAddr, string(executeVAAPayload))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for transaction
|
||||||
|
return testutil.WaitForBlocks(ctx, 2, wormchain)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyGuardianSet verifies the guardian set in the contract state
|
||||||
|
func VerifyGuardianSet(
|
||||||
|
t *testing.T,
|
||||||
|
ctx context.Context,
|
||||||
|
wormchain *cosmos.CosmosChain,
|
||||||
|
contractAddr string,
|
||||||
|
expectedGuardians *guardians.ValSet,
|
||||||
|
expectedIndex int,
|
||||||
|
) {
|
||||||
|
var guardianSetResp GuardianSetQueryResponse
|
||||||
|
err := wormchain.QueryContract(ctx, contractAddr, QueryMsg{
|
||||||
|
GuardianSetInfo: &QueryMsg_GuardianSetInfo{},
|
||||||
|
}, &guardianSetResp)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, len(expectedGuardians.Vals), len(guardianSetResp.Data.Addresses), "unexpected number of guardians")
|
||||||
|
require.Equal(t, expectedIndex, guardianSetResp.Data.GuardianSetIndex, "unexpected guardian set index")
|
||||||
|
|
||||||
|
for i, val := range expectedGuardians.Vals {
|
||||||
|
found := false
|
||||||
|
for _, guardian := range guardianSetResp.Data.Addresses {
|
||||||
|
decoded, err := base64.StdEncoding.DecodeString(string(guardian.Bytes))
|
||||||
|
require.NoError(t, err)
|
||||||
|
guardianDecodedBytes := []byte(decoded)
|
||||||
|
if bytes.Equal(val.Addr, guardianDecodedBytes) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.True(t, found, "guardian %d not found in guardian set", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubmitContractUpgrade submits a VAA to upgrade the contract code
|
||||||
|
func SubmitContractUpgrade(
|
||||||
|
t *testing.T,
|
||||||
|
ctx context.Context,
|
||||||
|
guardians *guardians.ValSet,
|
||||||
|
wormchain *cosmos.CosmosChain,
|
||||||
|
contractAddr string,
|
||||||
|
newCodeId string,
|
||||||
|
) error {
|
||||||
|
if err := helpers.MigrateContract(t, ctx, wormchain, "faucet", contractAddr, newCodeId, "{}", guardians); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for transaction
|
||||||
|
return testutil.WaitForBlocks(ctx, 2, wormchain)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SubmitContractUpgradeWithVaa(
|
||||||
|
t *testing.T,
|
||||||
|
ctx context.Context,
|
||||||
|
guardians *guardians.ValSet,
|
||||||
|
guardianSetIndex uint64,
|
||||||
|
vaaChainId vaa.ChainID,
|
||||||
|
chain *cosmos.CosmosChain,
|
||||||
|
contractAddr string,
|
||||||
|
newCodeId string,
|
||||||
|
keyName string,
|
||||||
|
) error {
|
||||||
|
// convert newCodeId to Uint256
|
||||||
|
var newCodeIdBz [32]byte
|
||||||
|
newCodeIdInt := new(big.Int)
|
||||||
|
newCodeIdInt.SetString(newCodeId, 10)
|
||||||
|
newCodeIdInt.FillBytes(newCodeIdBz[:])
|
||||||
|
|
||||||
|
// Create contract upgrade payload
|
||||||
|
updateMsg := vaa.BodyContractUpgrade{
|
||||||
|
ChainID: vaaChainId,
|
||||||
|
NewContract: vaa.Address(newCodeIdBz),
|
||||||
|
}
|
||||||
|
|
||||||
|
payload, err := updateMsg.Serialize()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Generate and sign the governance VAA
|
||||||
|
govVaa := helpers.GenerateGovernanceVaa(uint32(guardianSetIndex), guardians, payload)
|
||||||
|
vaaBz, err := govVaa.Marshal()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
encodedVaa := base64.StdEncoding.EncodeToString(vaaBz)
|
||||||
|
executeVAAPayload, err := json.Marshal(ExecuteMsg{
|
||||||
|
SubmitVaa: &ExecuteMsg_SubmitVAA{
|
||||||
|
Vaa: Binary(encodedVaa),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Submit VAA
|
||||||
|
_, err = chain.ExecuteContract(ctx, keyName, contractAddr, string(executeVAAPayload))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubmitFeeUpdate submits a VAA to update the fee amount
|
||||||
|
func SubmitFeeUpdate(
|
||||||
|
t *testing.T,
|
||||||
|
ctx context.Context,
|
||||||
|
guardians *guardians.ValSet,
|
||||||
|
wormchain *cosmos.CosmosChain,
|
||||||
|
contractAddr string,
|
||||||
|
amount string,
|
||||||
|
replay bool,
|
||||||
|
) (*TxResponse, error) {
|
||||||
|
// Get current guardian set index
|
||||||
|
guardianSetIndex := helpers.QueryConsensusGuardianSetIndex(t, wormchain, ctx)
|
||||||
|
|
||||||
|
// Create a fixed 32-byte array for the fee amount
|
||||||
|
var amountBytes [32]byte
|
||||||
|
amountInt := new(big.Int)
|
||||||
|
amountInt.SetString(amount, 10)
|
||||||
|
amountInt.FillBytes(amountBytes[:])
|
||||||
|
|
||||||
|
// Create governance VAA payload
|
||||||
|
// [32 bytes] Core Module
|
||||||
|
// [1 byte] Action (3 for set fee)
|
||||||
|
// [2 bytes] ChainID (0 for universal)
|
||||||
|
// [32 bytes] Amount
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
buf.Write(vaa.CoreModule)
|
||||||
|
vaa.MustWrite(buf, binary.BigEndian, vaa.ActionCoreSetMessageFee)
|
||||||
|
vaa.MustWrite(buf, binary.BigEndian, uint16(0)) // ChainID 0 for universal
|
||||||
|
buf.Write(amountBytes[:])
|
||||||
|
|
||||||
|
// Generate and sign governance VAA
|
||||||
|
govVaa := helpers.GenerateGovernanceVaa(uint32(guardianSetIndex), guardians, buf.Bytes())
|
||||||
|
vaaBz, err := govVaa.Marshal()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Rest of the function remains the same...
|
||||||
|
encodedVaa := base64.StdEncoding.EncodeToString(vaaBz)
|
||||||
|
executeVAAPayload, err := json.Marshal(ExecuteMsg{
|
||||||
|
SubmitVaa: &ExecuteMsg_SubmitVAA{
|
||||||
|
Vaa: Binary(encodedVaa),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Submit VAA
|
||||||
|
txHash, err := wormchain.ExecuteContract(ctx, "faucet", contractAddr, string(executeVAAPayload))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for transaction
|
||||||
|
err = testutil.WaitForBlocks(ctx, 2, wormchain)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Replay the transaction
|
||||||
|
if replay {
|
||||||
|
_, err = wormchain.ExecuteContract(ctx, "faucet", contractAddr, string(executeVAAPayload))
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "VaaAlreadyExecuted")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query transaction result
|
||||||
|
txResult, _, err := wormchain.Validators[0].ExecQuery(ctx, "tx", txHash)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Parse response
|
||||||
|
var txResponse TxResponse
|
||||||
|
err = json.Unmarshal(txResult, &txResponse)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return &txResponse, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyFee verifies the fee amount in the contract state
|
||||||
|
func VerifyFee(
|
||||||
|
t *testing.T,
|
||||||
|
ctx context.Context,
|
||||||
|
wormchain *cosmos.CosmosChain,
|
||||||
|
contractAddr string,
|
||||||
|
expectedAmount string,
|
||||||
|
) {
|
||||||
|
var stateResp GetStateQueryResponse
|
||||||
|
err := wormchain.QueryContract(ctx, contractAddr, QueryMsg{
|
||||||
|
GetState: &QueryMsg_GetState{},
|
||||||
|
}, &stateResp)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "uworm", stateResp.Data.Fee.Denom)
|
||||||
|
require.Equal(t, Uint128(expectedAmount), stateResp.Data.Fee.Amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifyEventAttributes verifies the attributes in a wasm tx response
|
||||||
|
func VerifyEventAttributes(t *testing.T, txResponse *TxResponse, expectedAttributes map[string]string) {
|
||||||
|
require.Equal(t, uint32(0), txResponse.Code, "tx should succeed")
|
||||||
|
|
||||||
|
// Find the wasm event
|
||||||
|
var wasmEvent *sdk.StringEvent
|
||||||
|
for _, log := range txResponse.Logs {
|
||||||
|
for _, event := range log.Events {
|
||||||
|
if event.Type == "wasm" {
|
||||||
|
wasmEvent = &event
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.NotNil(t, wasmEvent, "wasm event not found")
|
||||||
|
|
||||||
|
// Helper to find attribute value
|
||||||
|
findAttribute := func(key string) string {
|
||||||
|
for _, attr := range wasmEvent.Attributes {
|
||||||
|
if attr.Key == key {
|
||||||
|
return attr.Value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify each expected attribute
|
||||||
|
for key, expectedValue := range expectedAttributes {
|
||||||
|
actualValue := findAttribute(key)
|
||||||
|
require.Equal(t, expectedValue, actualValue,
|
||||||
|
"unexpected value for attribute %s", key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostMessageWithFee posts a message to the contract with a fee
|
||||||
|
func PostMessageWithFee(
|
||||||
|
t *testing.T,
|
||||||
|
ctx context.Context,
|
||||||
|
wormchain *cosmos.CosmosChain,
|
||||||
|
contractAddr string,
|
||||||
|
message string,
|
||||||
|
fee int64,
|
||||||
|
) error {
|
||||||
|
messageBase64 := base64.StdEncoding.EncodeToString([]byte(message))
|
||||||
|
executeMsg, err := json.Marshal(ExecuteMsg{
|
||||||
|
PostMessage: &ExecuteMsg_PostMessage{
|
||||||
|
Message: Binary(messageBase64),
|
||||||
|
Nonce: 1,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
funds := sdk.Coins{sdk.NewInt64Coin("uworm", fee)}
|
||||||
|
_, err = wormchain.ExecuteContractWithAmount(ctx, "faucet", contractAddr, string(executeMsg), funds)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubmitTransferFee submits a VAA to transfer fees to an address
|
||||||
|
func SubmitTransferFee(
|
||||||
|
t *testing.T,
|
||||||
|
ctx context.Context,
|
||||||
|
guardians *guardians.ValSet,
|
||||||
|
wormchain *cosmos.CosmosChain,
|
||||||
|
contractAddr string,
|
||||||
|
addrBytes []byte,
|
||||||
|
amount string,
|
||||||
|
replay bool,
|
||||||
|
) (*TxResponse, error) {
|
||||||
|
// Created a fixed 32-byte array for the recipient address
|
||||||
|
var recipientBytes [32]byte
|
||||||
|
copy(recipientBytes[32-len(addrBytes):], addrBytes)
|
||||||
|
|
||||||
|
// Create a fixed 32-byte array for the fee amount
|
||||||
|
var amountBytes [32]byte
|
||||||
|
amountInt := new(big.Int)
|
||||||
|
amountInt.SetString(amount, 10)
|
||||||
|
amountInt.FillBytes(amountBytes[:])
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
buf.Write(vaa.CoreModule)
|
||||||
|
vaa.MustWrite(buf, binary.BigEndian, vaa.ActionCoreTransferFees)
|
||||||
|
vaa.MustWrite(buf, binary.BigEndian, uint16(0))
|
||||||
|
buf.Write(recipientBytes[:])
|
||||||
|
buf.Write(amountBytes[:])
|
||||||
|
|
||||||
|
guardianSetIndex := helpers.QueryConsensusGuardianSetIndex(t, wormchain, ctx)
|
||||||
|
govVaa := helpers.GenerateGovernanceVaa(uint32(guardianSetIndex), guardians, buf.Bytes())
|
||||||
|
vaaBz, err := govVaa.Marshal()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
encodedVaa := base64.StdEncoding.EncodeToString(vaaBz)
|
||||||
|
executeVAAPayload, err := json.Marshal(ExecuteMsg{
|
||||||
|
SubmitVaa: &ExecuteMsg_SubmitVAA{
|
||||||
|
Vaa: Binary(encodedVaa),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
txHash, err := wormchain.ExecuteContract(ctx, "faucet", contractAddr, string(executeVAAPayload))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = testutil.WaitForBlocks(ctx, 2, wormchain)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if replay {
|
||||||
|
_, err = wormchain.ExecuteContract(ctx, "faucet", contractAddr, string(executeVAAPayload))
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "VaaAlreadyExecuted")
|
||||||
|
}
|
||||||
|
|
||||||
|
txResult, _, err := wormchain.Validators[0].ExecQuery(ctx, "tx", txHash)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var txResponse TxResponse
|
||||||
|
err = json.Unmarshal(txResult, &txResponse)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return &txResponse, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUwormBalance returns the balance of uworm tokens for an address
|
||||||
|
func GetUwormBalance(t *testing.T, ctx context.Context, wormchain *cosmos.CosmosChain, addr string) (int64, error) {
|
||||||
|
coins, err := wormchain.GetBalance(ctx, addr, "uworm")
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return coins, nil
|
||||||
|
}
|
|
@ -35,7 +35,7 @@ func MigrateContract(
|
||||||
codeId string,
|
codeId string,
|
||||||
message string,
|
message string,
|
||||||
guardians *guardians.ValSet,
|
guardians *guardians.ValSet,
|
||||||
) {
|
) error {
|
||||||
|
|
||||||
node := chain.GetFullNode()
|
node := chain.GetFullNode()
|
||||||
|
|
||||||
|
@ -48,5 +48,5 @@ func MigrateContract(
|
||||||
vHex := hex.EncodeToString(vBz)
|
vHex := hex.EncodeToString(vBz)
|
||||||
|
|
||||||
_, err = node.ExecTx(ctx, keyName, "wormhole", "migrate", contractAddr, codeId, message, vHex, "--gas", "auto")
|
_, err = node.ExecTx(ctx, keyName, "wormhole", "migrate", contractAddr, codeId, message, vHex, "--gas", "auto")
|
||||||
require.NoError(t, err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
package helpers
|
package helpers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||||
|
|
||||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||||
|
@ -44,3 +47,23 @@ func GenerateGovernanceVaa(index uint32,
|
||||||
latestSequence = latestSequence + 1
|
latestSequence = latestSequence + 1
|
||||||
return signVaa(*v, signers)
|
return signVaa(*v, signers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GenerateEmptyVAA(
|
||||||
|
t *testing.T,
|
||||||
|
guardians *guardians.ValSet,
|
||||||
|
moduleStr string,
|
||||||
|
action vaa.GovernanceAction,
|
||||||
|
chainID vaa.ChainID,
|
||||||
|
) string {
|
||||||
|
|
||||||
|
payloadBz, err := vaa.EmptyPayloadVaa(moduleStr, action, chainID)
|
||||||
|
require.NoError(t, err)
|
||||||
|
v := generateVaa(0, guardians, vaa.GovernanceChain, vaa.GovernanceEmitter, payloadBz)
|
||||||
|
|
||||||
|
v = signVaa(v, guardians)
|
||||||
|
vBz, err := v.Marshal()
|
||||||
|
require.NoError(t, err)
|
||||||
|
vHex := hex.EncodeToString(vBz)
|
||||||
|
|
||||||
|
return vHex
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package helpers
|
package helpers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/strangelove-ventures/interchaintest/v4/chain/cosmos"
|
||||||
"github.com/strangelove-ventures/interchaintest/v4/ibc"
|
"github.com/strangelove-ventures/interchaintest/v4/ibc"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
"github.com/wormhole-foundation/wormchain/interchaintest/guardians"
|
||||||
|
@ -28,7 +30,7 @@ type GuardianAddress struct {
|
||||||
Bytes []byte `json:"bytes"`
|
Bytes []byte `json:"bytes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func CoreContractInstantiateMsg(t *testing.T, cfg ibc.ChainConfig, guardians *guardians.ValSet) string {
|
func CoreContractInstantiateMsg(t *testing.T, cfg ibc.ChainConfig, vaaChainId vaa.ChainID, guardians *guardians.ValSet) string {
|
||||||
guardianAddresses := []GuardianAddress{}
|
guardianAddresses := []GuardianAddress{}
|
||||||
for i := 0; i < guardians.Total; i++ {
|
for i := 0; i < guardians.Total; i++ {
|
||||||
guardianAddresses = append(guardianAddresses, GuardianAddress{
|
guardianAddresses = append(guardianAddresses, GuardianAddress{
|
||||||
|
@ -44,7 +46,7 @@ func CoreContractInstantiateMsg(t *testing.T, cfg ibc.ChainConfig, guardians *gu
|
||||||
ExpirationTime: 0,
|
ExpirationTime: 0,
|
||||||
},
|
},
|
||||||
GuardianSetExpirity: 86400,
|
GuardianSetExpirity: 86400,
|
||||||
ChainId: uint16(vaa.ChainIDWormchain),
|
ChainId: uint16(vaaChainId),
|
||||||
FeeDenom: cfg.Denom,
|
FeeDenom: cfg.Denom,
|
||||||
}
|
}
|
||||||
msgBz, err := json.Marshal(msg)
|
msgBz, err := json.Marshal(msg)
|
||||||
|
@ -52,3 +54,23 @@ func CoreContractInstantiateMsg(t *testing.T, cfg ibc.ChainConfig, guardians *gu
|
||||||
|
|
||||||
return string(msgBz)
|
return string(msgBz)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryConsensusGuardianSetIndex queries the index of the consensus guardian set
|
||||||
|
func QueryConsensusGuardianSetIndex(t *testing.T, wormchain *cosmos.CosmosChain, ctx context.Context) uint64 {
|
||||||
|
stdout, _, err := wormchain.GetFullNode().ExecQuery(ctx,
|
||||||
|
"wormhole", "show-consensus-guardian-set-index",
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
res := new(ConsensusGuardianSetIndexResponse)
|
||||||
|
err = json.Unmarshal(stdout, res)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return res.ConsensusGuardianSetIndex.Index
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConsensusGuardianSetIndexResponse struct {
|
||||||
|
ConsensusGuardianSetIndex struct {
|
||||||
|
Index uint64 `json:"index"`
|
||||||
|
} `json:"ConsensusGuardianSetIndex"`
|
||||||
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ func createChains(t *testing.T, wormchainVersion string, guardians guardians.Val
|
||||||
wormchainConfig.Images[0].Version = wormchainVersion
|
wormchainConfig.Images[0].Version = wormchainVersion
|
||||||
|
|
||||||
// Create chain factory with wormchain
|
// Create chain factory with wormchain
|
||||||
wormchainConfig.ModifyGenesis = ModifyGenesis(votingPeriod, maxDepositPeriod, guardians)
|
wormchainConfig.ModifyGenesis = ModifyGenesis(votingPeriod, maxDepositPeriod, guardians, false)
|
||||||
|
|
||||||
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
|
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
|
||||||
{
|
{
|
||||||
|
@ -338,7 +338,7 @@ func instantiateWormholeIbcContracts(t *testing.T, ctx context.Context,
|
||||||
guardians *guardians.ValSet) (helpers.ContractInfoResponse, helpers.ContractInfoResponse) {
|
guardians *guardians.ValSet) (helpers.ContractInfoResponse, helpers.ContractInfoResponse) {
|
||||||
|
|
||||||
// Instantiate the Wormchain core contract
|
// Instantiate the Wormchain core contract
|
||||||
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, guardians)
|
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, vaa.ChainIDWormchain, guardians)
|
||||||
wormchainCoreContractInfo := helpers.StoreAndInstantiateWormholeContract(t, ctx, wormchain, "faucet", "./contracts/wormhole_core.wasm", "wormhole_core", coreInstantiateMsg, guardians)
|
wormchainCoreContractInfo := helpers.StoreAndInstantiateWormholeContract(t, ctx, wormchain, "faucet", "./contracts/wormhole_core.wasm", "wormhole_core", coreInstantiateMsg, guardians)
|
||||||
|
|
||||||
// Store wormhole-ibc-receiver contract on wormchain
|
// Store wormhole-ibc-receiver contract on wormchain
|
||||||
|
@ -354,7 +354,7 @@ func instantiateWormholeIbcContracts(t *testing.T, ctx context.Context,
|
||||||
require.NotEmpty(t, wormchainReceiverContractInfo.ContractInfo.IbcPortID, "wormchain (wormchain-ibc-receiver) contract port id is nil")
|
require.NotEmpty(t, wormchainReceiverContractInfo.ContractInfo.IbcPortID, "wormchain (wormchain-ibc-receiver) contract port id is nil")
|
||||||
|
|
||||||
// Store and instantiate wormhole-ibc contract on osmosis
|
// Store and instantiate wormhole-ibc contract on osmosis
|
||||||
senderInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, guardians)
|
senderInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, vaa.ChainIDWormchain, guardians)
|
||||||
senderCodeId, err := remoteChain.StoreContract(ctx, "faucet", "./contracts/wormhole_ibc.wasm")
|
senderCodeId, err := remoteChain.StoreContract(ctx, "faucet", "./contracts/wormhole_ibc.wasm")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
senderContractAddr, err := remoteChain.InstantiateContract(ctx, "faucet", senderCodeId, senderInstantiateMsg, true)
|
senderContractAddr, err := remoteChain.InstantiateContract(ctx, "faucet", senderCodeId, senderInstantiateMsg, true)
|
||||||
|
|
|
@ -58,7 +58,7 @@ func TestMalformedPayload(t *testing.T) {
|
||||||
fmt.Println("Core contract code id: ", coreContractCodeId)
|
fmt.Println("Core contract code id: ", coreContractCodeId)
|
||||||
|
|
||||||
// Instantiate wormhole core contract
|
// Instantiate wormhole core contract
|
||||||
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, guardians)
|
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, vaa.ChainIDWormchain, guardians)
|
||||||
coreContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", coreContractCodeId, "wormhole_core", coreInstantiateMsg, guardians)
|
coreContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", coreContractCodeId, "wormhole_core", coreInstantiateMsg, guardians)
|
||||||
fmt.Println("Core contract address: ", coreContractAddr)
|
fmt.Println("Core contract address: ", coreContractAddr)
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ func CreateChains(t *testing.T, wormchainVersion string, guardians guardians.Val
|
||||||
wormchainConfig.Images[0].Version = wormchainVersion
|
wormchainConfig.Images[0].Version = wormchainVersion
|
||||||
|
|
||||||
// Create chain factory with wormchain
|
// Create chain factory with wormchain
|
||||||
wormchainConfig.ModifyGenesis = ModifyGenesis(votingPeriod, maxDepositPeriod, guardians)
|
wormchainConfig.ModifyGenesis = ModifyGenesis(votingPeriod, maxDepositPeriod, guardians, false)
|
||||||
|
|
||||||
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
|
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
|
||||||
{
|
{
|
||||||
|
@ -136,7 +136,7 @@ func BuildInterchain(t *testing.T, chains []ibc.Chain) (context.Context, ibc.Rel
|
||||||
Client: client,
|
Client: client,
|
||||||
NetworkID: network,
|
NetworkID: network,
|
||||||
SkipPathCreation: false,
|
SkipPathCreation: false,
|
||||||
// BlockDatabaseFile: interchaintest.DefaultBlockDatabaseFilepath(),
|
BlockDatabaseFile: interchaintest.DefaultBlockDatabaseFilepath(),
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ func BuildInterchain(t *testing.T, chains []ibc.Chain) (context.Context, ibc.Rel
|
||||||
// * Set Guardian Set List using new val set
|
// * Set Guardian Set List using new val set
|
||||||
// * Set Guardian Validator List using new val set
|
// * Set Guardian Validator List using new val set
|
||||||
// * Allow list the faucet address
|
// * Allow list the faucet address
|
||||||
func ModifyGenesis(votingPeriod string, maxDepositPeriod string, guardians guardians.ValSet) func(ibc.ChainConfig, []byte) ([]byte, error) {
|
func ModifyGenesis(votingPeriod string, maxDepositPeriod string, guardians guardians.ValSet, skipRelayers bool) func(ibc.ChainConfig, []byte) ([]byte, error) {
|
||||||
return func(chainConfig ibc.ChainConfig, genbz []byte) ([]byte, error) {
|
return func(chainConfig ibc.ChainConfig, genbz []byte) ([]byte, error) {
|
||||||
numVals := len(guardians.Vals)
|
numVals := len(guardians.Vals)
|
||||||
g := make(map[string]interface{})
|
g := make(map[string]interface{})
|
||||||
|
@ -202,11 +202,14 @@ func ModifyGenesis(votingPeriod string, maxDepositPeriod string, guardians guard
|
||||||
return nil, fmt.Errorf("failed to get faucet address: %w", err)
|
return nil, fmt.Errorf("failed to get faucet address: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var relayerAddress interface{}
|
||||||
|
if !skipRelayers {
|
||||||
// Get relayer address
|
// Get relayer address
|
||||||
relayerAddress, err := dyno.Get(g, "app_state", "auth", "accounts", numVals+1, "address")
|
relayerAddress, err = dyno.Get(g, "app_state", "auth", "accounts", numVals+1, "address")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get relayer address: %w", err)
|
return nil, fmt.Errorf("failed to get relayer address: %w", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set guardian set list and validators
|
// Set guardian set list and validators
|
||||||
guardianSetList := []GuardianSet{}
|
guardianSetList := []GuardianSet{}
|
||||||
|
@ -236,11 +239,15 @@ func ModifyGenesis(votingPeriod string, maxDepositPeriod string, guardians guard
|
||||||
AllowedAddress: faucetAddress.(string),
|
AllowedAddress: faucetAddress.(string),
|
||||||
Name: "Faucet",
|
Name: "Faucet",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if !skipRelayers {
|
||||||
allowedAddresses = append(allowedAddresses, ValidatorAllowedAddress{
|
allowedAddresses = append(allowedAddresses, ValidatorAllowedAddress{
|
||||||
ValidatorAddress: sdk.MustBech32ifyAddressBytes(chainConfig.Bech32Prefix, validators[0]),
|
ValidatorAddress: sdk.MustBech32ifyAddressBytes(chainConfig.Bech32Prefix, validators[0]),
|
||||||
AllowedAddress: relayerAddress.(string),
|
AllowedAddress: relayerAddress.(string),
|
||||||
Name: "Relayer",
|
Name: "Relayer",
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if err := dyno.Set(g, allowedAddresses, "app_state", "wormhole", "allowedAddresses"); err != nil {
|
if err := dyno.Set(g, allowedAddresses, "app_state", "wormhole", "allowedAddresses"); err != nil {
|
||||||
return nil, fmt.Errorf("failed to set guardian validator list: %w", err)
|
return nil, fmt.Errorf("failed to set guardian validator list: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ import (
|
||||||
// - Verify asset 1 balance of gaia user 1, osmo user 1, osmo user 2, and cw20 contract total supply
|
// - Verify asset 1 balance of gaia user 1, osmo user 1, osmo user 2, and cw20 contract total supply
|
||||||
func TestUpgrade(t *testing.T) {
|
func TestUpgrade(t *testing.T) {
|
||||||
// Base setup
|
// Base setup
|
||||||
numVals := 3
|
numVals := 5
|
||||||
guardians := guardians.CreateValSet(t, numVals)
|
guardians := guardians.CreateValSet(t, numVals)
|
||||||
chains := CreateChains(t, "v2.18.1", *guardians)
|
chains := CreateChains(t, "v2.18.1", *guardians)
|
||||||
ctx, r, eRep, client := BuildInterchain(t, chains)
|
ctx, r, eRep, client := BuildInterchain(t, chains)
|
||||||
|
@ -186,7 +186,7 @@ func TestUpgrade(t *testing.T) {
|
||||||
fmt.Println("Core contract code id: ", coreContractCodeId)
|
fmt.Println("Core contract code id: ", coreContractCodeId)
|
||||||
|
|
||||||
// Instantiate wormhole core contract
|
// Instantiate wormhole core contract
|
||||||
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, guardians)
|
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, vaa.ChainIDWormchain, guardians)
|
||||||
coreContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", coreContractCodeId, "wormhole_core", coreInstantiateMsg, guardians)
|
coreContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", coreContractCodeId, "wormhole_core", coreInstantiateMsg, guardians)
|
||||||
fmt.Println("Core contract address: ", coreContractAddr)
|
fmt.Println("Core contract address: ", coreContractAddr)
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ func TestWormchain(t *testing.T) {
|
||||||
fmt.Println("Core contract code id: ", coreContractCodeId)
|
fmt.Println("Core contract code id: ", coreContractCodeId)
|
||||||
|
|
||||||
// Instantiate wormhole core contract
|
// Instantiate wormhole core contract
|
||||||
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, guardians)
|
coreInstantiateMsg := helpers.CoreContractInstantiateMsg(t, wormchainConfig, vaa.ChainIDWormchain, guardians)
|
||||||
coreContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", coreContractCodeId, "wormhole_core", coreInstantiateMsg, guardians)
|
coreContractAddr := helpers.InstantiateContract(t, ctx, wormchain, "faucet", coreContractCodeId, "wormhole_core", coreInstantiateMsg, guardians)
|
||||||
fmt.Println("Core contract address: ", coreContractAddr)
|
fmt.Println("Core contract address: ", coreContractAddr)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue