wormhole/bridge/e2e/e2e_test.go

263 lines
7.3 KiB
Go

package e2e
import (
"context"
"testing"
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/mr-tron/base58"
"k8s.io/client-go/kubernetes"
"github.com/certusone/wormhole/bridge/pkg/devnet"
"github.com/certusone/wormhole/bridge/pkg/ethereum"
"github.com/certusone/wormhole/bridge/pkg/vaa"
"github.com/ethereum/go-ethereum/ethclient"
)
func setup(t *testing.T) (*kubernetes.Clientset, *ethclient.Client, *bind.TransactOpts, *TerraClient) {
// List of pods we need in a ready state before we can run tests.
want := []string{
// Our test guardian set.
"guardian-0",
//"guardian-1",
//"guardian-2",
//"guardian-3",
//"guardian-4",
//"guardian-5",
// Connected chains
"solana-devnet-0",
"terra-terrad-0",
"terra-lcd-0",
"eth-devnet-0",
}
c := getk8sClient()
// Wait for all pods to be ready. This blocks until the bridge is ready to receive lockups.
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
defer cancel()
waitForPods(ctx, c, want)
if ctx.Err() != nil {
t.Fatal(ctx.Err())
}
// Ethereum client.
ec, err := ethclient.Dial(devnet.GanacheRPCURL)
if err != nil {
t.Fatalf("dialing devnet eth rpc failed: %v", err)
}
kt := devnet.GetKeyedTransactor(context.Background())
// Terra client
tc, err := NewTerraClient()
if err != nil {
t.Fatalf("creating devnet terra client failed: %v", err)
}
return c, ec, kt, tc
}
// Careful about parallel tests - accounts on some chains like Ethereum cannot be
// used concurrently as they have monotonically increasing nonces that would conflict.
// Either use different Ethereum account, or do not run Ethereum tests in parallel.
func TestEndToEnd_SOL_ETH(t *testing.T) {
c, ec, kt, _ := setup(t)
t.Run("[SOL] Native -> [ETH] Wrapped", func(t *testing.T) {
testSolanaLockup(t, context.Background(), ec, c,
// Source SPL account
devnet.SolanaExampleTokenOwningAccount,
// Source SPL token
devnet.SolanaExampleToken,
// Our wrapped destination token on Ethereum
devnet.GanacheExampleERC20WrappedSOL,
// Amount of SPL token value to transfer.
50*devnet.SolanaDefaultPrecision,
// Same precision - same amount, no precision gained.
0,
)
})
t.Run("[ETH] Wrapped -> [SOL] Native", func(t *testing.T) {
testEthereumLockup(t, context.Background(), ec, kt, c,
// Source ERC20 token
devnet.GanacheExampleERC20WrappedSOL,
// Destination SPL token account
devnet.SolanaExampleTokenOwningAccount,
// Amount (the reverse of what the previous test did, with the same precision because
// the wrapped ERC20 is set to the original asset's 10**9 precision).
50*devnet.SolanaDefaultPrecision,
// No precision loss
0,
)
})
t.Run("[ETH] Native -> [SOL] Wrapped", func(t *testing.T) {
testEthereumLockup(t, context.Background(), ec, kt, c,
// Source ERC20 token
devnet.GanacheExampleERC20Token,
// Destination SPL token account
devnet.SolanaExampleWrappedERCTokenOwningAccount,
// Amount
0.000000012*devnet.ERC20DefaultPrecision,
// We lose 9 digits of precision on this path, as the default ERC20 token has 10**18 precision.
9,
)
})
t.Run("[SOL] Wrapped -> [ETH] Native", func(t *testing.T) {
testSolanaLockup(t, context.Background(), ec, c,
// Source SPL account
devnet.SolanaExampleWrappedERCTokenOwningAccount,
// Source SPL token
devnet.SolanaExampleWrappedERCToken,
// Our wrapped destination token on Ethereum
devnet.GanacheExampleERC20Token,
// Amount of SPL token value to transfer.
0.000000012*devnet.SolanaDefaultPrecision,
// We gain 9 digits of precision on Eth.
9,
)
})
}
func TestEndToEnd_SOL_Terra(t *testing.T) {
c, _, _, tc := setup(t)
t.Run("[Terra] Native -> [SOL] Wrapped", func(t *testing.T) {
testTerraLockup(t, context.Background(), tc, c,
// Source CW20 token
devnet.TerraTokenAddress,
// Destination SPL token account
devnet.SolanaExampleWrappedCWTokenOwningAccount,
// Amount
2*devnet.TerraDefaultPrecision,
// Same precision - same amount, no precision gained.
0,
)
})
t.Run("[SOL] Wrapped -> [Terra] Native", func(t *testing.T) {
testSolanaToTerraLockup(t, context.Background(), c,
// Source SPL account
devnet.SolanaExampleWrappedCWTokenOwningAccount,
// Source SPL token
devnet.SolanaExampleWrappedCWToken,
// Wrapped
false,
// Amount of SPL token value to transfer.
2*devnet.TerraDefaultPrecision,
// Same precision - same amount, no precision gained.
0,
)
})
t.Run("[SOL] Native -> [Terra] Wrapped", func(t *testing.T) {
testSolanaToTerraLockup(t, context.Background(), c,
// Source SPL account
devnet.SolanaExampleTokenOwningAccount,
// Source SPL token
devnet.SolanaExampleToken,
// Native
true,
// Amount of SPL token value to transfer.
50*devnet.SolanaDefaultPrecision,
// Same precision - same amount, no precision gained.
0,
)
})
t.Run("[Terra] Wrapped -> [SOL] Native", func(t *testing.T) {
tokenSlice, err := base58.Decode(devnet.SolanaExampleToken)
if err != nil {
t.Fatal(err)
}
wrappedAsset, err := waitTerraAsset(t, context.Background(), devnet.TerraBridgeAddress, vaa.ChainIDSolana, tokenSlice)
if err != nil {
t.Fatal(err)
}
testTerraLockup(t, context.Background(), tc, c,
// Source wrapped token
wrappedAsset,
// Destination SPL token account
devnet.SolanaExampleTokenOwningAccount,
// Amount of Terra token value to transfer.
50*devnet.SolanaDefaultPrecision,
// Same precision
0,
)
})
}
func TestEndToEnd_ETH_Terra(t *testing.T) {
_, ec, kt, tc := setup(t)
t.Run("[Terra] Native -> [ETH] Wrapped", func(t *testing.T) {
testTerraToEthLockup(t, context.Background(), tc, ec,
// Source CW20 token
devnet.TerraTokenAddress,
// Destination ETH token
devnet.GanacheExampleERC20WrappedTerra,
// Amount
2*devnet.TerraDefaultPrecision,
// Same precision - same amount, no precision gained.
0,
)
})
t.Run("[ETH] Wrapped -> [Terra] Native", func(t *testing.T) {
testEthereumToTerraLockup(t, context.Background(), ec, kt,
// Source Ethereum token
devnet.GanacheExampleERC20WrappedTerra,
// Wrapped
false,
// Amount of Ethereum token value to transfer.
2*devnet.TerraDefaultPrecision,
// Same precision
0,
)
})
t.Run("[ETH] Native -> [Terra] Wrapped", func(t *testing.T) {
testEthereumToTerraLockup(t, context.Background(), ec, kt,
// Source Ethereum token
devnet.GanacheExampleERC20Token,
// Native
true,
// Amount of Ethereum token value to transfer.
0.000000012*devnet.ERC20DefaultPrecision,
// We lose 9 digits of precision on this path, as the default ERC20 token has 10**18 precision.
9,
)
})
t.Run("[Terra] Wrapped -> [ETH] Native", func(t *testing.T) {
paddedTokenAddress := ethereum.PadAddress(devnet.GanacheExampleERC20Token)
wrappedAsset, err := waitTerraAsset(t, context.Background(), devnet.TerraBridgeAddress, vaa.ChainIDEthereum, paddedTokenAddress[:])
if err != nil {
t.Fatal(err)
}
testTerraToEthLockup(t, context.Background(), tc, ec,
// Source wrapped token
wrappedAsset,
// Destination ETH token
devnet.GanacheExampleERC20Token,
// Amount of Terra token value to transfer.
0.000000012*1e9, // 10**9 because default ETH precision is 18 and we lost 9 digits on wrapping
// We gain 9 digits of precision on Eth.
9,
)
})
}