Added missing e2e tests between Terra and Ethereum/Solana (#168)

* Added missing e2e tests between Terra and Ethereum/Solana

* Review comments fixed

* Uncommented Solana<->ETH code, missing Ethereum utils file added
This commit is contained in:
Yuriy Savchenko 2021-02-01 21:38:13 +02:00 committed by GitHub
parent 5256d2025a
commit d9bb5f6802
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 323 additions and 58 deletions

View File

@ -142,6 +142,7 @@ using `kubectl exec solana-devnet-0 -c setup -- cli airdrop solana-devnet:9900`
| `0xe78A0F7E598Cc8b0Bb87894B0F60dD2a88d6a8Ab` | Wrapped asset contract |
| `0xCfEB869F69431e42cdB54A4F4f105C19C080A601` | Example ERC20 token |
| `0xf5b1d8fab1054b9cf7db274126972f97f9d42a11` | Wrapped asset address for the 6qRhs8oA... SPL token |
| `0x62b47a23cd900da982bdbe75aeb891d3ed18cc36` | Wrapped asset address for the terra18v... Terra token |
**Terra**

View File

@ -12,6 +12,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/certusone/wormhole/bridge/pkg/ethereum"
"github.com/certusone/wormhole/bridge/pkg/vaa"
)
@ -322,14 +323,5 @@ func generateKeys(n int) (keys []*ecdsa.PrivateKey) {
func hexToAddress(hex string) vaa.Address {
hexAddr := common.HexToAddress(hex)
return padAddress(hexAddr)
}
func padAddress(address common.Address) vaa.Address {
paddedAddress := common.LeftPadBytes(address[:], 32)
addr := vaa.Address{}
copy(addr[:], paddedAddress)
return addr
return ethereum.PadAddress(hexAddr)
}

View File

@ -13,6 +13,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/certusone/wormhole/bridge/pkg/devnet"
"github.com/certusone/wormhole/bridge/pkg/ethereum"
"github.com/certusone/wormhole/bridge/pkg/vaa"
)
@ -39,7 +40,7 @@ func main() {
SourceChain: 1,
TargetChain: 2,
SourceAddress: vaa.Address{2, 1, 4},
TargetAddress: padAddress(devnet.GanacheClientDefaultAccountAddress),
TargetAddress: ethereum.PadAddress(devnet.GanacheClientDefaultAccountAddress),
Asset: &vaa.AssetMeta{
Chain: vaa.ChainIDSolana,
Address: hexToAddress("0x347ef34687bdc9f189e87a9200658d9c40e9988"),
@ -58,7 +59,7 @@ func main() {
SourceChain: 1,
TargetChain: 2,
SourceAddress: vaa.Address{2, 1, 4},
TargetAddress: padAddress(devnet.GanacheClientDefaultAccountAddress),
TargetAddress: ethereum.PadAddress(devnet.GanacheClientDefaultAccountAddress),
Asset: &vaa.AssetMeta{
Chain: vaa.ChainIDEthereum,
Address: hexToAddress("0xd833215cbcc3f914bd1c9ece3ee7bf8b14f841bb"),
@ -101,7 +102,7 @@ func main() {
SourceChain: 1,
TargetChain: 2,
SourceAddress: vaa.Address{2, 1, 4},
TargetAddress: padAddress(devnet.GanacheClientDefaultAccountAddress),
TargetAddress: ethereum.PadAddress(devnet.GanacheClientDefaultAccountAddress),
Asset: &vaa.AssetMeta{
Chain: vaa.ChainIDSolana,
Address: hexToAddress("0x347ef34687bdc9f189e87a9200658d9c40e9988"),
@ -120,7 +121,7 @@ func main() {
SourceChain: 1,
TargetChain: 2,
SourceAddress: vaa.Address{2, 1, 5},
TargetAddress: padAddress(devnet.GanacheClientDefaultAccountAddress),
TargetAddress: ethereum.PadAddress(devnet.GanacheClientDefaultAccountAddress),
Asset: &vaa.AssetMeta{
Chain: vaa.ChainIDSolana,
Address: hexToAddress("0x347ef34687bdc9f189e87a9200658d9c40e9988"),
@ -139,7 +140,7 @@ func main() {
SourceChain: 1,
TargetChain: 2,
SourceAddress: vaa.Address{2, 1, 5},
TargetAddress: padAddress(devnet.GanacheClientDefaultAccountAddress),
TargetAddress: ethereum.PadAddress(devnet.GanacheClientDefaultAccountAddress),
Asset: &vaa.AssetMeta{
Chain: vaa.ChainIDSolana,
Address: hexToAddress("0x347ef34687bdc9f189e87a9200658d9c40e9988"),
@ -158,7 +159,7 @@ func main() {
SourceChain: 1,
TargetChain: 2,
SourceAddress: vaa.Address{2, 1, 5},
TargetAddress: padAddress(devnet.GanacheClientDefaultAccountAddress),
TargetAddress: ethereum.PadAddress(devnet.GanacheClientDefaultAccountAddress),
Asset: &vaa.AssetMeta{
Chain: vaa.ChainIDSolana,
Address: hexToAddress("0x347ef34687bdc9f189e87a9200658d9c40e9988"),
@ -194,7 +195,7 @@ func main() {
SourceChain: 1,
TargetChain: 2,
SourceAddress: vaa.Address{2, 1, 5},
TargetAddress: padAddress(devnet.GanacheClientDefaultAccountAddress),
TargetAddress: ethereum.PadAddress(devnet.GanacheClientDefaultAccountAddress),
Asset: &vaa.AssetMeta{
Chain: vaa.ChainIDSolana,
Address: hexToAddress("0x347ef34687bdc9f189e87a9200658d9c40e9988"),
@ -213,7 +214,7 @@ func main() {
SourceChain: 1,
TargetChain: 2,
SourceAddress: vaa.Address{2, 1, 5},
TargetAddress: padAddress(devnet.GanacheClientDefaultAccountAddress),
TargetAddress: ethereum.PadAddress(devnet.GanacheClientDefaultAccountAddress),
Asset: &vaa.AssetMeta{
Chain: vaa.ChainIDSolana,
Address: hexToAddress("0x347ef34687bdc9f189e87a9200658d9c40e9988"),
@ -253,14 +254,5 @@ func generateKeys(n int) (keys []*ecdsa.PrivateKey) {
func hexToAddress(hex string) vaa.Address {
hexAddr := common.HexToAddress(hex)
return padAddress(hexAddr)
}
func padAddress(address common.Address) vaa.Address {
paddedAddress := common.LeftPadBytes(address[:], 32)
addr := vaa.Address{}
copy(addr[:], paddedAddress)
return addr
return ethereum.PadAddress(hexAddr)
}

View File

@ -2,16 +2,20 @@ package e2e
import (
"context"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"k8s.io/client-go/kubernetes"
"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) {
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.
@ -48,7 +52,13 @@ func setup(t *testing.T) (*kubernetes.Clientset, *ethclient.Client, *bind.Transa
}
kt := devnet.GetKeyedTransactor(context.Background())
return c, ec, kt
// 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
@ -56,7 +66,7 @@ func setup(t *testing.T) (*kubernetes.Clientset, *ethclient.Client, *bind.Transa
// 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)
c, ec, kt, _ := setup(t)
t.Run("[SOL] Native -> [ETH] Wrapped", func(t *testing.T) {
testSolanaLockup(t, context.Background(), ec, c,
@ -117,12 +127,7 @@ func TestEndToEnd_SOL_ETH(t *testing.T) {
}
func TestEndToEnd_SOL_Terra(t *testing.T) {
c, _, _ := setup(t)
tc, err := NewTerraClient()
if err != nil {
t.Fatalf("creating devnet terra client failed: %v", err)
}
c, _, _, tc := setup(t)
t.Run("[Terra] Native -> [SOL] Wrapped", func(t *testing.T) {
testTerraLockup(t, context.Background(), tc, c,
@ -137,14 +142,29 @@ func TestEndToEnd_SOL_Terra(t *testing.T) {
)
})
// TODO(https://github.com/certusone/wormhole/issues/164): [SOL] Wrapped -> [Terra] Native
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(), tc, c,
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.
@ -152,7 +172,91 @@ func TestEndToEnd_SOL_Terra(t *testing.T) {
)
})
// TODO(https://github.com/certusone/wormhole/issues/164): [Terra] Wrapped -> [SOL] Native
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,
)
})
}
// TODO(https://github.com/certusone/wormhole/issues/164): TestEndToEnd_ETH_Terra
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,
)
})
}

View File

@ -2,6 +2,7 @@ package e2e
import (
"context"
"encoding/hex"
"math"
"math/big"
"testing"
@ -15,6 +16,7 @@ import (
"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/ethereum/abi"
"github.com/certusone/wormhole/bridge/pkg/ethereum/erc20"
"github.com/certusone/wormhole/bridge/pkg/vaa"
@ -105,3 +107,84 @@ func testEthereumLockup(t *testing.T, ctx context.Context, ec *ethclient.Client,
// Source account decreases by the full amount.
waitEthBalance(t, ctx, token, beforeErc20, -int64(amount))
}
func testEthereumToTerraLockup(t *testing.T, ctx context.Context, ec *ethclient.Client, kt *bind.TransactOpts,
tokenAddr common.Address, isNative bool, amount int64, precisionLoss int) {
// Bridge client
ethBridge, err := abi.NewAbi(devnet.GanacheBridgeContractAddress, ec)
if err != nil {
panic(err)
}
// Source token client
token, err := erc20.NewErc20(tokenAddr, ec)
if err != nil {
panic(err)
}
// Store balance of source ERC20 token
beforeErc20, err := token.BalanceOf(nil, devnet.GanacheClientDefaultAccountAddress)
if err != nil {
beforeErc20 = new(big.Int)
t.Log(err) // account may not yet exist, defaults to 0
}
t.Logf("ERC20 balance: %v", beforeErc20)
// Store balance of destination CW20 token
paddedTokenAddress := ethereum.PadAddress(tokenAddr)
var terraToken string
if isNative {
terraToken, err = getAssetAddress(ctx, devnet.TerraBridgeAddress, vaa.ChainIDEthereum, paddedTokenAddress[:])
if err != nil {
t.Log(err)
}
} else {
terraToken = devnet.TerraTokenAddress
}
// Get balance if deployed
beforeCw20, err := getTerraBalance(ctx, terraToken)
if err != nil {
beforeCw20 = new(big.Int)
t.Log(err) // account may not yet exist, defaults to 0
}
t.Logf("CW20 balance: %v", beforeCw20)
// Send lockup
dstAddress, err := hex.DecodeString(devnet.TerraMainTestAddressHex)
if err != nil {
t.Fatal(err)
}
var dstAddressBytes [32]byte
copy(dstAddressBytes[:], dstAddress)
tx, err := ethBridge.LockAssets(kt,
// asset address
tokenAddr,
// token amount
new(big.Int).SetInt64(amount),
// recipient address on target chain
dstAddressBytes,
// target chain
vaa.ChainIDTerra,
// random nonce
rand.Uint32(),
// refund dust?
false,
)
if err != nil {
t.Fatal(err)
}
t.Logf("sent lockup tx: %v", tx.Hash().Hex())
// Destination account increases by the full amount.
if isNative {
waitTerraUnknownBalance(t, ctx, devnet.TerraBridgeAddress, vaa.ChainIDEthereum, paddedTokenAddress[:], beforeCw20, int64(float64(amount)/math.Pow10(precisionLoss)))
} else {
waitTerraBalance(t, ctx, devnet.TerraTokenAddress, beforeCw20, int64(float64(amount)/math.Pow10(precisionLoss)))
}
// Source account decreases by the full amount.
waitEthBalance(t, ctx, token, beforeErc20, -int64(amount))
}

View File

@ -119,14 +119,22 @@ func testSolanaLockup(t *testing.T, ctx context.Context, ec *ethclient.Client, c
waitSPLBalance(t, ctx, c, sourceAcct, beforeSPL, -int64(amount))
}
func testSolanaToTerraLockup(t *testing.T, ctx context.Context, tc *TerraClient, c *kubernetes.Clientset,
sourceAcct string, tokenAddr string, amount int, precisionGain int) {
func testSolanaToTerraLockup(t *testing.T, ctx context.Context, c *kubernetes.Clientset,
sourceAcct string, tokenAddr string, isNative bool, amount int, precisionGain int) {
tokenSlice, err := base58.Decode(tokenAddr)
if err != nil {
t.Fatal(err)
}
terraToken, err := getAssetAddress(ctx, devnet.TerraBridgeAddress, vaa.ChainIDSolana, tokenSlice)
var terraToken string
if isNative {
terraToken, err = getAssetAddress(ctx, devnet.TerraBridgeAddress, vaa.ChainIDSolana, tokenSlice)
if err != nil {
t.Log(err)
}
} else {
terraToken = devnet.TerraTokenAddress
}
// Get balance if deployed
beforeCw20, err := getTerraBalance(ctx, terraToken)
@ -168,5 +176,9 @@ func testSolanaToTerraLockup(t *testing.T, ctx context.Context, tc *TerraClient,
waitSPLBalance(t, ctx, c, sourceAcct, beforeSPL, -int64(amount))
// Destination account increases by the full amount.
waitTerraUnknownBalance(t, ctx, devnet.TerraBridgeAddress, vaa.ChainIDSolana, tokenSlice, beforeCw20, int64(float64(amount)*math.Pow10(precisionGain)))
if isNative {
waitTerraUnknownBalance(t, ctx, devnet.TerraBridgeAddress, vaa.ChainIDSolana, tokenSlice, beforeCw20, int64(float64(amount)*math.Pow10(precisionGain)))
} else {
waitTerraBalance(t, ctx, devnet.TerraTokenAddress, beforeCw20, int64(float64(amount)*math.Pow10(precisionGain)))
}
}

View File

@ -9,11 +9,16 @@ import (
"math"
"math/big"
"net/http"
"net/url"
"testing"
"time"
"github.com/certusone/wormhole/bridge/pkg/devnet"
"github.com/certusone/wormhole/bridge/pkg/ethereum"
"github.com/certusone/wormhole/bridge/pkg/ethereum/erc20"
"github.com/certusone/wormhole/bridge/pkg/vaa"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/tendermint/tendermint/libs/rand"
"github.com/terra-project/terra.go/client"
"github.com/terra-project/terra.go/key"
@ -168,7 +173,7 @@ func getAssetAddress(ctx context.Context, contract string, chain uint8, asset []
func terraQuery(ctx context.Context, contract string, query string) (string, error) {
requestURL := fmt.Sprintf("%s/wasm/contracts/%s/store?query_msg=%s", devnet.TerraLCDURL, contract, query)
requestURL := fmt.Sprintf("%s/wasm/contracts/%s/store?query_msg=%s", devnet.TerraLCDURL, contract, url.QueryEscape(query))
req, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil)
if err != nil {
@ -193,21 +198,27 @@ func terraQuery(ctx context.Context, contract string, query string) (string, err
// waitTerraAsset waits for asset contract to be deployed on terra
func waitTerraAsset(t *testing.T, ctx context.Context, contract string, chain uint8, asset []byte) (string, error) {
ctx, cancel := context.WithTimeout(ctx, 60*time.Second)
ctx, cancel := context.WithTimeout(ctx, 90*time.Second)
defer cancel()
assetAddress := ""
err := wait.PollUntil(1*time.Second, func() (bool, error) {
err := wait.PollUntil(3*time.Second, func() (bool, error) {
address, err := getAssetAddress(ctx, contract, chain, asset)
if err != nil {
t.Log(err)
return true, nil
return false, nil
}
// Check the case if request was successful, but asset address is not yet in the registry
if address == "" {
return false, nil
}
t.Logf("Returning asset: %s", address)
assetAddress = address
return false, nil
return true, nil
}, ctx.Done())
if err != nil {
@ -252,10 +263,10 @@ func waitTerraUnknownBalance(t *testing.T, ctx context.Context, contract string,
return
}
ctx, cancel := context.WithTimeout(ctx, 60*time.Second)
ctx, cancel := context.WithTimeout(ctx, 90*time.Second)
defer cancel()
err = wait.PollUntil(1*time.Second, func() (bool, error) {
err = wait.PollUntil(3*time.Second, func() (bool, error) {
after, err := getTerraBalance(ctx, token)
if err != nil {
@ -322,3 +333,54 @@ func testTerraLockup(t *testing.T, ctx context.Context, tc *TerraClient,
// Source account decreases by the full amount.
waitTerraBalance(t, ctx, token, beforeCw20, -int64(amount))
}
func testTerraToEthLockup(t *testing.T, ctx context.Context, tc *TerraClient,
ec *ethclient.Client, tokenAddr string, destination common.Address, amount int64, precisionGain int) {
token, err := erc20.NewErc20(destination, ec)
if err != nil {
panic(err)
}
// Store balance of source CW20 token
beforeCw20, err := getTerraBalance(ctx, tokenAddr)
if err != nil {
t.Log(err) // account may not yet exist, defaults to 0
beforeCw20 = new(big.Int)
}
t.Logf("CW20 balance: %v", beforeCw20)
/// Store balance of wrapped destination token
beforeErc20, err := token.BalanceOf(nil, devnet.GanacheClientDefaultAccountAddress)
if err != nil {
t.Log(err) // account may not yet exist, defaults to 0
beforeErc20 = new(big.Int)
}
t.Logf("ERC20 balance: %v", beforeErc20)
// Send lockup
tx, err := tc.lockAssets(
t, ctx,
// asset address
tokenAddr,
// token amount
new(big.Int).SetInt64(amount),
// recipient address on target chain
ethereum.PadAddress(devnet.GanacheClientDefaultAccountAddress),
// target chain
vaa.ChainIDEthereum,
// random nonce
rand.Uint32(),
)
if err != nil {
t.Error(err)
}
t.Logf("sent lockup tx: %s", tx.TxHash)
// Destination account increases by full amount.
waitEthBalance(t, ctx, token, beforeErc20, int64(float64(amount)*math.Pow10(precisionGain)))
// Source account decreases by the full amount.
waitTerraBalance(t, ctx, tokenAddr, beforeCw20, -int64(amount))
}

View File

@ -26,8 +26,9 @@ var (
GanacheBridgeContractAddress = common.HexToAddress("0x5b1869D9A4C187F2EAa108f3062412ecf0526b24")
// ERC20 example tokens.
GanacheExampleERC20Token = common.HexToAddress("0xCfEB869F69431e42cdB54A4F4f105C19C080A601")
GanacheExampleERC20WrappedSOL = common.HexToAddress("0xf5b1d8fab1054b9cf7db274126972f97f9d42a11")
GanacheExampleERC20Token = common.HexToAddress("0xCfEB869F69431e42cdB54A4F4f105C19C080A601")
GanacheExampleERC20WrappedSOL = common.HexToAddress("0xf5b1d8fab1054b9cf7db274126972f97f9d42a11")
GanacheExampleERC20WrappedTerra = common.HexToAddress("0x62b47a23cd900da982bdbe75aeb891d3ed18cc36")
)
const (

View File

@ -0,0 +1,16 @@
package ethereum
import (
"github.com/certusone/wormhole/bridge/pkg/vaa"
"github.com/ethereum/go-ethereum/common"
)
// PadAddress creates 32-byte VAA.Address from 20-byte Ethereum addresses by adding 12 0-bytes at the left
func PadAddress(address common.Address) vaa.Address {
paddedAddress := common.LeftPadBytes(address[:], 32)
addr := vaa.Address{}
copy(addr[:], paddedAddress)
return addr
}

View File

@ -3,11 +3,12 @@ package ethereum
import (
"context"
"fmt"
"github.com/prometheus/client_golang/prometheus"
"math/big"
"sync"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
eth_common "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"

View File

@ -353,6 +353,7 @@ fn vaa_transfer<S: Storage, A: Api, Q: Querier>(
const TARGET_ADDRESS_POS: usize = 38;
const TOKEN_CHAIN_POS: usize = 70;
const TOKEN_ADDRESS_POS: usize = 71;
const DECIMALS_POS: usize = 103;
const AMOUNT_POS: usize = 104;
const PAYLOAD_LEN: usize = 136;
@ -413,7 +414,7 @@ fn vaa_transfer<S: Storage, A: Api, Q: Querier>(
msg: to_binary(&WrappedInit {
asset_chain: token_chain,
asset_address: asset_address.to_vec().into(),
decimals: data.get_u8(103),
decimals: data.get_u8(DECIMALS_POS),
mint: Some(InitMint {
recipient: deps
.api