From ef7098726175db943ba274b379a1b53befe7bbd6 Mon Sep 17 00:00:00 2001 From: Steve <1848680+misko9@users.noreply.github.com> Date: Fri, 23 Aug 2024 19:30:24 -0600 Subject: [PATCH 1/4] feat(geth): add ethereum support for the geth binary (#1230) Co-authored-by: Andrew Gouin --- chain/ethereum/ethererum_chain.go | 334 +++----------- chain/ethereum/foundry/anvil_chain.go | 228 ++++++++++ chain/ethereum/foundry/default_configs.go | 36 ++ chain/ethereum/{ => foundry}/forge.go | 33 +- chain/ethereum/geth/default_configs.go | 78 ++++ chain/ethereum/geth/geth_chain.go | 266 +++++++++++ chain/ethereum/wallet.go | 32 +- chain/thorchain/thornode.go | 1 + chain/utxo/cli.go | 4 +- chain/utxo/default_configs.go | 8 +- chain/utxo/utxo_chain.go | 8 + chain/utxo/wallet.go | 1 + chainfactory.go | 12 +- .../{start_test.go => foundry_test.go} | 7 +- examples/ethereum/geth_test.go | 95 ++++ examples/thorchain/chainspec_exochains.go | 28 +- examples/thorchain/chainspec_thorchain.go | 16 +- .../thorchain/contracts/eth-router-abi.json | 308 +++++++++++++ .../contracts/eth-router-bytecode.txt | 1 + examples/thorchain/contracts/router-abi.json | 423 ++++++++++++++++++ .../thorchain/contracts/router-bytecode.txt | 1 + examples/thorchain/contracts/token-abi.json | 229 ++++++++++ .../thorchain/contracts/token-bytecode.txt | 1 + examples/thorchain/features/dual_lper.go | 16 +- examples/thorchain/features/helpers.go | 10 +- examples/thorchain/features/ragnarok.go | 2 +- examples/thorchain/features/saver_eject.go | 27 +- examples/thorchain/features/swap.go | 22 +- examples/thorchain/helper.go | 25 +- examples/thorchain/setup.go | 165 +++++-- examples/thorchain/thorchain_hardfork_test.go | 3 +- examples/thorchain/thorchain_test.go | 22 +- local-interchain/interchain/logs.go | 6 +- 33 files changed, 2014 insertions(+), 434 deletions(-) create mode 100644 chain/ethereum/foundry/anvil_chain.go create mode 100644 chain/ethereum/foundry/default_configs.go rename chain/ethereum/{ => foundry}/forge.go (83%) create mode 100644 chain/ethereum/geth/default_configs.go create mode 100644 chain/ethereum/geth/geth_chain.go rename examples/ethereum/{start_test.go => foundry_test.go} (94%) create mode 100644 examples/ethereum/geth_test.go create mode 100644 examples/thorchain/contracts/eth-router-abi.json create mode 100644 examples/thorchain/contracts/eth-router-bytecode.txt create mode 100644 examples/thorchain/contracts/router-abi.json create mode 100644 examples/thorchain/contracts/router-bytecode.txt create mode 100644 examples/thorchain/contracts/token-abi.json create mode 100644 examples/thorchain/contracts/token-bytecode.txt diff --git a/chain/ethereum/ethererum_chain.go b/chain/ethereum/ethererum_chain.go index 2c96e663a..010bd0068 100644 --- a/chain/ethereum/ethererum_chain.go +++ b/chain/ethereum/ethererum_chain.go @@ -2,16 +2,12 @@ package ethereum import ( "context" - "encoding/json" "fmt" "io" - "os" - "path" - "path/filepath" - "strconv" - "strings" + "time" sdkmath "cosmossdk.io/math" + dockertypes "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/mount" "github.com/docker/docker/api/types/volume" @@ -22,75 +18,45 @@ import ( "github.com/strangelove-ventures/interchaintest/v8/ibc" "github.com/strangelove-ventures/interchaintest/v8/testutil" "go.uber.org/zap" -) -var _ ibc.Chain = &EthereumChain{} + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" +) const ( - blockTime = 2 // seconds - rpcPort = "8545/tcp" + rpcPort = "8545/tcp" ) +var natPorts = nat.PortMap{ + nat.Port(rpcPort): {}, +} + var ( GWEI = sdkmath.NewInt(1_000_000_000) ETHER = GWEI.MulRaw(1_000_000_000) ) -var natPorts = nat.PortMap{ - nat.Port(rpcPort): {}, -} - type EthereumChain struct { testName string cfg ibc.ChainConfig log *zap.Logger - VolumeName string - NetworkID string - DockerClient *dockerclient.Client + volumeName string + networkID string + dockerClient *dockerclient.Client containerLifecycle *dockerutil.ContainerLifecycle hostRPCPort string - - genesisWallets GenesisWallets - - keystoreMap map[string]string -} - -func DefaultEthereumAnvilChainConfig( - name string, -) ibc.ChainConfig { - return ibc.ChainConfig{ - Type: "ethereum", - Name: name, - ChainID: "31337", // default anvil chain-id - Bech32Prefix: "n/a", - CoinType: "60", - Denom: "wei", - GasPrices: "0", - GasAdjustment: 0, - TrustingPeriod: "0", - NoHostMount: false, - Images: []ibc.DockerImage{ - { - Repository: "ghcr.io/foundry-rs/foundry", - Version: "latest", - UidGid: "1000:1000", - }, - }, - Bin: "anvil", - } + rpcClient *ethclient.Client } func NewEthereumChain(testName string, chainConfig ibc.ChainConfig, log *zap.Logger) *EthereumChain { return &EthereumChain{ - testName: testName, - cfg: chainConfig, - log: log, - genesisWallets: NewGenesisWallet(), - keystoreMap: make(map[string]string), + testName: testName, + cfg: chainConfig, + log: log, } } @@ -115,9 +81,9 @@ func (c *EthereumChain) Initialize(ctx context.Context, testName string, cli *do if err != nil { return fmt.Errorf("creating volume for chain node: %w", err) } - c.VolumeName = v.Name - c.NetworkID = networkID - c.DockerClient = cli + c.volumeName = v.Name + c.networkID = networkID + c.dockerClient = cli if err := dockerutil.SetVolumeOwner(ctx, dockerutil.VolumeOwnerOptions{ Log: c.log, @@ -136,19 +102,15 @@ func (c *EthereumChain) Initialize(ctx context.Context, testName string, cli *do } func (c *EthereumChain) Name() string { - return fmt.Sprintf("anvil-%s-%s", c.cfg.ChainID, dockerutil.SanitizeContainerName(c.testName)) + return fmt.Sprintf("%s-%s-%s-%s", c.cfg.Name, c.cfg.Bin, c.cfg.ChainID, dockerutil.SanitizeContainerName(c.testName)) } func (c *EthereumChain) HomeDir() string { - return "/home/foundry" -} - -func (c *EthereumChain) KeystoreDir() string { - return path.Join(c.HomeDir(), ".foundry", "keystores") + return "/home/ethereum" } func (c *EthereumChain) Bind() []string { - return []string{fmt.Sprintf("%s:%s", c.VolumeName, c.HomeDir())} + return []string{fmt.Sprintf("%s:%s", c.volumeName, c.HomeDir())} } func (c *EthereumChain) pullImages(ctx context.Context, cli *dockerclient.Client) { @@ -171,48 +133,7 @@ func (c *EthereumChain) pullImages(ctx context.Context, cli *dockerclient.Client } } -func (c *EthereumChain) Start(testName string, ctx context.Context, additionalGenesisWallets ...ibc.WalletAmount) error { - // TODO: - // * add support for different denom configuration, ether, gwei or wei, - // this will affect SendFunds, SendFundsWithNote, GetBalance and anything other than wei will lose precision for GetBalance - // * add support for modifying genesis amount config, default is 10 ether - // * add support for ConfigFileOverrides - // * block time - // * add support for custom chain id, must be an int? - // * add support for custom gas-price - // Maybe add code-size-limit configuration for larger contracts - - // IBC support, add when necessary - // * add additionalGenesisWallet support for relayer wallet, either add genesis accounts or tx after chain starts - - cmd := []string{c.cfg.Bin, - "--host", "0.0.0.0", // Anyone can call - "--block-time", "2", // 2 second block times - "--accounts", "10", // We current only use the first account for the faucet, but tests may expect the default - "--balance", "10000000", // Genesis accounts loaded with 10mil ether, change as needed - "--no-cors", - "--gas-price", "20000000000", - "--block-base-fee-per-gas", "0", - } - - var mounts []mount.Mount - if loadState, ok := c.cfg.ConfigFileOverrides["--load-state"].(string); ok { - pwd, err := os.Getwd() - if err != nil { - return err - } - localJsonFile := filepath.Join(pwd, loadState) - dockerJsonFile := path.Join(c.HomeDir(), path.Base(loadState)) - mounts = []mount.Mount{ - { - Type: mount.TypeBind, - Source: localJsonFile, - Target: dockerJsonFile, - }, - } - cmd = append(cmd, "--load-state", dockerJsonFile) - } - +func (c *EthereumChain) Start(ctx context.Context, cmd []string, mount []mount.Mount) error { usingPorts := nat.PortMap{} for k, v := range natPorts { usingPorts[k] = v @@ -230,7 +151,7 @@ func (c *EthereumChain) Start(testName string, ctx context.Context, additionalGe fmt.Printf("Port Overrides: %v. Using: %v\n", c.cfg.HostPortOverride, usingPorts) } - err := c.containerLifecycle.CreateContainer(ctx, c.testName, c.NetworkID, c.cfg.Images[0], usingPorts, c.Bind(), mounts, c.HostName(), cmd, nil, []string{}) + err := c.containerLifecycle.CreateContainer(ctx, c.testName, c.networkID, c.cfg.Images[0], usingPorts, c.Bind(), mount, c.HostName(), cmd, nil, []string{}) if err != nil { return err } @@ -247,7 +168,19 @@ func (c *EthereumChain) Start(testName string, ctx context.Context, additionalGe } c.hostRPCPort = hostPorts[0] - fmt.Println("Host RPC port: ", c.hostRPCPort) + + // wait for rpc to come up + time.Sleep(time.Second * 2) + + // dial the rpc host + c.rpcClient, err = ethclient.Dial(c.GetHostRPCAddress()) + if err != nil { + time.Sleep(time.Second * 2) + c.rpcClient, err = ethclient.Dial(c.GetHostRPCAddress()) + if err != nil { + return fmt.Errorf("failed to dial ETH rpc host(%s): %w", c.GetHostRPCAddress(), err) + } + } return testutil.WaitForBlocks(ctx, 2, c) } @@ -256,12 +189,12 @@ func (c *EthereumChain) HostName() string { return dockerutil.CondenseHostName(c.Name()) } +func (c *EthereumChain) NewJob() *dockerutil.Image { + return dockerutil.NewImage(c.Logger(), c.dockerClient, c.networkID, c.testName, c.cfg.Images[0].Repository, c.cfg.Images[0].Version) +} + func (c *EthereumChain) Exec(ctx context.Context, cmd []string, env []string) (stdout, stderr []byte, err error) { - logger := zap.NewNop() - if cmd[1] != "block-number" { // too much logging, maybe switch to an rpc lib in the future - logger = c.logger() - } - job := dockerutil.NewImage(logger, c.DockerClient, c.NetworkID, c.testName, c.cfg.Images[0].Repository, c.cfg.Images[0].Version) + job := c.NewJob() opts := dockerutil.ContainerOptions{ Env: env, Binds: c.Bind(), @@ -270,7 +203,7 @@ func (c *EthereumChain) Exec(ctx context.Context, cmd []string, env []string) (s return res.Stdout, res.Stderr, res.Err } -func (c *EthereumChain) logger() *zap.Logger { +func (c *EthereumChain) Logger() *zap.Logger { return c.log.With( zap.String("chain_id", c.cfg.ChainID), zap.String("test", c.testName), @@ -293,184 +226,19 @@ func (c *EthereumChain) GetHostWSAddress() string { return "ws://" + c.hostRPCPort } -type NewWalletOutput struct { - Address string `json:"address"` - Path string `json:"path"` -} - -func (c *EthereumChain) MakeKeystoreDir(ctx context.Context) error { - cmd := []string{"mkdir", "-p", c.KeystoreDir()} - _, _, err := c.Exec(ctx, cmd, nil) - return err -} - -func (c *EthereumChain) CreateKey(ctx context.Context, keyName string) error { - err := c.MakeKeystoreDir(ctx) // Ensure keystore directory is created - if err != nil { - return err - } - - _, ok := c.keystoreMap[keyName] - if ok { - return fmt.Errorf("Keyname (%s) already used", keyName) - } - - cmd := []string{"cast", "wallet", "new", c.KeystoreDir(), "--unsafe-password", "", "--json"} - stdout, _, err := c.Exec(ctx, cmd, nil) - if err != nil { - return err - } - - newWallet := []NewWalletOutput{} - err = json.Unmarshal(stdout, &newWallet) - if err != nil { - return err - } - - c.keystoreMap[keyName] = newWallet[0].Path - - return nil -} - -// cast wallet import requires a password prompt which docker isn't properly handling. For now, we only use CreateKey(). -// Can re-add/support with this commit: https://github.com/foundry-rs/foundry/pull/6671 -func (c *EthereumChain) RecoverKey(ctx context.Context, keyName, mnemonic string) error { - err := c.MakeKeystoreDir(ctx) // Ensure keystore directory is created - if err != nil { - return err - } - - cmd := []string{"cast", "wallet", "import", keyName, "--keystore-dir", c.KeystoreDir(), "--mnemonic", mnemonic, "--unsafe-password", ""} - _, _, err = c.Exec(ctx, cmd, nil) - if err != nil { - return err - } - - // This is needed for CreateKey() since that keystore path does not use the keyname - c.keystoreMap[keyName] = path.Join(c.KeystoreDir(), keyName) - - return nil -} - -// Get address of account, cast to a string to use -func (c *EthereumChain) GetAddress(ctx context.Context, keyName string) ([]byte, error) { - keystore, ok := c.keystoreMap[keyName] - if !ok { - return nil, fmt.Errorf("Keyname (%s) not found", keyName) - } - - cmd := []string{"cast", "wallet", "address", "--keystore", keystore, "--password", ""} - stdout, _, err := c.Exec(ctx, cmd, nil) - if err != nil { - return nil, err - } - return []byte(strings.TrimSpace(string(stdout))), nil -} - -func (c *EthereumChain) SendFunds(ctx context.Context, keyName string, amount ibc.WalletAmount) error { - cmd := []string{"cast", "send", amount.Address, "--value", amount.Amount.String()} - if keyName == "faucet" { - cmd = append(cmd, - "--private-key", "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", - "--rpc-url", c.GetRPCAddress(), - ) - - } else { - keystore, ok := c.keystoreMap[keyName] - if !ok { - return fmt.Errorf("keyname (%s) not found", keyName) - } - cmd = append(cmd, - "--keystore", keystore, - "--password", "", - "--rpc-url", c.GetRPCAddress(), - ) - } - _, _, err := c.Exec(ctx, cmd, nil) - return err -} - -type TransactionReceipt struct { - TxHash string `json:"transactionHash"` -} - -func (c *EthereumChain) SendFundsWithNote(ctx context.Context, keyName string, amount ibc.WalletAmount, note string) (string, error) { - cmd := []string{"cast", "send", amount.Address, hexutil.Encode([]byte(note)), "--value", amount.Amount.String(), "--json"} - if keyName == "faucet" { - cmd = append(cmd, - "--private-key", "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", - "--rpc-url", c.GetRPCAddress(), - ) - - } else { - keystore, ok := c.keystoreMap[keyName] - if !ok { - return "", fmt.Errorf("Keyname (%s) not found", keyName) - } - cmd = append(cmd, - "--keystore", keystore, - "--password", "", - "--rpc-url", c.GetRPCAddress(), - ) - } - stdout, _, err := c.Exec(ctx, cmd, nil) - if err != nil { - return "", err - } - - var txReceipt TransactionReceipt - if err = json.Unmarshal(stdout, &txReceipt); err != nil { - return "", err - } - - return txReceipt.TxHash, nil -} - func (c *EthereumChain) Height(ctx context.Context) (int64, error) { - cmd := []string{"cast", "block-number", "--rpc-url", c.GetRPCAddress()} - stdout, _, err := c.Exec(ctx, cmd, nil) + time.Sleep(time.Millisecond * 200) // TODO: slow down WaitForBlocks instead of here + height, err := c.rpcClient.BlockNumber(ctx) if err != nil { - return 0, err + return 0, fmt.Errorf("failed to get height: %w", err) } - return strconv.ParseInt(strings.TrimSpace(string(stdout)), 10, 64) + return int64(height), nil } func (c *EthereumChain) GetBalance(ctx context.Context, address string, denom string) (sdkmath.Int, error) { - cmd := []string{"cast", "balance", "--rpc-url", c.GetRPCAddress(), address} - stdout, _, err := c.Exec(ctx, cmd, nil) - if err != nil { - return sdkmath.ZeroInt(), err - } - balance, ok := sdkmath.NewIntFromString(strings.TrimSpace(string(stdout))) - if !ok { - return sdkmath.ZeroInt(), fmt.Errorf("Error parsing string to sdk int") - } - return balance, nil -} - -func (c *EthereumChain) BuildWallet(ctx context.Context, keyName string, mnemonic string) (ibc.Wallet, error) { - if mnemonic != "" { - err := c.RecoverKey(ctx, keyName, mnemonic) - if err != nil { - return nil, err - } - } else { - // Use the genesis account - if keyName == "faucet" { - // TODO: implement RecoverKey() so faucet can be saved to keystore - return c.genesisWallets.GetFaucetWallet(keyName), nil - } else { - // Create new account - err := c.CreateKey(ctx, keyName) - if err != nil { - return nil, err - } - } - } - - address, err := c.GetAddress(ctx, keyName) + balance, err := c.rpcClient.BalanceAt(ctx, common.Address(hexutil.MustDecode(address)), nil) if err != nil { - return nil, err + return sdkmath.Int{}, fmt.Errorf("failed to get height: %w", err) } - return NewWallet(keyName, string(address)), nil + return sdkmath.NewIntFromBigInt(balance), nil } diff --git a/chain/ethereum/foundry/anvil_chain.go b/chain/ethereum/foundry/anvil_chain.go new file mode 100644 index 000000000..d42b8c7ef --- /dev/null +++ b/chain/ethereum/foundry/anvil_chain.go @@ -0,0 +1,228 @@ +package foundry + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path" + "path/filepath" + "strings" + "sync" + + "github.com/docker/docker/api/types/mount" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum" + "github.com/strangelove-ventures/interchaintest/v8/ibc" + "go.uber.org/zap" +) + +var _ ibc.Chain = &AnvilChain{} + +type AnvilChain struct { + *ethereum.EthereumChain + + keystoreMap map[string]*NodeWallet +} + +func NewAnvilChain(testName string, chainConfig ibc.ChainConfig, log *zap.Logger) *AnvilChain { + return &AnvilChain{ + EthereumChain: ethereum.NewEthereumChain(testName, chainConfig, log), + keystoreMap: make(map[string]*NodeWallet), + } +} + +func (c *AnvilChain) KeystoreDir() string { + return path.Join(c.HomeDir(), ".foundry", "keystores") +} + +func (c *AnvilChain) Start(testName string, ctx context.Context, additionalGenesisWallets ...ibc.WalletAmount) error { + cmd := []string{c.Config().Bin, + "--host", "0.0.0.0", // Anyone can call + "--no-cors", + "--gas-price", c.Config().GasPrices, + } + + cmd = append(cmd, c.Config().AdditionalStartArgs...) + + var mounts []mount.Mount + if loadState, ok := c.Config().ConfigFileOverrides["--load-state"].(string); ok { + pwd, err := os.Getwd() + if err != nil { + return err + } + localJsonFile := filepath.Join(pwd, loadState) + dockerJsonFile := path.Join(c.HomeDir(), path.Base(loadState)) + mounts = []mount.Mount{ + { + Type: mount.TypeBind, + Source: localJsonFile, + Target: dockerJsonFile, + }, + } + cmd = append(cmd, "--load-state", dockerJsonFile) + } + + return c.EthereumChain.Start(ctx, cmd, mounts) +} + +type NewWalletOutput struct { + Address string `json:"address"` + Path string `json:"path"` +} + +func (c *AnvilChain) MakeKeystoreDir(ctx context.Context) error { + cmd := []string{"mkdir", "-p", c.KeystoreDir()} + _, _, err := c.Exec(ctx, cmd, nil) + return err +} + +func (c *AnvilChain) CreateKey(ctx context.Context, keyName string) error { + err := c.MakeKeystoreDir(ctx) // Ensure keystore directory is created + if err != nil { + return err + } + + _, ok := c.keystoreMap[keyName] + if ok { + return fmt.Errorf("keyname (%s) already used", keyName) + } + + cmd := []string{"cast", "wallet", "new", c.KeystoreDir(), "--unsafe-password", "", "--json"} + stdout, _, err := c.Exec(ctx, cmd, nil) + if err != nil { + return err + } + + newWallet := []NewWalletOutput{} + err = json.Unmarshal(stdout, &newWallet) + if err != nil { + return err + } + + c.keystoreMap[keyName] = &NodeWallet{ + keystore: newWallet[0].Path, + } + + return nil +} + +func (c *AnvilChain) RecoverKey(ctx context.Context, keyName, mnemonic string) error { + err := c.MakeKeystoreDir(ctx) // Ensure keystore directory is created + if err != nil { + return err + } + + cmd := []string{"cast", "wallet", "import", keyName, "--keystore-dir", c.KeystoreDir(), "--mnemonic", mnemonic, "--unsafe-password", ""} + _, _, err = c.Exec(ctx, cmd, nil) + if err != nil { + return err + } + + // This is needed for CreateKey() since that keystore path does not use the keyname + c.keystoreMap[keyName] = &NodeWallet{ + keystore: path.Join(c.KeystoreDir(), keyName), + } + + return nil +} + +// Get address of account, cast to a string to use +func (c *AnvilChain) GetAddress(ctx context.Context, keyName string) ([]byte, error) { + account, ok := c.keystoreMap[keyName] + if !ok { + return nil, fmt.Errorf("keyname (%s) not found", keyName) + } + + if account.address != "" { + return hexutil.MustDecode(account.address), nil + } + + cmd := []string{"cast", "wallet", "address", "--keystore", account.keystore, "--password", ""} + stdout, _, err := c.Exec(ctx, cmd, nil) + if err != nil { + return nil, err + } + + addr := strings.TrimSpace(string(stdout)) + account.address = addr + return hexutil.MustDecode(addr), nil +} + +func (c *AnvilChain) SendFunds(ctx context.Context, keyName string, amount ibc.WalletAmount) error { + _, err := c.SendFundsWithNote(ctx, keyName, amount, "") + return err +} + +type TransactionReceipt struct { + TxHash string `json:"transactionHash"` +} + +func (c *AnvilChain) SendFundsWithNote(ctx context.Context, keyName string, amount ibc.WalletAmount, note string) (string, error) { + var cmd []string + if len(note) > 0 { + cmd = []string{"cast", "send", amount.Address, hexutil.Encode([]byte(note)), "--value", amount.Amount.String(), "--json"} + } else { + cmd = []string{"cast", "send", amount.Address, "--value", amount.Amount.String(), "--json"} + } + + account, ok := c.keystoreMap[keyName] + if !ok { + return "", fmt.Errorf("keyname (%s) not found", keyName) + } + cmd = append(cmd, + "--keystore", account.keystore, + "--password", "", + "--rpc-url", c.GetRPCAddress(), + ) + + account.txLock.Lock() + defer account.txLock.Unlock() + stdout, _, err := c.Exec(ctx, cmd, nil) + if err != nil { + return "", fmt.Errorf("send funds, exec, %w", err) + } + + var txReceipt TransactionReceipt + if err = json.Unmarshal([]byte(strings.TrimSpace(string(stdout))), &txReceipt); err != nil { + return "", fmt.Errorf("tx receipt unmarshal:\n %s\nerror: %w", string(stdout), err) + } + + return txReceipt.TxHash, nil +} + +func (c *AnvilChain) BuildWallet(ctx context.Context, keyName string, mnemonic string) (ibc.Wallet, error) { + if mnemonic != "" { + err := c.RecoverKey(ctx, keyName, mnemonic) + if err != nil { + return nil, err + } + } else { + // Use the genesis account + if keyName == "faucet" { + mnemonic = "test test test test test test test test test test test junk" + err := c.RecoverKey(ctx, keyName, mnemonic) + if err != nil { + return nil, err + } + } else { + // Create new account + err := c.CreateKey(ctx, keyName) + if err != nil { + return nil, err + } + } + } + + address, err := c.GetAddress(ctx, keyName) + if err != nil { + return nil, err + } + return ethereum.NewWallet(keyName, address, mnemonic), nil +} + +type NodeWallet struct { + address string + keystore string + txLock sync.Mutex +} diff --git a/chain/ethereum/foundry/default_configs.go b/chain/ethereum/foundry/default_configs.go new file mode 100644 index 000000000..498f132ae --- /dev/null +++ b/chain/ethereum/foundry/default_configs.go @@ -0,0 +1,36 @@ +package foundry + +import ( + "github.com/strangelove-ventures/interchaintest/v8/ibc" +) + +func DefaultEthereumAnvilChainConfig( + name string, +) ibc.ChainConfig { + return ibc.ChainConfig{ + Type: "ethereum", + Name: name, + ChainID: "31337", // default anvil chain-id + Bech32Prefix: "n/a", + CoinType: "60", + Denom: "wei", + GasPrices: "20000000000", // 20 gwei + GasAdjustment: 0, + TrustingPeriod: "0", + NoHostMount: false, + Images: []ibc.DockerImage{ + { + Repository: "ghcr.io/foundry-rs/foundry", + Version: "latest", + UidGid: "1000:1000", + }, + }, + Bin: "anvil", + AdditionalStartArgs: []string{ + "--block-time", "2", // 2 second block times + "--accounts", "10", // We current only use the first account for the faucet, but tests may expect the default + "--balance", "10000000", // Genesis accounts loaded with 10mil ether, change as needed + "--block-base-fee-per-gas", "0", + }, + } +} diff --git a/chain/ethereum/forge.go b/chain/ethereum/foundry/forge.go similarity index 83% rename from chain/ethereum/forge.go rename to chain/ethereum/foundry/forge.go index 0de826523..a37084e83 100644 --- a/chain/ethereum/forge.go +++ b/chain/ethereum/foundry/forge.go @@ -1,7 +1,8 @@ -package ethereum +package foundry import ( "context" + "fmt" "os" "path" "path/filepath" @@ -21,19 +22,15 @@ type ForgeScriptOpts struct { } // Add private-key or keystore to cmd -func (c *EthereumChain) AddKey(cmd []string, keyName string) []string { - // choose whether to use private-key or keystore - if keyName == "faucet" { - cmd = append(cmd, - "--private-key", "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", - ) - - } else { - cmd = append(cmd, - "--keystores", c.keystoreMap[keyName], - "--password", "", - ) +func (c *AnvilChain) AddKey(cmd []string, keyName string) []string { + account, ok := c.keystoreMap[keyName] + if !ok { + panic(fmt.Sprintf("Keyname (%s) not found", keyName)) } + cmd = append(cmd, + "--keystores", account.keystore, + "--password", "", + ) return cmd } @@ -78,7 +75,13 @@ func WriteConfigFile(configFile string, localContractRootDir string, solidityCon // Run "forge script" // see: https://book.getfoundry.sh/reference/forge/forge-script -func (c *EthereumChain) ForgeScript(ctx context.Context, keyName string, opts ForgeScriptOpts) (stdout, stderr []byte, err error) { +func (c *AnvilChain) ForgeScript(ctx context.Context, keyName string, opts ForgeScriptOpts) (stdout, stderr []byte, err error) { + account, ok := c.keystoreMap[keyName] + if !ok { + return nil, nil, fmt.Errorf("keyname (%s) not found", keyName) + } + account.txLock.Lock() + defer account.txLock.Unlock() pwd, err := os.Getwd() if err != nil { return nil, nil, err @@ -96,7 +99,7 @@ func (c *EthereumChain) ForgeScript(ctx context.Context, keyName string, opts Fo return nil, nil, err } - job := dockerutil.NewImage(c.logger(), c.DockerClient, c.NetworkID, c.testName, c.cfg.Images[0].Repository, c.cfg.Images[0].Version) + job := c.NewJob() containerOpts := dockerutil.ContainerOptions{ Binds: c.Bind(), Mounts: []mount.Mount{ diff --git a/chain/ethereum/geth/default_configs.go b/chain/ethereum/geth/default_configs.go new file mode 100644 index 000000000..a38235c8f --- /dev/null +++ b/chain/ethereum/geth/default_configs.go @@ -0,0 +1,78 @@ +package geth + +import ( + "github.com/strangelove-ventures/interchaintest/v8/ibc" +) + +func DefaultEthereumGethChainConfig( + name string, +) ibc.ChainConfig { + return ibc.ChainConfig{ + Type: "ethereum", + Name: name, + ChainID: "1337", // default geth chain-id + Bech32Prefix: "n/a", + CoinType: "60", + Denom: "wei", + GasPrices: "2000000000", // 2gwei, default 1M + GasAdjustment: 0, + TrustingPeriod: "0", + NoHostMount: false, + Images: []ibc.DockerImage{ + { + Repository: "ethereum/client-go", + Version: "v1.14.7", + UidGid: "1025:1025", + }, + }, + Bin: "geth", + AdditionalStartArgs: []string{ + "--dev.period", "2", // 2 second block time + "--verbosity", "4", // Level = debug + "--networkid", "15", + "--rpc.txfeecap", "50.0", // 50 eth + "--rpc.gascap", "30000000", //30M + "--gpo.percentile", "150", // default 60 + "--gpo.ignoreprice", "1000000000", // 1gwei, default 2 + "--dev.gaslimit", "30000000", // 30M, default 11.5M + "--rpc.enabledeprecatedpersonal", // required (in this version) for recover key and unlocking accounts + }, + } +} + +func DefaultBscChainConfig( + name string, +) ibc.ChainConfig { + return ibc.ChainConfig{ + Type: "ethereum", + Name: name, + ChainID: "11337", + Bech32Prefix: "n/a", + CoinType: "60", + Denom: "wei", + GasPrices: "2000000000", // 2gwei, default 1M + GasAdjustment: 0, + TrustingPeriod: "0", + NoHostMount: false, + Images: []ibc.DockerImage{ + { + Repository: "ghcr.io/bnb-chain/bsc", + Version: "1.2.13", // same version as other sim tests + //Version: "1.4.13", // this version does not work in dev mode (1.3.x+) + UidGid: "1000:1000", + }, + }, + Bin: "geth", + AdditionalStartArgs: []string{ + "-mine", + "--dev.period", "2", // 2 second block time + "--verbosity", "4", // Level = debug + "--networkid", "15", + "--rpc.txfeecap", "50.0", // 50 eth + "--rpc.gascap", "30000000", //30M + "--gpo.percentile", "150", // default 60 + "--gpo.ignoreprice", "1000000000", // 1gwei, default 2 + "--dev.gaslimit", "30000000", // 30M, default 11.5M + }, + } +} diff --git a/chain/ethereum/geth/geth_chain.go b/chain/ethereum/geth/geth_chain.go new file mode 100644 index 000000000..cf9538870 --- /dev/null +++ b/chain/ethereum/geth/geth_chain.go @@ -0,0 +1,266 @@ +package geth + +import ( + "context" + "encoding/hex" + "fmt" + "strings" + "sync" + "time" + + "github.com/cosmos/cosmos-sdk/crypto/hd" + + "github.com/docker/docker/api/types/mount" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum" + "github.com/strangelove-ventures/interchaintest/v8/ibc" + "github.com/strangelove-ventures/interchaintest/v8/testutil" + "go.uber.org/zap" +) + +var _ ibc.Chain = &GethChain{} + +type GethChain struct { + *ethereum.EthereumChain + + keynameToAccountMap map[string]*NodeWallet + nextAcctNum int +} + +func NewGethChain(testName string, chainConfig ibc.ChainConfig, log *zap.Logger) *GethChain { + return &GethChain{ + EthereumChain: ethereum.NewEthereumChain(testName, chainConfig, log), + keynameToAccountMap: map[string]*NodeWallet{ + "faucet": { + accountNum: 0, + }, + }, + nextAcctNum: 1, + } +} + +func (c *GethChain) Start(testName string, ctx context.Context, additionalGenesisWallets ...ibc.WalletAmount) error { + cmd := []string{c.Config().Bin, + "--dev", "--datadir", c.HomeDir(), "-http", "--http.addr", "0.0.0.0", "--http.port", "8545", "--allow-insecure-unlock", + "--http.api", "eth,net,web3,miner,personal,txpool,debug", "--http.corsdomain", "*", "-nodiscover", "--http.vhosts=*", + "--miner.gasprice", c.Config().GasPrices, + "--rpc.allow-unprotected-txs", + } + + cmd = append(cmd, c.Config().AdditionalStartArgs...) + + return c.EthereumChain.Start(ctx, cmd, []mount.Mount{}) +} + +// JavaScriptExec() - Execute web3 code via geth's attach command +func (c *GethChain) JavaScriptExec(ctx context.Context, jsCmd string) (stdout, stderr []byte, err error) { + cmd := []string{c.Config().Bin, "--exec", jsCmd, "--datadir", c.HomeDir(), "attach"} + return c.Exec(ctx, cmd, nil) +} + +// JavaScriptExecTx() - Execute a tx via web3, function ensures account is unlocked and blocks multiple txs +func (c *GethChain) JavaScriptExecTx(ctx context.Context, account *NodeWallet, jsCmd string) (stdout, stderr []byte, err error) { + if err := c.UnlockAccount(ctx, account); err != nil { + return nil, nil, err + } + + account.txLock.Lock() + defer account.txLock.Unlock() + stdout, stderr, err = c.JavaScriptExec(ctx, jsCmd) + if err != nil { + return nil, nil, err + } + + err = testutil.WaitForBlocks(ctx, 2, c) + return stdout, stderr, err +} + +func (c *GethChain) CreateKey(ctx context.Context, keyName string) error { + _, ok := c.keynameToAccountMap[keyName] + if ok { + return fmt.Errorf("keyname (%s) already used", keyName) + } + + cmd := []string{ + "sh", + "-c", + fmt.Sprintf(`cat < 3 { + return nil, fmt.Errorf("getAddress(): Keyname (%s) with account (%d) not found", + keyName, account.accountNum) + } + } + + return hexutil.MustDecode(strings.Trim(strings.TrimSpace(string(stdout)), "\"")), nil +} + +// UnlockAccount() unlocks a non-default account for use. We will unlock when sending funds and deploying contracts. +// Accounts are unlocked for 100 seconds which is plenty of time for the transaction. +func (c *GethChain) UnlockAccount(ctx context.Context, account *NodeWallet) error { + // shouldn't need to unlock the default account + if account.accountNum == 0 { + return nil + } + + _, _, err := c.JavaScriptExec(ctx, fmt.Sprintf("personal.unlockAccount(eth.accounts[%d], \"\", 100)", account.accountNum)) + + return err +} + +func (c *GethChain) SendFunds(ctx context.Context, keyName string, amount ibc.WalletAmount) error { + _, err := c.SendFundsWithNote(ctx, keyName, amount, "") + return err +} + +func (c *GethChain) SendFundsWithNote(ctx context.Context, keyName string, amount ibc.WalletAmount, note string) (string, error) { + account, found := c.keynameToAccountMap[keyName] + if !found { + return "", fmt.Errorf("keyname (%s) not found", keyName) + } + + var cmd string + if len(note) > 0 { + cmd = fmt.Sprintf("eth.sendTransaction({from: eth.accounts[%d],to: %q,value: %s,data: \"%s\"});", + account.accountNum, amount.Address, amount.Amount, hexutil.Encode([]byte(note))) + } else { + cmd = fmt.Sprintf("eth.sendTransaction({from: eth.accounts[%d],to: %q,value: %s});", + account.accountNum, amount.Address, amount.Amount) + } + stdout, _, err := c.JavaScriptExecTx(ctx, account, cmd) + if err != nil { + return "", err + } + return strings.Trim(strings.TrimSpace(string(stdout)), "\""), nil +} + +// DeployContract creates a new contract on-chain, returning the contract address +// Constructor params are appended to the byteCode +func (c *GethChain) DeployContract(ctx context.Context, keyName string, abi []byte, byteCode []byte) (string, error) { + account, found := c.keynameToAccountMap[keyName] + if !found { + return "", fmt.Errorf("SendFundsWithNote(): Keyname (%s) not found", keyName) + } + + stdout, _, err := c.JavaScriptExecTx(ctx, account, + fmt.Sprintf("eth.contract(abi=%s).new({from: eth.accounts[%d], data: %q, gas: 20000000}).transactionHash", + abi, account.accountNum, byteCode), + ) + if err != nil { + return "", err + } + + txHash := strings.TrimSpace(string(stdout)) + status, _, err := c.JavaScriptExec(ctx, fmt.Sprintf("eth.getTransactionReceipt(%s).status", txHash)) + if err != nil { + return "", err + } + + if strings.Trim(strings.TrimSpace(string(status)), "\"") == "0x0" { + return "", fmt.Errorf("contract deployment failed") + } + + stdout, _, err = c.JavaScriptExec(ctx, fmt.Sprintf("eth.getTransactionReceipt(%s).contractAddress", txHash)) + if err != nil { + return "", err + } + + return strings.Trim(strings.TrimSpace(string(stdout)), "\""), nil +} + +func (c *GethChain) BuildWallet(ctx context.Context, keyName string, mnemonic string) (ibc.Wallet, error) { + if mnemonic != "" { + err := c.RecoverKey(ctx, keyName, mnemonic) + if err != nil { + return nil, err + } + } else { + // faucet is created when the chain starts and will be account #0 + if keyName == "faucet" { + return ethereum.NewWallet(keyName, []byte{}, mnemonic), nil + } else { + // Create new account + err := c.CreateKey(ctx, keyName) + if err != nil { + return nil, err + } + } + } + + address, err := c.GetAddress(ctx, keyName) + if err != nil { + return nil, err + } + return ethereum.NewWallet(keyName, address, mnemonic), nil +} + +type NodeWallet struct { + accountNum int + address string + txLock sync.Mutex +} diff --git a/chain/ethereum/wallet.go b/chain/ethereum/wallet.go index 385da7343..86e6688a7 100644 --- a/chain/ethereum/wallet.go +++ b/chain/ethereum/wallet.go @@ -8,14 +8,16 @@ import ( var _ ibc.Wallet = &EthereumWallet{} type EthereumWallet struct { - address string - keyName string + address []byte + keyName string + mnemonic string } -func NewWallet(keyname string, address string) ibc.Wallet { +func NewWallet(keyname string, address []byte, mnemonic string) ibc.Wallet { return &EthereumWallet{ - address: address, - keyName: keyname, + address: address, + keyName: keyname, + mnemonic: mnemonic, } } @@ -25,29 +27,15 @@ func (w *EthereumWallet) KeyName() string { // Get formatted address, passing in a prefix func (w *EthereumWallet) FormattedAddress() string { - return w.address + return hexutil.Encode(w.address) } // Get mnemonic, only used for relayer wallets func (w *EthereumWallet) Mnemonic() string { - return "" + return w.mnemonic } // Get Address with chain's prefix func (w *EthereumWallet) Address() []byte { - return hexutil.MustDecode(w.address) -} - -type GenesisWallets struct { - total uint32 -} - -func NewGenesisWallet() GenesisWallets { - return GenesisWallets{ - total: 2, // Start with 2 at genesis, one for faucet, one for relayer - } -} - -func (w *GenesisWallets) GetFaucetWallet(keyname string) ibc.Wallet { - return NewWallet(keyname, "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266") + return w.address } diff --git a/chain/thorchain/thornode.go b/chain/thorchain/thornode.go index 06c9134c7..b7c8d9309 100644 --- a/chain/thorchain/thornode.go +++ b/chain/thorchain/thornode.go @@ -395,6 +395,7 @@ func (tn *ChainNode) SetPeers(ctx context.Context, peers string) error { } func (tn *ChainNode) Height(ctx context.Context) (int64, error) { + time.Sleep(time.Millisecond * 200) // TODO: slow down WaitForBlocks instead of here res, err := tn.Client.Status(ctx) if err != nil { return 0, fmt.Errorf("tendermint rpc client status: %w", err) diff --git a/chain/utxo/cli.go b/chain/utxo/cli.go index d5b701a8d..84138c22f 100644 --- a/chain/utxo/cli.go +++ b/chain/utxo/cli.go @@ -185,7 +185,7 @@ func (c *UtxoChain) SetAccount(ctx context.Context, addr string, keyName string) // sendToMwebAddress is used for creating the mweb transaction needed at block 431 // no other use case is currently supported func (c *UtxoChain) sendToMwebAddress(ctx context.Context, keyName string, addr string, amount float64) error { - _, err := c.getWalletForUse(keyName) + wallet, err := c.getWalletForUse(keyName) if err != nil { return err } @@ -200,7 +200,9 @@ func (c *UtxoChain) sendToMwebAddress(ctx context.Context, keyName string, addr fmt.Sprintf("amount=%.8f", amount), ) + wallet.txLock.Lock() _, _, err = c.Exec(ctx, cmd, nil) + wallet.txLock.Unlock() if err != nil { return err } diff --git a/chain/utxo/default_configs.go b/chain/utxo/default_configs.go index 45af5e7f3..cd42df4d3 100644 --- a/chain/utxo/default_configs.go +++ b/chain/utxo/default_configs.go @@ -19,7 +19,7 @@ func DefaultBitcoinChainConfig( CoinType: "0", Denom: "sat", GasPrices: "0.00001", // min fee / kb - GasAdjustment: 2, // min fee multiplier + GasAdjustment: 4, // min fee multiplier TrustingPeriod: "0", NoHostMount: false, Images: []ibc.DockerImage{ @@ -52,7 +52,7 @@ func DefaultBitcoinCashChainConfig( CoinType: "145", Denom: "sat", GasPrices: "0.00001", // min fee / kb - GasAdjustment: 2, // min fee multiplier + GasAdjustment: 4, // min fee multiplier TrustingPeriod: "0", NoHostMount: false, Images: []ibc.DockerImage{ @@ -85,7 +85,7 @@ func DefaultLitecoinChainConfig( CoinType: "2", Denom: "sat", GasPrices: "0.0001", // min fee / kb - GasAdjustment: 2, // min fee multiplier + GasAdjustment: 4, // min fee multiplier TrustingPeriod: "0", NoHostMount: false, Images: []ibc.DockerImage{ @@ -118,7 +118,7 @@ func DefaultDogecoinChainConfig( CoinType: "3", Denom: "sat", GasPrices: "0.01", // min fee / kb - GasAdjustment: 2, // min fee multiplier + GasAdjustment: 4, // min fee multiplier TrustingPeriod: "0", NoHostMount: false, Images: []ibc.DockerImage{ diff --git a/chain/utxo/utxo_chain.go b/chain/utxo/utxo_chain.go index 17d285555..bc981ce73 100644 --- a/chain/utxo/utxo_chain.go +++ b/chain/utxo/utxo_chain.go @@ -415,6 +415,13 @@ func (c *UtxoChain) SendFundsWithNote(ctx context.Context, keyName string, amoun return "", err } + wallet, err := c.getWalletForUse(keyName) + if err != nil { + return "", err + } + wallet.txLock.Lock() + defer wallet.txLock.Unlock() + // get utxo listUtxo, err := c.ListUnspent(ctx, keyName) if err != nil { @@ -447,6 +454,7 @@ func (c *UtxoChain) SendFundsWithNote(ctx context.Context, keyName string, amoun } func (c *UtxoChain) Height(ctx context.Context) (int64, error) { + time.Sleep(time.Millisecond * 200) // TODO: slow down WaitForBlocks instead of here cmd := append(c.BaseCli, "getblockcount") stdout, _, err := c.Exec(ctx, cmd, nil) if err != nil { diff --git a/chain/utxo/wallet.go b/chain/utxo/wallet.go index 26c00d2b0..3cacf32e0 100644 --- a/chain/utxo/wallet.go +++ b/chain/utxo/wallet.go @@ -44,6 +44,7 @@ type NodeWallet struct { keyName string address string mu sync.Mutex + txLock sync.Mutex loadCount int ready bool } diff --git a/chainfactory.go b/chainfactory.go index fef1e1e0a..124b8a19d 100644 --- a/chainfactory.go +++ b/chainfactory.go @@ -8,7 +8,8 @@ import ( "sync" "github.com/strangelove-ventures/interchaintest/v8/chain/cosmos" - "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum" + "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum/foundry" + "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum/geth" "github.com/strangelove-ventures/interchaintest/v8/chain/penumbra" "github.com/strangelove-ventures/interchaintest/v8/chain/polkadot" "github.com/strangelove-ventures/interchaintest/v8/chain/thorchain" @@ -157,7 +158,14 @@ func buildChain(log *zap.Logger, testName string, cfg ibc.ChainConfig, numValida return nil, fmt.Errorf("unexpected error, unknown polkadot parachain: %s", cfg.Name) } case "ethereum": - return ethereum.NewEthereumChain(testName, cfg, log), nil + switch cfg.Bin { + case "anvil": + return foundry.NewAnvilChain(testName, cfg, log), nil + case "geth": + return geth.NewGethChain(testName, cfg, log), nil + default: + return nil, fmt.Errorf("unknown binary: %s for ethereum chain type, must be anvil or geth", cfg.Bin) + } case "thorchain": return thorchain.NewThorchain(testName, cfg, nv, nf, log), nil case "utxo": diff --git a/examples/ethereum/start_test.go b/examples/ethereum/foundry_test.go similarity index 94% rename from examples/ethereum/start_test.go rename to examples/ethereum/foundry_test.go index 7e4278dc0..12a38cca5 100644 --- a/examples/ethereum/start_test.go +++ b/examples/ethereum/foundry_test.go @@ -9,6 +9,7 @@ import ( "cosmossdk.io/math" "github.com/strangelove-ventures/interchaintest/v8" "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum" + "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum/foundry" "github.com/strangelove-ventures/interchaintest/v8/ibc" "github.com/strangelove-ventures/interchaintest/v8/testreporter" @@ -16,7 +17,7 @@ import ( "go.uber.org/zap/zaptest" ) -func TestEthereum(t *testing.T) { +func TestFoundry(t *testing.T) { if testing.Short() { t.Skip() @@ -36,7 +37,7 @@ func TestEthereum(t *testing.T) { ctx := context.Background() // Get default ethereum chain config for anvil - anvilConfig := ethereum.DefaultEthereumAnvilChainConfig("ethereum") + anvilConfig := foundry.DefaultEthereumAnvilChainConfig("ethereum") // add --load-state config (this step is not required for tests that don't require an existing state) configFileOverrides := make(map[string]any) @@ -55,7 +56,7 @@ func TestEthereum(t *testing.T) { chains, err := cf.Chains(t.Name()) require.NoError(t, err) - ethereumChain := chains[0].(*ethereum.EthereumChain) + ethereumChain := chains[0].(*foundry.AnvilChain) ic := interchaintest.NewInterchain(). AddChain(ethereumChain) diff --git a/examples/ethereum/geth_test.go b/examples/ethereum/geth_test.go new file mode 100644 index 000000000..e3232fdc0 --- /dev/null +++ b/examples/ethereum/geth_test.go @@ -0,0 +1,95 @@ +package ethereum_test + +import ( + "context" + + "fmt" + "strings" + "testing" + "time" + + "github.com/strangelove-ventures/interchaintest/v8" + "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum" + "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum/geth" + "github.com/strangelove-ventures/interchaintest/v8/ibc" + + "github.com/strangelove-ventures/interchaintest/v8/testreporter" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zaptest" +) + +func TestGeth(t *testing.T) { + + if testing.Short() { + t.Skip() + } + + t.Parallel() + + client, network := interchaintest.DockerSetup(t) + + // Log location + f, err := interchaintest.CreateLogFile(fmt.Sprintf("%d.json", time.Now().Unix())) + require.NoError(t, err) + // Reporter/logs + rep := testreporter.NewReporter(f) + eRep := rep.RelayerExecReporter(t) + + ctx := context.Background() + + // Get default ethereum chain config for geth + gethConfig := geth.DefaultEthereumGethChainConfig("ethereum") + + cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{ + {ChainConfig: gethConfig}, + }) + + chains, err := cf.Chains(t.Name()) + require.NoError(t, err) + + ethereumChain := chains[0].(*geth.GethChain) + + ic := interchaintest.NewInterchain(). + AddChain(ethereumChain) + + require.NoError(t, ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{ + TestName: t.Name(), + Client: client, + NetworkID: network, + SkipPathCreation: true, // Skip path creation, so we can have granular control over the process + })) + fmt.Println("Interchain built") + + // Create and fund a user using GetAndFundTestUsers + ethUserInitialAmount := ethereum.ETHER.MulRaw(1000) + users := interchaintest.GetAndFundTestUsers(t, ctx, "user", ethUserInitialAmount, ethereumChain) + ethUser := users[0] + + // Check balances of user + balance, err := ethereumChain.GetBalance(ctx, ethUser.FormattedAddress(), "") + require.NoError(t, err) + require.True(t, balance.Equal(ethUserInitialAmount)) + + ethUser2, err := interchaintest.GetAndFundTestUserWithMnemonic(ctx, "user2", strings.Repeat("dog ", 23)+"fossil", ethUserInitialAmount, ethereumChain) + require.NoError(t, err) + + balance, err = ethereumChain.GetBalance(ctx, ethUser2.FormattedAddress(), "") + require.NoError(t, err) + require.True(t, balance.Equal(ethUserInitialAmount)) + + txHash, err := ethereumChain.SendFundsWithNote(ctx, ethUser2.KeyName(), ibc.WalletAmount{ + Address: ethUser.FormattedAddress(), + Amount: ethUserInitialAmount.QuoRaw(10), + Denom: ethereumChain.Config().Denom, + }, "memo") + require.NoError(t, err) + require.NotEmpty(t, txHash) + + balance, err = ethereumChain.GetBalance(ctx, ethUser.FormattedAddress(), "") + require.NoError(t, err) + require.True(t, balance.Equal(ethUserInitialAmount.Add(ethUserInitialAmount.QuoRaw(10)))) +} + +type ContractOutput struct { + TxHash string `json:"transactionHash"` +} diff --git a/examples/thorchain/chainspec_exochains.go b/examples/thorchain/chainspec_exochains.go index 4b98f1ba5..002889e76 100644 --- a/examples/thorchain/chainspec_exochains.go +++ b/examples/thorchain/chainspec_exochains.go @@ -3,7 +3,8 @@ package thorchain_test import ( "github.com/strangelove-ventures/interchaintest/v8" "github.com/strangelove-ventures/interchaintest/v8/chain/cosmos" - "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum" + "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum/foundry" + "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum/geth" "github.com/strangelove-ventures/interchaintest/v8/chain/thorchain/common" "github.com/strangelove-ventures/interchaintest/v8/chain/utxo" "github.com/strangelove-ventures/interchaintest/v8/ibc" @@ -15,7 +16,6 @@ type ExoChain struct { chain ibc.Chain lpers []ibc.Wallet savers []ibc.Wallet - arbers []ibc.Wallet genWallets []ibc.Wallet } @@ -58,14 +58,28 @@ func GaiaChainSpec() *interchaintest.ChainSpec { } } -func EthChainSpec() *interchaintest.ChainSpec { +func EthChainSpec(chainType string) *interchaintest.ChainSpec { ethChainName := common.ETHChain.String() // must use this name for test + chainConfig := geth.DefaultEthereumGethChainConfig(ethChainName) + if chainType == "anvil" { + chainConfig = foundry.DefaultEthereumAnvilChainConfig(ethChainName) + } + return &interchaintest.ChainSpec{ ChainName: ethChainName, Name: ethChainName, - Version: "latest", - ChainConfig: ethereum.DefaultEthereumAnvilChainConfig(ethChainName), + ChainConfig: chainConfig, + } +} + +func BscChainSpec() *interchaintest.ChainSpec { + bscChainName := common.BSCChain.String() // must use this name for test + + return &interchaintest.ChainSpec{ + ChainName: bscChainName, + Name: bscChainName, + ChainConfig: geth.DefaultBscChainConfig(bscChainName), } } @@ -75,7 +89,6 @@ func BtcChainSpec() *interchaintest.ChainSpec { return &interchaintest.ChainSpec{ ChainName: btcChainName, Name: btcChainName, - Version: "26.2", ChainConfig: utxo.DefaultBitcoinChainConfig(btcChainName, "thorchain", "password"), } } @@ -86,7 +99,6 @@ func BchChainSpec() *interchaintest.ChainSpec { return &interchaintest.ChainSpec{ ChainName: bchChainName, Name: bchChainName, - Version: "27.1.0", ChainConfig: utxo.DefaultBitcoinCashChainConfig(bchChainName, "thorchain", "password"), } } @@ -97,7 +109,6 @@ func LtcChainSpec() *interchaintest.ChainSpec { return &interchaintest.ChainSpec{ ChainName: liteChainName, Name: liteChainName, - Version: "0.21", ChainConfig: utxo.DefaultLitecoinChainConfig(liteChainName, "thorchain", "password"), } } @@ -108,7 +119,6 @@ func DogeChainSpec() *interchaintest.ChainSpec { return &interchaintest.ChainSpec{ ChainName: dogeChainName, Name: dogeChainName, - Version: "dogecoin-daemon-1.14.7", ChainConfig: utxo.DefaultDogecoinChainConfig(dogeChainName, "thorchain", "password"), } } diff --git a/examples/thorchain/chainspec_thorchain.go b/examples/thorchain/chainspec_thorchain.go index 50095487c..de750d711 100644 --- a/examples/thorchain/chainspec_thorchain.go +++ b/examples/thorchain/chainspec_thorchain.go @@ -25,20 +25,23 @@ type ChainContract struct { Router string `json:"router"` } -func ThorchainDefaultChainSpec(testName string, numVals int, numFn int, ethRouter string, thornodeEnvOverrides, bifrostEnvOverrides map[string]string) *interchaintest.ChainSpec { +func ThorchainDefaultChainSpec(testName string, numVals int, numFn int, ethRouter string, bscRouter string, thornodeEnvOverrides, bifrostEnvOverrides map[string]string) *interchaintest.ChainSpec { chainID := "thorchain" name := common.THORChain.String() // Must use this name for test chainImage := ibc.NewDockerImage("thorchain", "local", "1025:1025") genesisKVMods := []thorchain.GenesisKV{ thorchain.NewGenesisKV("app_state.bank.params.default_send_enabled", false), // disable bank module transfers - thorchain.NewGenesisKV("app_state.transfer.params.send_enabled", false), // disable ibc transfer sends thorchain.NewGenesisKV("app_state.thorchain.reserve", "22000000000000000"), // mint to reserve for mocknet (220M) thorchain.NewGenesisKV("app_state.thorchain.chain_contracts", []ChainContract{ { Chain: "ETH", Router: ethRouter, }, - }), // mint to reserve for mocknet (220M) + { + Chain: "BSC", + Router: bscRouter, + }, + }), } thornodeEnv := thornodeDefaults @@ -93,7 +96,7 @@ func ThorchainDefaultChainSpec(testName string, numVals int, numFn int, ethRoute HomeDir: "/var/data/bifrost", Ports: []string{"5040", "6040", "9000"}, //StartCmd: []string{"bifrost", "-p"}, - StartCmd: []string{"bifrost", "-p", "-l", "debug"}, + StartCmd: []string{"bifrost", "-p", "-l", "debug"}, Env: bifrostEnv, PreStart: false, ValidatorProcess: true, @@ -162,11 +165,6 @@ var ( "BIFROST_CHAINS_AVAX_BLOCK_SCANNER_MAX_GAS_LIMIT=80000", "BIFROST_CHAINS_BSC_BLOCK_SCANNER_MAX_GAS_LIMIT=80000", - // enable bsc - //"BIFROST_CHAINS_BSC_DISABLED=false", // todo change to false once brought in - //"BIFROST_CHAINS_BSC_RPC_HOST: ${BSC_HOST:-http://binance-smart:8545} - //"BIFROST_CHAINS_BSC_BLOCK_SCANNER_RPC_HOST: ${BSC_HOST:-http://binance-smart:8545} - // set fixed gas rate for evm chains "BIFROST_CHAINS_ETH_BLOCK_SCANNER_FIXED_GAS_RATE=30000000000", // 30 gwei "BIFROST_CHAINS_AVAX_BLOCK_SCANNER_FIXED_GAS_RATE=100_000_000_000", // 100 navax diff --git a/examples/thorchain/contracts/eth-router-abi.json b/examples/thorchain/contracts/eth-router-abi.json new file mode 100644 index 000000000..17026c0bb --- /dev/null +++ b/examples/thorchain/contracts/eth-router-abi.json @@ -0,0 +1,308 @@ +[ + { + "inputs": [ + { "internalType": "address", "name": "rune", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldVault", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newVault", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "TransferAllowance", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vault", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "TransferOut", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vault", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "finalAsset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "TransferOutAndCall", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldVault", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newVault", + "type": "address" + }, + { + "components": [ + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "indexed": false, + "internalType": "struct THORChain_Router.Coin[]", + "name": "coins", + "type": "tuple[]" + }, + { + "indexed": false, + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "VaultTransfer", + "type": "event" + }, + { + "inputs": [], + "name": "RUNE", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address payable", "name": "vault", "type": "address" }, + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "string", "name": "memo", "type": "string" } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address payable", "name": "vault", "type": "address" }, + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "string", "name": "memo", "type": "string" }, + { "internalType": "uint256", "name": "expiration", "type": "uint256" } + ], + "name": "depositWithExpiry", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "router", "type": "address" }, + { + "internalType": "address payable", + "name": "asgard", + "type": "address" + }, + { + "components": [ + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "internalType": "struct THORChain_Router.Coin[]", + "name": "coins", + "type": "tuple[]" + }, + { "internalType": "string", "name": "memo", "type": "string" } + ], + "name": "returnVaultAssets", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "router", "type": "address" }, + { "internalType": "address", "name": "newVault", "type": "address" }, + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "string", "name": "memo", "type": "string" } + ], + "name": "transferAllowance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address payable", "name": "to", "type": "address" }, + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "string", "name": "memo", "type": "string" } + ], + "name": "transferOut", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "target", + "type": "address" + }, + { "internalType": "address", "name": "finalToken", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amountOutMin", "type": "uint256" }, + { "internalType": "string", "name": "memo", "type": "string" } + ], + "name": "transferOutAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "vault", "type": "address" }, + { "internalType": "address", "name": "token", "type": "address" } + ], + "name": "vaultAllowance", + "outputs": [ + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/examples/thorchain/contracts/eth-router-bytecode.txt b/examples/thorchain/contracts/eth-router-bytecode.txt new file mode 100644 index 000000000..ce3557b53 --- /dev/null +++ b/examples/thorchain/contracts/eth-router-bytecode.txt @@ -0,0 +1 @@ +0x608060405234801561001057600080fd5b5060405161149e38038061149e83398101604081905261002f91610059565b600080546001600160a01b0319166001600160a01b03929092169190911790556001600255610089565b60006020828403121561006b57600080fd5b81516001600160a01b038116811461008257600080fd5b9392505050565b611406806100986000396000f3fe60806040526004361061007b5760003560e01c80634039fd4b1161004e5780634039fd4b1461012157806344bc937b14610134578063574da7171461014757806393e4eaa91461015a57600080fd5b806303b6a673146100805780631b738b32146100d95780631fece7b4146100fb5780632923e82e1461010e575b600080fd5b34801561008c57600080fd5b506100c661009b366004610d91565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6040519081526020015b60405180910390f35b3480156100e557600080fd5b506100f96100f4366004610eaa565b610192565b005b6100f9610109366004610f29565b610248565b6100f961011c366004610f95565b61048d565b6100f961012f366004610eaa565b610611565b6100f96101423660046110a8565b61079d565b6100f9610155366004610f29565b6107ff565b34801561016657600080fd5b5060005461017a906001600160a01b031681565b6040516001600160a01b0390911681526020016100d0565b60028054036101bc5760405162461bcd60e51b81526004016101b39061111c565b60405180910390fd5b60028055306001600160a01b0386160361022f576101db8484846109ee565b836001600160a01b0316336001600160a01b03167f05b90458f953d3fcb2d7fb25616a2fddeca749d0c47cc5c9832d0266b5346eea858585604051610222939291906111af565b60405180910390a361023c565b61023c8585858585610a67565b50506001600255505050565b60028054036102695760405162461bcd60e51b81526004016101b39061111c565b6002805560006001600160a01b0384166102b9575060405134906000906001600160a01b0387169083156108fc0290849084818181858888f193505050509050806102b357600080fd5b50610434565b34156102f85760405162461bcd60e51b815260206004820152600e60248201526d0eadccaf0e0cac6e8cac840cae8d60931b60448201526064016101b3565b6000546001600160a01b03908116908516036103e857506000546040516302ccb1b360e41b81523060048201526024810184905283916001600160a01b031690632ccb1b30906044016020604051808303816000875af1158015610360573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061038491906111df565b50600054604051630852cd8d60e31b8152600481018590526001600160a01b03909116906342966c6890602401600060405180830381600087803b1580156103cb57600080fd5b505af11580156103df573d6000803e3d6000fd5b50505050610434565b6103f28484610bb8565b6001600160a01b03808716600090815260016020908152604080832093891683529290529081208054929350839290919061042e90849061121e565b90915550505b836001600160a01b0316856001600160a01b03167fef519b7eb82aaf6ac376a6df2d793843ebfd593de5f1a0601d3cc6ab49ebb3958385604051610479929190611236565b60405180910390a350506001600255505050565b60028054036104ae5760405162461bcd60e51b81526004016101b39061111c565b60028055306001600160a01b038516036105785760005b825181101561052557610513848483815181106104e4576104e4611257565b60200260200101516000015185848151811061050257610502611257565b6020026020010151602001516109ee565b8061051d8161126d565b9150506104c5565b50826001600160a01b0316336001600160a01b03167f281daef48d91e5cd3d32db0784f6af69cd8d8d2e8c612a3568dca51ded51e08f848460405161056b929190611286565b60405180910390a36105df565b60005b82518110156105dd576105cb858585848151811061059b5761059b611257565b6020026020010151600001518685815181106105b9576105b9611257565b60200260200101516020015186610a67565b806105d58161126d565b91505061057b565b505b6040516000906001600160a01b038516903480156108fc029184818181858888f1935050505090508061023c57600080fd5b60028054036106325760405162461bcd60e51b81526004016101b39061111c565b600280556040516001600160a01b0385811660248301528481166044830152606482018490523491600091881690839060840160408051601f198184030181529181526020820180516001600160e01b0316631230c53d60e21b1790525161069a91906112f1565b60006040518083038185875af1925050503d80600081146106d7576040519150601f19603f3d011682016040523d82523d6000602084013e6106dc565b606091505b5050905080610744576040516000906001600160a01b0387169084156108fc0290859084818181858888f1935050505090508061074257604051339084156108fc029085906000818181858888f19350505050158015610740573d6000803e3d6000fd5b505b505b336001600160a01b03167f8e5841bcd195b858d53b38bcf91b38d47f3bc800469b6812d35451ab619c6f6c8884898989896040516107879695949392919061130d565b60405180910390a2505060016002555050505050565b8042106107ec5760405162461bcd60e51b815260206004820152601960248201527f54484f52436861696e5f526f757465723a20657870697265640000000000000060448201526064016101b3565b6107f885858585610248565b5050505050565b60028054036108205760405162461bcd60e51b81526004016101b39061111c565b6002805560006001600160a01b03841661089a575060405134906000906001600160a01b0387169083156108fc0290849084818181858888f1935050505090508061089457604051339083156108fc029084906000818181858888f19350505050158015610892573d6000803e3d6000fd5b505b506109a7565b3360009081526001602090815260408083206001600160a01b0388168452909152812080548592906108cd90849061135b565b90915550506040516001600160a01b03868116602483015260448201859052600091829187169060640160408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b1790525161092c91906112f1565b6000604051808303816000865af19150503d8060008114610969576040519150601f19603f3d011682016040523d82523d6000602084013e61096e565b606091505b509150915081801561099857508051158061099857508080602001905181019061099891906111df565b6109a157600080fd5b84925050505b846001600160a01b0316336001600160a01b03167fa9cd03aa3c1b4515114539cd53d22085129d495cb9e9f9af77864526240f1bf7868486604051610479939291906111af565b3360009081526001602090815260408083206001600160a01b038616845290915281208054839290610a2190849061135b565b90915550506001600160a01b03808416600090815260016020908152604080832093861683529290529081208054839290610a5d90849061121e565b9091555050505050565b3360009081526001602090815260408083206001600160a01b038716845290915281208054849290610a9a90849061135b565b90915550506040516001600160a01b038681166024830152604482018490526000919085169060640160408051601f198184030181529181526020820180516001600160e01b031663095ea7b360e01b17905251610af891906112f1565b6000604051808303816000865af19150503d8060008114610b35576040519150601f19603f3d011682016040523d82523d6000602084013e610b3a565b606091505b5050905080610b4857600080fd5b6040516344bc937b60e01b81526001600160a01b038716906344bc937b90610b7e90889088908890889060001990600401611372565b600060405180830381600087803b158015610b9857600080fd5b505af1158015610bac573d6000803e3d6000fd5b50505050505050505050565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa158015610c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2591906113b7565b6040513360248201523060448201526064810185905290915060009081906001600160a01b0387169060840160408051601f198184030181529181526020820180516001600160e01b03166323b872dd60e01b17905251610c8691906112f1565b6000604051808303816000865af19150503d8060008114610cc3576040519150601f19603f3d011682016040523d82523d6000602084013e610cc8565b606091505b5091509150818015610cf2575080511580610cf2575080806020019051810190610cf291906111df565b610cfb57600080fd5b6040516370a0823160e01b815230600482015283906001600160a01b038816906370a0823190602401602060405180830381865afa158015610d41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6591906113b7565b610d6f919061135b565b9695505050505050565b6001600160a01b0381168114610d8e57600080fd5b50565b60008060408385031215610da457600080fd5b8235610daf81610d79565b91506020830135610dbf81610d79565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610e0357610e03610dca565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715610e3257610e32610dca565b604052919050565b600082601f830112610e4b57600080fd5b813567ffffffffffffffff811115610e6557610e65610dca565b610e78601f8201601f1916602001610e09565b818152846020838601011115610e8d57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a08688031215610ec257600080fd5b8535610ecd81610d79565b94506020860135610edd81610d79565b93506040860135610eed81610d79565b925060608601359150608086013567ffffffffffffffff811115610f1057600080fd5b610f1c88828901610e3a565b9150509295509295909350565b60008060008060808587031215610f3f57600080fd5b8435610f4a81610d79565b93506020850135610f5a81610d79565b925060408501359150606085013567ffffffffffffffff811115610f7d57600080fd5b610f8987828801610e3a565b91505092959194509250565b60008060008060808587031215610fab57600080fd5b8435610fb681610d79565b9350602085810135610fc781610d79565b935060408681013567ffffffffffffffff80821115610fe557600080fd5b818901915089601f830112610ff957600080fd5b81358181111561100b5761100b610dca565b611019858260051b01610e09565b81815260069190911b8301850190858101908c83111561103857600080fd5b938601935b828510156110815785858e0312156110555760008081fd5b61105d610de0565b853561106881610d79565b815285880135888201528252938501939086019061103d565b97505050606089013593508084111561109957600080fd5b505050610f8987828801610e3a565b600080600080600060a086880312156110c057600080fd5b85356110cb81610d79565b945060208601356110db81610d79565b935060408601359250606086013567ffffffffffffffff8111156110fe57600080fd5b61110a88828901610e3a565b95989497509295608001359392505050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60005b8381101561116e578181015183820152602001611156565b8381111561117d576000848401525b50505050565b6000815180845261119b816020860160208601611153565b601f01601f19169290920160200192915050565b60018060a01b03841681528260208201526060604082015260006111d66060830184611183565b95945050505050565b6000602082840312156111f157600080fd5b8151801515811461120157600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561123157611231611208565b500190565b82815260406020820152600061124f6040830184611183565b949350505050565b634e487b7160e01b600052603260045260246000fd5b60006001820161127f5761127f611208565b5060010190565b60408082528351828201819052600091906020906060850190828801855b828110156112d257815180516001600160a01b031685528501518585015292850192908401906001016112a4565b505050848103828601526112e68187611183565b979650505050505050565b60008251611303818460208701611153565b9190910192915050565b6001600160a01b038781168252602082018790528581166040830152841660608201526080810183905260c060a0820181905260009061134f90830184611183565b98975050505050505050565b60008282101561136d5761136d611208565b500390565b6001600160a01b038681168252851660208201526040810184905260a0606082018190526000906113a590830185611183565b90508260808301529695505050505050565b6000602082840312156113c957600080fd5b505191905056fea264697066735822122081bfb5152612852b02c6e856e49c9abbe953e45e649e4ea942477a8b50a3773064736f6c634300080d0033 \ No newline at end of file diff --git a/examples/thorchain/contracts/router-abi.json b/examples/thorchain/contracts/router-abi.json new file mode 100644 index 000000000..3c638983e --- /dev/null +++ b/examples/thorchain/contracts/router-abi.json @@ -0,0 +1,423 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldVault", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newVault", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "TransferAllowance", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vault", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "TransferOut", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vault", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "finalAsset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "TransferOutAndCall", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldVault", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newVault", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct AvaxRouter.Coin[]", + "name": "coins", + "type": "tuple[]" + }, + { + "indexed": false, + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "VaultTransfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "vault", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "vault", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + } + ], + "name": "depositWithExpiry", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "router", + "type": "address" + }, + { + "internalType": "address payable", + "name": "asgard", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct AvaxRouter.Coin[]", + "name": "coins", + "type": "tuple[]" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "returnVaultAssets", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "router", + "type": "address" + }, + { + "internalType": "address", + "name": "newVault", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "transferAllowance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "transferOut", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "target", + "type": "address" + }, + { + "internalType": "address", + "name": "finalToken", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "string", + "name": "memo", + "type": "string" + } + ], + "name": "transferOutAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vault", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "vaultAllowance", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/examples/thorchain/contracts/router-bytecode.txt b/examples/thorchain/contracts/router-bytecode.txt new file mode 100644 index 000000000..c516942b7 --- /dev/null +++ b/examples/thorchain/contracts/router-bytecode.txt @@ -0,0 +1 @@ +0x608060405234801561001057600080fd5b50600180556118ec806100246000396000f3fe6080604052600436106100705760003560e01c80632923e82e1161004e5780632923e82e1461010d5780634039fd4b1461012057806344bc937b14610133578063574da7171461014657600080fd5b806303b6a673146100755780631b738b32146100d85780631fece7b4146100fa575b600080fd5b34801561008157600080fd5b506100c66100903660046111b7565b73ffffffffffffffffffffffffffffffffffffffff91821660009081526020818152604080832093909416825291909152205490565b60405190815260200160405180910390f35b3480156100e457600080fd5b506100f86100f3366004611325565b610159565b005b6100f86101083660046113a4565b61027f565b6100f861011b366004611410565b610488565b6100f861012e366004611325565b61068e565b6100f8610141366004611523565b6108d9565b6100f86101543660046113a4565b610955565b600260015414156101cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b600260015573ffffffffffffffffffffffffffffffffffffffff8516301415610267576101f9848484610c29565b8373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f05b90458f953d3fcb2d7fb25616a2fddeca749d0c47cc5c9832d0266b5346eea85858560405161025a93929190611611565b60405180910390a3610274565b6102748585858585610cb8565b505060018055505050565b600260015414156102ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016101c2565b6002600155600073ffffffffffffffffffffffffffffffffffffffff84166103575750604051349060009073ffffffffffffffffffffffffffffffffffffffff87169083156108fc0290849084818181858888f1935050505090508061035157600080fd5b50610416565b34156103bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f756e65787065637465642061766178000000000000000000000000000000000060448201526064016101c2565b6103c98484610eb1565b73ffffffffffffffffffffffffffffffffffffffff80871660009081526020818152604080832093891683529290529081208054929350839290919061041090849061167e565b90915550505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fef519b7eb82aaf6ac376a6df2d793843ebfd593de5f1a0601d3cc6ab49ebb3958385604051610475929190611696565b60405180910390a3505060018055505050565b600260015414156104f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016101c2565b600260015573ffffffffffffffffffffffffffffffffffffffff84163014156105e85760005b825181101561057b576105698484838151811061053a5761053a6116b7565b602002602001015160000151858481518110610558576105586116b7565b602002602001015160200151610c29565b80610573816116e6565b91505061051b565b508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f281daef48d91e5cd3d32db0784f6af69cd8d8d2e8c612a3568dca51ded51e08f84846040516105db92919061171f565b60405180910390a361064f565b60005b825181101561064d5761063b858585848151811061060b5761060b6116b7565b602002602001015160000151868581518110610629576106296116b7565b60200260200101516020015186610cb8565b80610645816116e6565b9150506105eb565b505b60405160009073ffffffffffffffffffffffffffffffffffffffff8516903480156108fc029184818181858888f1935050505090508061027457600080fd5b600260015414156106fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016101c2565b600260015560405173ffffffffffffffffffffffffffffffffffffffff858116602483015284811660448301526064820184905234916000918816908390608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f48c314f400000000000000000000000000000000000000000000000000000000179052516107bd9190611797565b60006040518083038185875af1925050503d80600081146107fa576040519150601f19603f3d011682016040523d82523d6000602084013e6107ff565b606091505b50509050806108745760405160009073ffffffffffffffffffffffffffffffffffffffff87169084156108fc0290859084818181858888f1935050505090508061087257604051339084156108fc029085906000818181858888f19350505050158015610870573d6000803e3d6000fd5b505b505b3373ffffffffffffffffffffffffffffffffffffffff167f8e5841bcd195b858d53b38bcf91b38d47f3bc800469b6812d35451ab619c6f6c8884898989896040516108c4969594939291906117b3565b60405180910390a25050600180555050505050565b804210610942576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f54484f52436861696e5f526f757465723a20657870697265640000000000000060448201526064016101c2565b61094e8585858561027f565b5050505050565b600260015414156109c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016101c2565b6002600155600073ffffffffffffffffffffffffffffffffffffffff8416610a575750604051349060009073ffffffffffffffffffffffffffffffffffffffff87169083156108fc0290849084818181858888f19350505050905080610a5157604051339083156108fc029084906000818181858888f19350505050158015610a4f573d6000803e3d6000fd5b505b50610bc8565b3360009081526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8816845290915281208054859290610a9590849061180c565b909155505060405173ffffffffffffffffffffffffffffffffffffffff8681166024830152604482018590526000918291871690606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905251610b4d9190611797565b6000604051808303816000865af19150503d8060008114610b8a576040519150601f19603f3d011682016040523d82523d6000602084013e610b8f565b606091505b5091509150818015610bb9575080511580610bb9575080806020019051810190610bb99190611823565b610bc257600080fd5b84925050505b8473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fa9cd03aa3c1b4515114539cd53d22085129d495cb9e9f9af77864526240f1bf786848660405161047593929190611611565b3360009081526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915281208054839290610c6790849061180c565b909155505073ffffffffffffffffffffffffffffffffffffffff80841660009081526020818152604080832093861683529290529081208054839290610cae90849061167e565b9091555050505050565b3360009081526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281208054849290610cf690849061180c565b909155505060405173ffffffffffffffffffffffffffffffffffffffff86811660248301526044820184905260009190851690606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905251610dad9190611797565b6000604051808303816000865af19150503d8060008114610dea576040519150601f19603f3d011682016040523d82523d6000602084013e610def565b606091505b5050905080610dfd57600080fd5b6040517f44bc937b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8716906344bc937b90610e779088908890889088907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060040161184c565b600060405180830381600087803b158015610e9157600080fd5b505af1158015610ea5573d6000803e3d6000fd5b50505050505050505050565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600090819073ffffffffffffffffffffffffffffffffffffffff8516906370a082319060240160206040518083038186803b158015610f1b57600080fd5b505afa158015610f2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f53919061189d565b60405133602482015230604482015260648101859052909150600090819073ffffffffffffffffffffffffffffffffffffffff871690608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790525161100d9190611797565b6000604051808303816000865af19150503d806000811461104a576040519150601f19603f3d011682016040523d82523d6000602084013e61104f565b606091505b50915091508180156110795750805115806110795750808060200190518101906110799190611823565b6110df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4661696c656420546f205472616e7366657246726f6d0000000000000000000060448201526064016101c2565b6040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152839073ffffffffffffffffffffffffffffffffffffffff8816906370a082319060240160206040518083038186803b15801561114657600080fd5b505afa15801561115a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117e919061189d565b611188919061180c565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146111b457600080fd5b50565b600080604083850312156111ca57600080fd5b82356111d581611192565b915060208301356111e581611192565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611242576112426111f0565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561128f5761128f6111f0565b604052919050565b600082601f8301126112a857600080fd5b813567ffffffffffffffff8111156112c2576112c26111f0565b6112f360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611248565b81815284602083860101111561130857600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561133d57600080fd5b853561134881611192565b9450602086013561135881611192565b9350604086013561136881611192565b925060608601359150608086013567ffffffffffffffff81111561138b57600080fd5b61139788828901611297565b9150509295509295909350565b600080600080608085870312156113ba57600080fd5b84356113c581611192565b935060208501356113d581611192565b925060408501359150606085013567ffffffffffffffff8111156113f857600080fd5b61140487828801611297565b91505092959194509250565b6000806000806080858703121561142657600080fd5b843561143181611192565b935060208581013561144281611192565b935060408681013567ffffffffffffffff8082111561146057600080fd5b818901915089601f83011261147457600080fd5b813581811115611486576114866111f0565b611494858260051b01611248565b81815260069190911b8301850190858101908c8311156114b357600080fd5b938601935b828510156114fc5785858e0312156114d05760008081fd5b6114d861121f565b85356114e381611192565b81528588013588820152825293850193908601906114b8565b97505050606089013593508084111561151457600080fd5b50505061140487828801611297565b600080600080600060a0868803121561153b57600080fd5b853561154681611192565b9450602086013561155681611192565b935060408601359250606086013567ffffffffffffffff81111561157957600080fd5b61158588828901611297565b95989497509295608001359392505050565b60005b838110156115b257818101518382015260200161159a565b838111156115c1576000848401525b50505050565b600081518084526115df816020860160208601611597565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061164660608301846115c7565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156116915761169161164f565b500190565b8281526040602082015260006116af60408301846115c7565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156117185761171861164f565b5060010190565b60408082528351828201819052600091906020906060850190828801855b82811015611778578151805173ffffffffffffffffffffffffffffffffffffffff16855285015185850152928501929084019060010161173d565b5050508481038286015261178c81876115c7565b979650505050505050565b600082516117a9818460208701611597565b9190910192915050565b600073ffffffffffffffffffffffffffffffffffffffff8089168352876020840152808716604084015280861660608401525083608083015260c060a083015261180060c08301846115c7565b98975050505050505050565b60008282101561181e5761181e61164f565b500390565b60006020828403121561183557600080fd5b8151801515811461184557600080fd5b9392505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525084604083015260a0606083015261188b60a08301856115c7565b90508260808301529695505050505050565b6000602082840312156118af57600080fd5b505191905056fea2646970667358221220f11847a348f63b399358a3736e1f295761b905637e0cec3e15f85765e2d3dac564736f6c63430008090033 \ No newline at end of file diff --git a/examples/thorchain/contracts/token-abi.json b/examples/thorchain/contracts/token-abi.json new file mode 100644 index 000000000..ba48a0da6 --- /dev/null +++ b/examples/thorchain/contracts/token-abi.json @@ -0,0 +1,229 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/examples/thorchain/contracts/token-bytecode.txt b/examples/thorchain/contracts/token-bytecode.txt new file mode 100644 index 000000000..1a7d13087 --- /dev/null +++ b/examples/thorchain/contracts/token-bytecode.txt @@ -0,0 +1 @@ +0x60806040526012600255600254600a0a620f42400260035534801561002357600080fd5b50600354600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506040518060400160405280600581526020017f546f6b656e000000000000000000000000000000000000000000000000000000815250600090805190602001906100b592919061016f565b506040518060400160405280600381526020017f544b4e00000000000000000000000000000000000000000000000000000000008152506001908051906020019061010192919061016f565b503373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6003546040518082815260200191505060405180910390a3610214565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106101b057805160ff19168380011785556101de565b828001600101855582156101de579182015b828111156101dd5782518255916020019190600101906101c2565b5b5090506101eb91906101ef565b5090565b61021191905b8082111561020d5760008160009055506001016101f5565b5090565b90565b610c34806102236000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063313ce56711610066578063313ce5671461022557806370a082311461024357806395d89b411461029b578063a9059cbb1461031e578063dd62ed3e1461038457610093565b806306fdde0314610098578063095ea7b31461011b57806318160ddd1461018157806323b872dd1461019f575b600080fd5b6100a06103fc565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100e05780820151818401526020810190506100c5565b50505050905090810190601f16801561010d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101676004803603604081101561013157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061049a565b604051808215151515815260200191505060405180910390f35b61018961058c565b6040518082815260200191505060405180910390f35b61020b600480360360608110156101b557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610592565b604051808215151515815260200191505060405180910390f35b61022d6106bd565b6040518082815260200191505060405180910390f35b6102856004803603602081101561025957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506106c3565b6040518082815260200191505060405180910390f35b6102a36106db565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102e35780820151818401526020810190506102c8565b50505050905090810190601f1680156103105780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61036a6004803603604081101561033457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610779565b604051808215151515815260200191505060405180910390f35b6103e66004803603604081101561039a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610790565b6040518082815260200191505060405180910390f35b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156104925780601f1061046757610100808354040283529160200191610492565b820191906000526020600020905b81548152906001019060200180831161047557829003601f168201915b505050505081565b600081600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60035481565b6000600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482111561061d57600080fd5b81600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506106b28484846107b5565b600190509392505050565b60025481565b60046020528060005260406000206000915090505481565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107715780601f1061074657610100808354040283529160200191610771565b820191906000526020600020905b81548152906001019060200180831161075457829003601f168201915b505050505081565b60006107863384846107b5565b6001905092915050565b6005602052816000526040600020602052806000526040600020600091509150505481565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156107ef57600080fd5b80600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101561083b57600080fd5b600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546108cd82600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610a6c90919063ffffffff16565b10156108d857600080fd5b61092a81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610af490919063ffffffff16565b600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506109bf81600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610a6c90919063ffffffff16565b600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600080828401905083811015610aea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000610b3683836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250610b3e565b905092915050565b6000838311158290610beb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610bb0578082015181840152602081019050610b95565b50505050905090810190601f168015610bdd5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838503905080915050939250505056fea26469706673582212208621a61a72b5773eedaaccd88413213c489e071f7a4afc9c87236e049e046e9064736f6c63430006050033 \ No newline at end of file diff --git a/examples/thorchain/features/dual_lper.go b/examples/thorchain/features/dual_lper.go index 13fbd9561..c418c5e4b 100644 --- a/examples/thorchain/features/dual_lper.go +++ b/examples/thorchain/features/dual_lper.go @@ -19,34 +19,34 @@ func DualLp( fmt.Println("#### Dual Lper:", exoChain.Config().Name) users, err := GetAndFundTestUsers(t, ctx, fmt.Sprintf("%s-DualLper", exoChain.Config().Name), thorchain, exoChain) if err != nil { - return thorUser, exoUser, err + return thorUser, exoUser, fmt.Errorf("duallp, fund users (%s), %w", exoChain.Config().Name, err) } thorUser, exoUser = users[0], users[1] exoChainType, err := common.NewChain(exoChain.Config().Name) if err != nil { - return thorUser, exoUser, err + return thorUser, exoUser, fmt.Errorf("duallp, chain type (%s), %w", exoChain.Config().Name, err) } exoAsset := exoChainType.GetGasAsset() thorUserBalance, err := thorchain.GetBalance(ctx, thorUser.FormattedAddress(), thorchain.Config().Denom) if err != nil { - return thorUser, exoUser, err + return thorUser, exoUser, fmt.Errorf("duallp, thor balance (%s), %w", exoChain.Config().Name, err) } memo := fmt.Sprintf("+:%s:%s", exoAsset, exoUser.FormattedAddress()) err = thorchain.Deposit(ctx, thorUser.KeyName(), thorUserBalance.QuoRaw(100).MulRaw(90), thorchain.Config().Denom, memo) if err != nil { - return thorUser, exoUser, err + return thorUser, exoUser, fmt.Errorf("duallp, thor deposit (%s), %w", exoChain.Config().Name, err) } exoUserBalance, err := exoChain.GetBalance(ctx, exoUser.FormattedAddress(), exoChain.Config().Denom) if err != nil { - return thorUser, exoUser, err + return thorUser, exoUser, fmt.Errorf("duallp, exo balance (%s), %w", exoChain.Config().Name, err) } memo = fmt.Sprintf("+:%s:%s", exoAsset, thorUser.FormattedAddress()) exoInboundAddr, _, err := thorchain.ApiGetInboundAddress(exoChainType.String()) if err != nil { - return thorUser, exoUser, err + return thorUser, exoUser, fmt.Errorf("duallp, inbound addr (%s), %w", exoChain.Config().Name, err) } _, err = exoChain.SendFundsWithNote(ctx, exoUser.KeyName(), ibc.WalletAmount{ Address: exoInboundAddr, @@ -54,12 +54,12 @@ func DualLp( Amount: exoUserBalance.QuoRaw(100).MulRaw(90), // LP 90% of balance }, memo) if err != nil { - return thorUser, exoUser, err + return thorUser, exoUser, fmt.Errorf("duallp, exo send funds (%s), %w", exoChain.Config().Name, err) } err = PollForPool(ctx, thorchain, 60, exoAsset) if err != nil { - return thorUser, exoUser, err + return thorUser, exoUser, fmt.Errorf("duallp, poll for pool (%s), %w", exoChain.Config().Name, err) } return thorUser, exoUser, err diff --git a/examples/thorchain/features/helpers.go b/examples/thorchain/features/helpers.go index 3c90992ac..f8d3206f4 100644 --- a/examples/thorchain/features/helpers.go +++ b/examples/thorchain/features/helpers.go @@ -47,7 +47,7 @@ func GetAndFundTestUsers( return err } if !userBalance.Equal(amount) { - return fmt.Errorf("User (%s) was not properly funded", user[0].KeyName()) + return fmt.Errorf("user (%s) was not properly funded", user[0].KeyName()) } return nil @@ -74,7 +74,7 @@ func PollForPool(ctx context.Context, thorchain *tc.Thorchain, deltaBlocks int64 if pool.BalanceAsset == "0" { time.Sleep(time.Second) // rate limit - return nil, fmt.Errorf("Pool (%s) exists, but not asset balance in %d blocks", asset, deltaBlocks) + return nil, fmt.Errorf("pool (%s) exists, but not asset balance in %d blocks", asset, deltaBlocks) } return nil, nil } @@ -97,7 +97,7 @@ func PollForSaver(ctx context.Context, thorchain *tc.Thorchain, deltaBlocks int6 return tc.Saver{}, err } for _, saver := range savers { - if strings.ToLower(saver.AssetAddress) == strings.ToLower(exoUser.FormattedAddress()) { + if strings.EqualFold(saver.AssetAddress, exoUser.FormattedAddress()) { return saver, nil } @@ -124,7 +124,7 @@ func PollForEjectedSaver(ctx context.Context, thorchain *tc.Thorchain, deltaBloc return tc.Saver{}, err } for _, saver := range savers { - if strings.ToLower(saver.AssetAddress) == strings.ToLower(exoUser.FormattedAddress()) { + if strings.EqualFold(saver.AssetAddress, exoUser.FormattedAddress()) { time.Sleep(time.Second) // rate limit return saver, fmt.Errorf("saver took longer than %d blocks to eject", deltaBlocks) } @@ -228,7 +228,7 @@ func PollForPoolSuspended(ctx context.Context, thorchain *tc.Thorchain, deltaBlo } time.Sleep(time.Second) // rate limit - return nil, fmt.Errorf("Pool (%s) did not suspend in %d blocks", exoAsset, deltaBlocks) + return nil, fmt.Errorf("pool (%s) did not suspend in %d blocks", exoAsset, deltaBlocks) } time.Sleep(time.Second) // Limit how quickly Height() is called back to back per go routine bp := testutil.BlockPoller[any]{CurrentHeight: thorchain.Height, PollFunc: doPoll} diff --git a/examples/thorchain/features/ragnarok.go b/examples/thorchain/features/ragnarok.go index e8e150cd4..5268ca4dc 100644 --- a/examples/thorchain/features/ragnarok.go +++ b/examples/thorchain/features/ragnarok.go @@ -63,7 +63,7 @@ func Ragnarok( return err } if exoUserPostRagBalance.LTE(exoUsersPreRagBalance[i]) { - return fmt.Errorf("User (%s) balance did not increase after %s ragnarok", exoUser.KeyName(), exoChainType) + return fmt.Errorf("user (%s) balance did not increase after %s ragnarok", exoUser.KeyName(), exoChainType) } fmt.Printf("\nUser (%s), pre: %s, post: %s\n", exoUser.KeyName(), exoUsersPreRagBalance[i], exoUserPostRagBalance) } diff --git a/examples/thorchain/features/saver_eject.go b/examples/thorchain/features/saver_eject.go index 7d52972a6..e6c6245c0 100644 --- a/examples/thorchain/features/saver_eject.go +++ b/examples/thorchain/features/saver_eject.go @@ -38,31 +38,36 @@ func SaverEject( mimirLock.Lock() mimirs, err := thorchain.ApiGetMimirs() if err != nil { + mimirLock.Unlock() return exoUser, err } // Set max synth per pool depth to 100% of pool amount if mimir, ok := mimirs[strings.ToUpper("MaxSynthPerPoolDepth")]; ok && mimir != int64(5000) { - if err := thorchain.SetMimir(ctx, "admin", "MaxSynthPerPoolDepth", "5000"); err != nil { + if err = thorchain.SetMimir(ctx, "admin", "MaxSynthPerPoolDepth", "5000"); err != nil { + mimirLock.Unlock() return exoUser, err } } // Disable saver ejection if mimir, ok := mimirs[strings.ToUpper("SaversEjectInterval")]; ok && mimir != int64(0) || !ok { - if err := thorchain.SetMimir(ctx, "admin", "SaversEjectInterval", "0"); err != nil { + if err = thorchain.SetMimir(ctx, "admin", "SaversEjectInterval", "0"); err != nil { + mimirLock.Unlock() return exoUser, err } } exoChainType, err := common.NewChain(exoChain.Config().Name) if err != nil { + mimirLock.Unlock() return exoUser, err } exoAsset := exoChainType.GetGasAsset() pool, err := thorchain.ApiGetPool(exoAsset) if err != nil { + mimirLock.Unlock() return exoUser, err } saveAmount := sdkmath.NewUintFromString(pool.BalanceAsset). @@ -70,6 +75,7 @@ func SaverEject( saverQuote, err := thorchain.ApiGetSaverDepositQuote(exoAsset, saveAmount) if err != nil { + mimirLock.Unlock() return exoUser, err } @@ -91,6 +97,7 @@ func SaverEject( exoInboundAddr, _, err := thorchain.ApiGetInboundAddress(exoChainType.String()) if err != nil { + mimirLock.Unlock() return exoUser, err } @@ -107,25 +114,30 @@ func SaverEject( err = exoChain.SendFunds(ctx, exoUser.KeyName(), wallet) } if err != nil { + mimirLock.Unlock() return exoUser, err } errMsgCommon := fmt.Sprintf("saver (%s - %s) of asset %s", exoUser.KeyName(), exoUser.FormattedAddress(), exoAsset) saver, err := PollForSaver(ctx, thorchain, 30, exoAsset, exoUser) if err != nil { + mimirLock.Unlock() return exoUser, fmt.Errorf("%s not found, %w", errMsgCommon, err) } deposit := sdkmath.NewUintFromString(saver.AssetDepositValue) if deposit.LT(minExpectedSaver) { + mimirLock.Unlock() return exoUser, fmt.Errorf("%s deposit: %s, min expected: %s", errMsgCommon, deposit, minExpectedSaver) } if deposit.GT(maxExpectedSaver) { + mimirLock.Unlock() return exoUser, fmt.Errorf("%s deposit: %s, max expected: %s", errMsgCommon, deposit, maxExpectedSaver) } exoUserPreEjectBalance, err := exoChain.GetBalance(ctx, exoUser.FormattedAddress(), exoChain.Config().Denom) if err != nil { + mimirLock.Unlock() return exoUser, err } @@ -133,35 +145,40 @@ func SaverEject( for i, exoSaver := range exoSavers { exoSaversBalance[i], err = exoChain.GetBalance(ctx, exoSaver.FormattedAddress(), exoChain.Config().Denom) if err != nil { + mimirLock.Unlock() return exoUser, err } } mimirs, err = thorchain.ApiGetMimirs() if err != nil { + mimirLock.Unlock() return exoUser, err } // Set mimirs if mimir, ok := mimirs[strings.ToUpper("MaxSynthPerPoolDepth")]; ok && mimir != int64(500) || !ok { if err := thorchain.SetMimir(ctx, "admin", "MaxSynthPerPoolDepth", "500"); err != nil { + mimirLock.Unlock() return exoUser, err } } if mimir, ok := mimirs[strings.ToUpper("SaversEjectInterval")]; ok && mimir != int64(1) || !ok { if err := thorchain.SetMimir(ctx, "admin", "SaversEjectInterval", "1"); err != nil { + mimirLock.Unlock() return exoUser, err } } _, err = PollForEjectedSaver(ctx, thorchain, 30, exoAsset, exoUser) if err != nil { + mimirLock.Unlock() return exoUser, err } mimirLock.Unlock() - if err := PollForBalanceChange(ctx, exoChain, 15, ibc.WalletAmount{ + if err = PollForBalanceChange(ctx, exoChain, 15, ibc.WalletAmount{ Address: exoUser.FormattedAddress(), Denom: exoChain.Config().Denom, Amount: exoUserPreEjectBalance, @@ -173,7 +190,7 @@ func SaverEject( return exoUser, err } if exoUserPostEjectBalance.LTE(exoUserPreEjectBalance) { - return exoUser, fmt.Errorf("User (%s) balance (%s) must be greater after ejection: %s", exoUser.KeyName(), exoUserPostEjectBalance, exoUserPreEjectBalance) + return exoUser, fmt.Errorf("user (%s) balance (%s) must be greater after ejection: %s", exoUser.KeyName(), exoUserPostEjectBalance, exoUserPreEjectBalance) } for i, exoSaver := range exoSavers { @@ -182,7 +199,7 @@ func SaverEject( return exoUser, err } if !exoSaverPostBalance.Equal(exoSaversBalance[i]) { - return exoUser, fmt.Errorf("Saver's (%s) post balance (%s) should be the same as (%s)", exoSaver.KeyName(), exoSaverPostBalance, exoSaversBalance[i]) + return exoUser, fmt.Errorf("saver's (%s) post balance (%s) should be the same as (%s)", exoSaver.KeyName(), exoSaverPostBalance, exoSaversBalance[i]) } } diff --git a/examples/thorchain/features/swap.go b/examples/thorchain/features/swap.go index 2ede3f9a1..a31393fc7 100644 --- a/examples/thorchain/features/swap.go +++ b/examples/thorchain/features/swap.go @@ -10,7 +10,6 @@ import ( tc "github.com/strangelove-ventures/interchaintest/v8/chain/thorchain" "github.com/strangelove-ventures/interchaintest/v8/chain/thorchain/common" "github.com/strangelove-ventures/interchaintest/v8/ibc" - "golang.org/x/sync/errgroup" ) func SingleSwap( @@ -44,17 +43,12 @@ func DualSwap( } srcUser, destUser := users[0], users[1] - var eg errgroup.Group - - eg.Go(func() error { - return singleSwap(ctx, thorchain, srcChain, srcUser, destChain, destUser) - }) - - eg.Go(func() error { - return singleSwap(ctx, thorchain, destChain, destUser, srcChain, srcUser) - }) + // Perform these swap sequential so the balance checks work properly + if err := singleSwap(ctx, thorchain, srcChain, srcUser, destChain, destUser); err != nil { + return err + } - return eg.Wait() + return singleSwap(ctx, thorchain, destChain, destUser, srcChain, srcUser) } // swap 0.5% of pool depth @@ -140,7 +134,7 @@ func singleSwap( } else { _, err = PollOutboundSigned(ctx, thorchain, 200, txHash) if err != nil { - return err + return fmt.Errorf("outbound chain: %s, err: %w", destChainType, err) } } @@ -179,10 +173,10 @@ func singleSwap( } actualSwapAmount := destUserBalancePostSwap.Sub(destUserBalancePreSwap) if actualSwapAmount.LT(sdkmath.Int(minExpectedSwapAmount)) { - return fmt.Errorf("Actual swap amount: %s %s, min expected: %s", actualSwapAmount, destChain.Config().Denom, minExpectedSwapAmount) + return fmt.Errorf("actual swap amount: %s %s, min expected: %s", actualSwapAmount, destChain.Config().Denom, minExpectedSwapAmount) } if actualSwapAmount.GT(sdkmath.Int(maxExpectedSwapAmount)) { - return fmt.Errorf("Actual swap amount: %s %s, max expected: %s", actualSwapAmount, destChain.Config().Denom, maxExpectedSwapAmount) + return fmt.Errorf("actual swap amount: %s %s, max expected: %s", actualSwapAmount, destChain.Config().Denom, maxExpectedSwapAmount) } // TODO: compare outAmountPlusMaxGas -> actualSwapAmount fmt.Println("outAmountPlusMaxGas:", outAmountPlusMaxGas, "actualSwapAmount:", actualSwapAmount) diff --git a/examples/thorchain/helper.go b/examples/thorchain/helper.go index 1656fe6f3..be897a7b6 100644 --- a/examples/thorchain/helper.go +++ b/examples/thorchain/helper.go @@ -4,9 +4,8 @@ import ( "context" "fmt" "regexp" - "strings" + "time" - "github.com/strangelove-ventures/interchaintest/v8/chain/cosmos" "github.com/strangelove-ventures/interchaintest/v8/ibc" ) @@ -23,8 +22,22 @@ func GetEthAddressFromStdout(stdout string) (string, error) { return matches[1], nil } -func sendFunds(ctx context.Context, keyName string, toAddr string, amount ibc.WalletAmount, val0 *cosmos.ChainNode) { - memo := strings.Repeat("Hello World ", 10) - command := []string{"bank", "send", keyName, toAddr, fmt.Sprintf("%s%s", amount.Amount.String(), amount.Denom), "--note", memo} - _, _, _ = val0.Exec(ctx, val0.TxCommand(keyName, command...), val0.Chain.Config().Env) +// We are running many nodes, using many resources. This function is similar to +// testutils.WaitForBlocks(), but does not hammer calls as fast as possible. +func NiceWaitForBlocks(ctx context.Context, delta int64, chain ibc.Chain) error { + startingHeight, err := chain.Height(ctx) + if err != nil { + return err + } + + currentHeight := startingHeight + for ; currentHeight < startingHeight + delta; { + time.Sleep(time.Millisecond * 200) + currentHeight, err = chain.Height(ctx) + if err != nil { + return err + } + } + + return nil } diff --git a/examples/thorchain/setup.go b/examples/thorchain/setup.go index f49e008c2..2353e4963 100644 --- a/examples/thorchain/setup.go +++ b/examples/thorchain/setup.go @@ -2,9 +2,11 @@ package thorchain_test import ( "context" + _ "embed" "fmt" "strings" "testing" + "time" sdkmath "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/codec" @@ -19,10 +21,11 @@ import ( "github.com/strangelove-ventures/interchaintest/v8" "github.com/strangelove-ventures/interchaintest/v8/chain/cosmos" "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum" + "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum/foundry" + "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum/geth" tc "github.com/strangelove-ventures/interchaintest/v8/chain/thorchain" "github.com/strangelove-ventures/interchaintest/v8/chain/utxo" "github.com/strangelove-ventures/interchaintest/v8/ibc" - "github.com/strangelove-ventures/interchaintest/v8/testutil" "github.com/stretchr/testify/require" "go.uber.org/zap/zaptest" "golang.org/x/sync/errgroup" @@ -30,12 +33,14 @@ import ( func StartExoChains(t *testing.T, ctx context.Context, client *client.Client, network string) ExoChains { chainSpecs := []*interchaintest.ChainSpec{ - EthChainSpec(), + EthChainSpec("geth"), // only use this chain spec for eth or the one below + //EthChainSpec("anvil"), GaiaChainSpec(), BtcChainSpec(), BchChainSpec(), LtcChainSpec(), DogeChainSpec(), + BscChainSpec(), } cf0 := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), chainSpecs) @@ -66,16 +71,16 @@ func StartExoChains(t *testing.T, ctx context.Context, client *client.Client, ne for _, wallet := range exoChains[name].genWallets { additionalGenesisWallets = append(additionalGenesisWallets, ibc.WalletAmount{ Address: wallet.FormattedAddress(), - Amount: sdkmath.NewInt(100_000_000), - Denom: chain.Config().Denom, + Amount: sdkmath.NewInt(100_000_000), + Denom: chain.Config().Denom, }) } if name == "GAIA" { // this wallet just stops bifrost complaining about it not existing additionalGenesisWallets = append(additionalGenesisWallets, ibc.WalletAmount{ Address: "cosmos1zf3gsk7edzwl9syyefvfhle37cjtql35427vcp", - Amount: sdkmath.NewInt(1_000_000), - Denom: chain.Config().Denom, + Amount: sdkmath.NewInt(1_000_000), + Denom: chain.Config().Denom, }) } ic.AddChain(chain, additionalGenesisWallets...) @@ -94,7 +99,7 @@ func StartExoChains(t *testing.T, ctx context.Context, client *client.Client, ne return exoChains } -func StartThorchain(t *testing.T, ctx context.Context, client *client.Client, network string, exoChains ExoChains, ethRouterContractAddress string) *tc.Thorchain { +func StartThorchain(t *testing.T, ctx context.Context, client *client.Client, network string, exoChains ExoChains, ethRouterContractAddress string, bscRouterContractAddress string) *tc.Thorchain { numThorchainValidators := 1 numThorchainFullNodes := 0 @@ -111,8 +116,14 @@ func StartThorchain(t *testing.T, ctx context.Context, client *client.Client, ne } disableChainKey := fmt.Sprintf("BIFROST_CHAINS_%s_DISABLED", name) bifrostEnvOverrides[disableChainKey] = "false" + if name == "BSC" { + hostKey = fmt.Sprintf("BIFROST_CHAINS_%s_RPC_HOST", name) + bifrostEnvOverrides[hostKey] = exoChain.chain.GetRPCAddress() + bsRpcHost := fmt.Sprintf("BIFROST_CHAINS_%s_BLOCK_SCANNER_RPC_HOST", name) + bifrostEnvOverrides[bsRpcHost] = exoChain.chain.GetRPCAddress() + } } - thorchainChainSpec := ThorchainDefaultChainSpec(t.Name(), numThorchainValidators, numThorchainFullNodes, ethRouterContractAddress, nil, bifrostEnvOverrides) + thorchainChainSpec := ThorchainDefaultChainSpec(t.Name(), numThorchainValidators, numThorchainFullNodes, ethRouterContractAddress, bscRouterContractAddress, nil, bifrostEnvOverrides) cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{ thorchainChainSpec, @@ -140,50 +151,130 @@ func StartThorchain(t *testing.T, ctx context.Context, client *client.Client, ne require.NoError(t, err, "failed starting validator sidecars") // Give some time for bifrost to initialize before any tests start - err = testutil.WaitForBlocks(ctx, 5, thorchain) + time.Sleep(time.Second * 15) require.NoError(t, err) return thorchain } -func SetupEthContracts(t *testing.T, ctx context.Context, exoChain *ExoChain) string { - ethChain := exoChain.chain.(*ethereum.EthereumChain) +func SetupContracts(ctx context.Context, ethExoChain *ExoChain, bscExoChain *ExoChain) (ethContractAddr, bscContractAddr string, err error) { + eg, egCtx := errgroup.WithContext(ctx) + eg.Go(func() error { + var err error + if ethExoChain.chain.Config().Bin == "geth" { + ethContractAddr, err = SetupGethContracts(egCtx, ethExoChain) + } else { + ethContractAddr, err = SetupAnvilContracts(egCtx, ethExoChain) + } + return err + }) + eg.Go(func() error { + var err error + bscContractAddr, err = SetupGethContracts(egCtx, bscExoChain) + return err + }) + + return ethContractAddr, bscContractAddr, eg.Wait() +} + +//go:embed contracts/eth-router-abi.json +var ethRouterAbi []byte + +//go:embed contracts/eth-router-bytecode.txt +var ethRouterByteCode []byte + +//go:embed contracts/router-abi.json +var routerAbi []byte + +//go:embed contracts/router-bytecode.txt +var routerByteCode []byte + +func SetupGethContracts(ctx context.Context, exoChain *ExoChain) (string, error) { + abi := routerAbi + byteCode := routerByteCode + if exoChain.chain.Config().Name == "ETH" { + abi = ethRouterAbi + byteCode = append(ethRouterByteCode, []byte("000000000000000000000000de06987c28d839daaefb6c85816a2cc55277654c")...) // RUNE token (doesn't matter) + } + + ethChain := exoChain.chain.(*geth.GethChain) + + ethUserInitialAmount := ethereum.ETHER.MulRaw(100) + + ethUser, err := interchaintest.GetAndFundTestUserWithMnemonic(ctx, "user", strings.Repeat("dog ", 23)+"fossil", ethUserInitialAmount, ethChain) + if err != nil { + return "", err + } + + ethRouterContractAddress, err := ethChain.DeployContract(ctx, ethUser.KeyName(), abi, byteCode) + if err != nil { + return "", err + } + if ethRouterContractAddress == "" { + return "", fmt.Errorf("router contract address for (%s) chain is empty", ethChain.Config().Name) + } + if !ethcommon.IsHexAddress(ethRouterContractAddress) { + return "", fmt.Errorf("router contract address for (%s) chain is not a hex address", ethChain.Config().Name) + } + + return ethRouterContractAddress, nil +} + +func SetupAnvilContracts(ctx context.Context, exoChain *ExoChain) (string, error) { + ethChain := exoChain.chain.(*foundry.AnvilChain) ethUserInitialAmount := ethereum.ETHER.MulRaw(2) ethUser, err := interchaintest.GetAndFundTestUserWithMnemonic(ctx, "user", strings.Repeat("dog ", 23)+"fossil", ethUserInitialAmount, ethChain) - require.NoError(t, err) + if err != nil { + return "", err + } - stdout, _, err := ethChain.ForgeScript(ctx, ethUser.KeyName(), ethereum.ForgeScriptOpts{ + stdout, _, err := ethChain.ForgeScript(ctx, ethUser.KeyName(), foundry.ForgeScriptOpts{ ContractRootDir: "contracts", SolidityContract: "script/Token.s.sol", RawOptions: []string{"--sender", ethUser.FormattedAddress(), "--json"}, }) - require.NoError(t, err) + if err != nil { + return "", err + } tokenContractAddress, err := GetEthAddressFromStdout(string(stdout)) - require.NoError(t, err) - require.NotEmpty(t, tokenContractAddress) - require.True(t, ethcommon.IsHexAddress(tokenContractAddress)) + if err != nil { + return "", err + } + if tokenContractAddress == "" { + return "", fmt.Errorf("token contract address for (%s) chain is empty", ethChain.Config().Name) + } + if !ethcommon.IsHexAddress(tokenContractAddress) { + return "", fmt.Errorf("token contract address for (%s) chain is not a hex address", ethChain.Config().Name) + } - stdout, _, err = ethChain.ForgeScript(ctx, ethUser.KeyName(), ethereum.ForgeScriptOpts{ + stdout, _, err = ethChain.ForgeScript(ctx, ethUser.KeyName(), foundry.ForgeScriptOpts{ ContractRootDir: "contracts", SolidityContract: "script/Router.s.sol", RawOptions: []string{"--sender", ethUser.FormattedAddress(), "--json"}, }) - require.NoError(t, err) + if err != nil { + return "", err + } ethRouterContractAddress, err := GetEthAddressFromStdout(string(stdout)) - require.NoError(t, err) - require.NotEmpty(t, ethRouterContractAddress) - require.True(t, ethcommon.IsHexAddress(ethRouterContractAddress)) + if err != nil { + return "", err + } + if ethRouterContractAddress == "" { + return "", fmt.Errorf("router contract address for (%s) chain is empty", ethChain.Config().Name) + } + if !ethcommon.IsHexAddress(ethRouterContractAddress) { + return "", fmt.Errorf("router contract address for (%s) chain is not a hex address", ethChain.Config().Name) + } - return ethRouterContractAddress + return ethRouterContractAddress, nil } func SetupGaia(t *testing.T, ctx context.Context, exoChain *ExoChain) *errgroup.Group { gaia := exoChain.chain.(*cosmos.CosmosChain) - eg, egCtx := errgroup.WithContext(ctx) eg.Go(func() error { for _, genWallet := range exoChain.genWallets { @@ -192,21 +283,27 @@ func SetupGaia(t *testing.T, ctx context.Context, exoChain *ExoChain) *errgroup. return err } } - - amount := ibc.WalletAmount{ - Denom: gaia.Config().Denom, - Amount: sdkmath.NewInt(1_000_000), - } - + // Send 100 txs on gaia so that bifrost can automatically set the network fee // Sim testing can directly use bifrost to do this, right now, we can't, but may in the future val0 := gaia.GetNode() - for i := 0; i < 100/len(exoChain.genWallets) + 1; i++ { + amount := fmt.Sprintf("%s%s", sdkmath.NewInt(1_000_000).String(), gaia.Config().Denom) + for i := 0; i < 100/len(exoChain.genWallets)+1; i++ { + cmd := "" for j, genWallet := range exoChain.genWallets { toUser := exoChain.genWallets[(j+1)%len(exoChain.genWallets)] - go sendFunds(ctx, genWallet.KeyName(), toUser.FormattedAddress(), amount, val0) + bankSend := []string{"bank", "send", genWallet.KeyName(), toUser.FormattedAddress(), amount} + bankSend = val0.TxCommand(genWallet.KeyName(), bankSend...) + if j < len(exoChain.genWallets)-1 { + bankSend = append(bankSend, "&& ") + } + cmd = fmt.Sprintf("%s%s", cmd, strings.Join(bankSend, " ")) } - err := testutil.WaitForBlocks(ctx, 1, gaia) + _, _, err := val0.Exec(ctx, []string{"sh", "-c", cmd}, val0.Chain.Config().Env) + if err != nil { + fmt.Println("Gaia send funds err:", err) + } + err = NiceWaitForBlocks(ctx, 1, gaia) if err != nil { return err } @@ -242,4 +339,4 @@ func BuildGaiaWallets(t *testing.T, numWallets int, cfg ibc.ChainConfig) []ibc.W } return gaiaWallets -} \ No newline at end of file +} diff --git a/examples/thorchain/thorchain_hardfork_test.go b/examples/thorchain/thorchain_hardfork_test.go index 5fc5305a7..6e5d794bd 100644 --- a/examples/thorchain/thorchain_hardfork_test.go +++ b/examples/thorchain/thorchain_hardfork_test.go @@ -15,7 +15,6 @@ import ( "go.uber.org/zap/zaptest" ) -// mainnet-genesis.json will not be included in interchaintest repo // //go:embed mainnet-genesis.json var genesisBz []byte @@ -34,7 +33,7 @@ func TestThorchainHardFork(t *testing.T) { // ---------------------------- // Set up thorchain and others // ---------------------------- - thorchainChainSpec := ThorchainDefaultChainSpec(t.Name(), numThorchainValidators, numThorchainFullNodes, "", nil, nil) + thorchainChainSpec := ThorchainDefaultChainSpec(t.Name(), numThorchainValidators, numThorchainFullNodes, "", "", nil, nil) thorchainChainSpec.Bech32Prefix = "thor" thorchainChainSpec.Images[0].Version = "local-mainnet" diff --git a/examples/thorchain/thorchain_test.go b/examples/thorchain/thorchain_test.go index cef90e957..60b47caa0 100644 --- a/examples/thorchain/thorchain_test.go +++ b/examples/thorchain/thorchain_test.go @@ -3,6 +3,7 @@ package thorchain_test import ( "context" "fmt" + "math/rand" "sync" "testing" @@ -26,12 +27,13 @@ func TestThorchainSim(t *testing.T) { // Start non-thorchain chains exoChains := StartExoChains(t, ctx, client, network) gaiaEg := SetupGaia(t, ctx, exoChains["GAIA"]) - ethRouterContractAddress := SetupEthContracts(t, ctx, exoChains["ETH"]) + ethRouterContractAddress, bscRouterContractAddress, err := SetupContracts(ctx, exoChains["ETH"], exoChains["BSC"]) + require.NoError(t, err) // Start thorchain - thorchain := StartThorchain(t, ctx, client, network, exoChains, ethRouterContractAddress) + thorchain := StartThorchain(t, ctx, client, network, exoChains, ethRouterContractAddress, bscRouterContractAddress) require.NoError(t, gaiaEg.Wait()) // Wait for 100 transactions before starting tests - + // -------------------------------------------------------- // Bootstrap pool // -------------------------------------------------------- @@ -69,7 +71,7 @@ func TestThorchainSim(t *testing.T) { // -------------------------------------------------------- // Arb // -------------------------------------------------------- - _, err := features.Arb(t, ctx, thorchain, exoChains.GetChains()...) // Must add all active chains + _, err = features.Arb(t, ctx, thorchain, exoChains.GetChains()...) require.NoError(t, err) // -------------------------------------------------------- @@ -80,11 +82,15 @@ func TestThorchainSim(t *testing.T) { for i := range exoChainList { i := i fmt.Println("Chain:", i, "Name:", exoChainList[i].Config().Name) - if i%2 == 0 { - eg.Go(func() error { - return features.SingleSwap(t, egCtx, thorchain, exoChainList[i], exoChainList[i+1]) - }) + randomChain := rand.Intn(len(exoChainList)) + if i == randomChain && i == 0 { + randomChain++ + } else if i == randomChain { + randomChain-- } + eg.Go(func() error { + return features.DualSwap(t, ctx, thorchain, exoChainList[i], exoChainList[randomChain]) + }) } require.NoError(t, eg.Wait()) diff --git a/local-interchain/interchain/logs.go b/local-interchain/interchain/logs.go index aa9d85ad5..00c46dee6 100644 --- a/local-interchain/interchain/logs.go +++ b/local-interchain/interchain/logs.go @@ -8,7 +8,7 @@ import ( types "github.com/strangelove-ventures/interchaintest/local-interchain/interchain/types" "github.com/strangelove-ventures/interchaintest/v8/chain/cosmos" - "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum" + "github.com/strangelove-ventures/interchaintest/v8/chain/ethereum/foundry" "github.com/strangelove-ventures/interchaintest/v8/ibc" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -56,8 +56,8 @@ func DumpChainsInfoToLogs(configDir string, config *types.Config, chains []ibc.C } mainLogs.Chains = append(mainLogs.Chains, log) - case *ethereum.EthereumChain: - chainObj := chains[idx].(*ethereum.EthereumChain) + case *foundry.AnvilChain: + chainObj := chains[idx].(*foundry.AnvilChain) log := types.LogOutput{ ChainID: chainObj.Config().ChainID, From cfa5d4be71aa81bc4197a5d3888d44480f7657fc Mon Sep 17 00:00:00 2001 From: Reece Williams <31943163+Reecepbcups@users.noreply.github.com> Date: Fri, 23 Aug 2024 19:04:22 -0700 Subject: [PATCH 2/4] fix(local-ic): showcase proper available chains (#1229) --- local-interchain/bash/test.bash | 2 +- local-interchain/interchain/handlers/actions.go | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/local-interchain/bash/test.bash b/local-interchain/bash/test.bash index 9fc37ed3a..85a44784a 100755 --- a/local-interchain/bash/test.bash +++ b/local-interchain/bash/test.bash @@ -85,4 +85,4 @@ ICT_RELAYER_STOP $API_ADDR "localjuno-1" # Kills all containers, not the local-ic process. Use `killall local-ic` to kill that as well ICT_KILL_ALL $API_ADDR "localjuno-1" -exit 0 \ No newline at end of file +exit 0 diff --git a/local-interchain/interchain/handlers/actions.go b/local-interchain/interchain/handlers/actions.go index f21b1f8a9..d40a03c3a 100644 --- a/local-interchain/interchain/handlers/actions.go +++ b/local-interchain/interchain/handlers/actions.go @@ -75,7 +75,12 @@ func (a *actions) PostActions(w http.ResponseWriter, r *http.Request) { chainId := ah.ChainId if _, ok := a.vals[chainId]; !ok { - util.Write(w, []byte(fmt.Sprintf(`{"error":"chain_id '%s' not found. Chains %v"}`, chainId, a.vals[chainId]))) + var chainIds []string + for k := range a.vals { + chainIds = append(chainIds, k) + } + + util.Write(w, []byte(fmt.Sprintf(`{"error":"chain_id '%s' not found. available chain ids: %v"}`, chainId, chainIds))) return } From 8c49a293d23fec56f1bc1f7b344cc0711845ebfb Mon Sep 17 00:00:00 2001 From: Dan Kanefsky <56059752+boojamya@users.noreply.github.com> Date: Mon, 26 Aug 2024 16:00:45 -0700 Subject: [PATCH 3/4] feat: implement override flag when creating clients (#1237) --- ibc/relayer.go | 1 + relayer/rly/cosmos_relayer.go | 3 +++ 2 files changed, 4 insertions(+) diff --git a/ibc/relayer.go b/ibc/relayer.go index 081490a2b..0739f16df 100644 --- a/ibc/relayer.go +++ b/ibc/relayer.go @@ -279,6 +279,7 @@ type CreateClientOptions struct { TrustingPeriod string TrustingPeriodPercentage int64 // only available for Go Relayer MaxClockDrift string + Override bool // only available for Go Relayer } // DefaultClientOpts returns the default settings for creating clients. diff --git a/relayer/rly/cosmos_relayer.go b/relayer/rly/cosmos_relayer.go index fb8268125..d6debbcf8 100644 --- a/relayer/rly/cosmos_relayer.go +++ b/relayer/rly/cosmos_relayer.go @@ -152,6 +152,9 @@ func createClientOptsHelper(opts ibc.CreateClientOptions) []string { if opts.MaxClockDrift != "" { clientOptions = append(clientOptions, "--max-clock-drift", opts.MaxClockDrift) } + if opts.Override { + clientOptions = append(clientOptions, "--override") + } return clientOptions } From 07390b0cbde2e3e7376cb09f8a8e40690ac0efb8 Mon Sep 17 00:00:00 2001 From: Dan Kanefsky <56059752+boojamya@users.noreply.github.com> Date: Fri, 30 Aug 2024 16:55:59 -0700 Subject: [PATCH 4/4] feat: custom port in ibc transfer (#1239) --- chain/cosmos/chain_node.go | 6 +++- go.mod | 15 ++++++++- go.sum | 65 ++++++++++++++++++++++++++++++++++++++ ibc/chain.go | 1 + 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/chain/cosmos/chain_node.go b/chain/cosmos/chain_node.go index 90d0e0c33..912c2a7fe 100644 --- a/chain/cosmos/chain_node.go +++ b/chain/cosmos/chain_node.go @@ -852,8 +852,12 @@ func (tn *ChainNode) SendIBCTransfer( amount ibc.WalletAmount, options ibc.TransferOptions, ) (string, error) { + port := "transfer" + if options.Port != "" { + port = options.Port + } command := []string{ - "ibc-transfer", "transfer", "transfer", channelID, + "ibc-transfer", "transfer", port, channelID, amount.Address, fmt.Sprintf("%s%s", amount.Amount.String(), amount.Denom), "--gas", "auto", } diff --git a/go.mod b/go.mod index cc74c1745..20c1f531d 100644 --- a/go.mod +++ b/go.mod @@ -34,6 +34,7 @@ require ( github.com/docker/go-connections v0.5.0 github.com/ethereum/go-ethereum v1.14.5 github.com/gdamore/tcell/v2 v2.7.4 + github.com/gogo/protobuf v1.3.3 github.com/google/go-cmp v0.6.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/hashicorp/go-version v1.7.0 @@ -83,6 +84,7 @@ require ( github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect github.com/aws/aws-sdk-go v1.44.224 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect @@ -100,6 +102,8 @@ require ( github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cometbft/cometbft-db v0.10.0 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.12.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-db v1.0.2 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect @@ -107,8 +111,10 @@ require ( github.com/cosmos/iavl v1.1.2 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect + github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/deckarep/golang-set v1.8.0 // indirect + github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/base58 v1.0.4 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect @@ -121,6 +127,7 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.6.0 // indirect github.com/emicklei/dot v1.6.1 // indirect + github.com/ethereum/c-kzg-4844 v1.0.0 // indirect github.com/fatih/color v1.16.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect @@ -131,10 +138,10 @@ require ( github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/gobwas/ws v1.2.1 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect - github.com/gogo/protobuf v1.3.3 // indirect github.com/golang/glog v1.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect @@ -193,6 +200,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect @@ -224,6 +232,7 @@ require ( github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/afero v1.11.0 // indirect @@ -231,11 +240,14 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.18.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect + github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/tidwall/btree v1.7.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect github.com/ulikunitz/xz v0.5.11 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect @@ -271,5 +283,6 @@ require ( modernc.org/token v1.1.0 // indirect nhooyr.io/websocket v1.8.7 // indirect pgregory.net/rapid v1.1.0 // indirect + rsc.io/tmplfunc v0.0.3 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index 3e2bd5fc9..e6b659a1e 100644 --- a/go.sum +++ b/go.sum @@ -254,6 +254,8 @@ github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDO github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/StirlingMarketingGroup/go-namecase v1.0.0 h1:2CzaNtCzc4iNHirR+5ru9OzGg8rQp860gqLBFqRI02Y= github.com/StirlingMarketingGroup/go-namecase v1.0.0/go.mod h1:ZsoSKcafcAzuBx+sndbxHu/RjDcDTrEdT4UvhniHfio= +github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= +github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I= @@ -361,6 +363,10 @@ github.com/cometbft/cometbft v0.38.10 h1:2ePuglchT+j0Iao+cfmt/nw5U7K2lnGDzXSUPGV github.com/cometbft/cometbft v0.38.10/go.mod h1:jHPx9vQpWzPHEAiYI/7EDKaB1NXhK6o3SArrrY8ExKc= github.com/cometbft/cometbft-db v0.10.0 h1:VMBQh88zXn64jXVvj39tlu/IgsGR84T7ImjS523DCiU= github.com/cometbft/cometbft-db v0.10.0/go.mod h1:7RR7NRv99j7keWJ5IkE9iZibUTKYdtepXTp7Ra0FxKk= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -397,9 +403,15 @@ github.com/cosmos/interchain-security/v5 v5.0.0-alpha1.0.20240424193412-7cd900ad github.com/cosmos/interchain-security/v5 v5.0.0-alpha1.0.20240424193412-7cd900ad2a74/go.mod h1:h/RkwOppo5AJj+1pkQyfjqU1MPdpohD/S6oEeAXpGZY= github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= +github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c h1:uQYC5Z1mdLRPrZhHjHxufI8+2UG/i25QG92j0Er9p6I= +github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= +github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI= +github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= @@ -465,14 +477,20 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= +github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-ethereum v1.14.5 h1:szuFzO1MhJmweXjoM5nSAeDvjNUH3vIQoMzzQnfvjpw= github.com/ethereum/go-ethereum v1.14.5/go.mod h1:VEDGGhSxY7IEjn98hJRFXl/uFvpRgbIIf2PpXiyGGgc= +github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0 h1:KrE8I4reeVvf7C1tm8elRjj4BdscTYzz/WAbYyf/JI4= +github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0/go.mod h1:D9AJLVXSyZQXJQVk8oh1EwjISE+sJTn2duYIZC0dy3w= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA= +github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -484,6 +502,8 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/tcell/v2 v2.4.1-0.20210905002822-f057f0a857a1/go.mod h1:Az6Jt+M5idSED2YPGtwnfJV0kXohgdCBPmHGSYc1r04= @@ -520,6 +540,7 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -549,10 +570,14 @@ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MG github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= @@ -651,6 +676,7 @@ github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwg github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -703,6 +729,8 @@ github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIv github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= @@ -751,6 +779,10 @@ github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU= github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -759,6 +791,8 @@ github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0Jr github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -773,6 +807,8 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -816,6 +852,10 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= @@ -879,6 +919,11 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -932,6 +977,8 @@ github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQ github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -1052,7 +1099,9 @@ github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= @@ -1099,6 +1148,8 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -1124,6 +1175,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= +github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= @@ -1156,9 +1209,14 @@ github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0o github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= +github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1402,6 +1460,7 @@ golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1477,6 +1536,8 @@ golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= @@ -1831,6 +1892,8 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= @@ -1899,6 +1962,8 @@ pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/ibc/chain.go b/ibc/chain.go index 780400b3d..d7d11cd74 100644 --- a/ibc/chain.go +++ b/ibc/chain.go @@ -98,4 +98,5 @@ type TransferOptions struct { Timeout *IBCTimeout Memo string AbsoluteTimeouts bool + Port string // default: transfer }