From 927e602e063e9459a7379c585d9fdbdb266d2887 Mon Sep 17 00:00:00 2001 From: Andrey Georgiev Date: Fri, 3 Apr 2026 13:59:58 +0300 Subject: [PATCH] Extend bridge config to include destination operations cost and refactor the config --- ...fungible_token.go => evm_regular_token.go} | 2 +- app/domain/service/assets.go | 4 +- app/model/asset/asset.go | 1 + app/model/bridge-config-event/params.go | 2 +- app/process/watcher/assets/watcher.go | 12 +- app/process/watcher/prometheus/watcher.go | 8 +- app/process/watcher/transfer/watcher_test.go | 14 -- app/router/assets/assets.go | 10 +- app/router/assets/assets_test.go | 7 + app/services/assets/assets.go | 168 ++++++++------- app/services/assets/assets_test.go | 95 +++++---- app/services/bridge-config/service_test.go | 52 +++-- app/services/prometheus/service_test.go | 4 +- bootstrap/clients.go | 119 ++++++----- bootstrap/server.go | 4 +- bootstrap/services.go | 8 +- bootstrap/watchers.go | 8 +- cmd/main.go | 2 +- config/bridge.go | 198 ++++++++---------- config/bridge_test.go | 83 ++++---- config/parser/bridge.go | 66 +++--- e2e/setup/config.go | 21 +- e2e/setup/evm/setup.go | 16 +- .../extend-config/cmd/extend-bridge-config.go | 2 +- .../bridge/setup/parser/extended-bridge.go | 84 +++++--- test/constants/bridge.go | 84 ++++---- test/helper/networks.go | 6 +- ...ck.go => evm_regular_token_client_mock.go} | 12 +- test/mocks/service/assets_service_mock.go | 4 +- test/mocks/setup.go | 4 +- 30 files changed, 584 insertions(+), 516 deletions(-) rename app/domain/client/{evm_fungible_token.go => evm_regular_token.go} (96%) rename test/mocks/client/{evm_fungible_token_client_mock.go => evm_regular_token_client_mock.go} (71%) diff --git a/app/domain/client/evm_fungible_token.go b/app/domain/client/evm_regular_token.go similarity index 96% rename from app/domain/client/evm_fungible_token.go rename to app/domain/client/evm_regular_token.go index 7478d9035..cbe08fdc0 100644 --- a/app/domain/client/evm_fungible_token.go +++ b/app/domain/client/evm_regular_token.go @@ -22,7 +22,7 @@ import ( "math/big" ) -type EvmFungibleToken interface { +type EvmRegularToken interface { Decimals(opts *bind.CallOpts) (uint8, error) Name(opts *bind.CallOpts) (string, error) Symbol(opts *bind.CallOpts) (string, error) diff --git a/app/domain/service/assets.go b/app/domain/service/assets.go index 6f5711cab..921539b15 100644 --- a/app/domain/service/assets.go +++ b/app/domain/service/assets.go @@ -45,6 +45,6 @@ type Assets interface { FungibleAssetInfo(networkId uint64, assetAddress string) (assetInfo *assetModel.FungibleAssetInfo, exist bool) // FetchHederaTokenReserveAmount Gets Hedera's Token Reserve Amount FetchHederaTokenReserveAmount(assetId string, mirrorNode client.MirrorNode, isNative bool, hederaTokenBalances map[string]int) (reserveAmount *big.Int, err error) - // FetchEvmFungibleReserveAmount Gets EVM's Fungible Token Reserve Amount - FetchEvmFungibleReserveAmount(networkId uint64, assetAddress string, isNative bool, evmTokenClient client.EvmFungibleToken, routerContractAddress string) (inLowestDenomination *big.Int, err error) + // FetchEvmRegularReserveAmount Gets EVM's Fungible Token Reserve Amount + FetchEvmRegularReserveAmount(networkId uint64, assetAddress string, isNative bool, evmTokenClient client.EvmRegularToken, routerContractAddress string) (inLowestDenomination *big.Int, err error) } diff --git a/app/model/asset/asset.go b/app/model/asset/asset.go index f62250e54..643beefe9 100644 --- a/app/model/asset/asset.go +++ b/app/model/asset/asset.go @@ -27,6 +27,7 @@ type NativeAsset struct { ChainId uint64 Asset string FeePercentage int64 + ReleaseTimestamp uint64 } type FungibleAssetInfo struct { diff --git a/app/model/bridge-config-event/params.go b/app/model/bridge-config-event/params.go index b315678f3..a42359f27 100644 --- a/app/model/bridge-config-event/params.go +++ b/app/model/bridge-config-event/params.go @@ -25,6 +25,6 @@ import ( type Params struct { Bridge *config.Bridge ParsedBridge *parser.Bridge - EvmFungibleTokenClients map[uint64]map[string]client.EvmFungibleToken + EvmRegularTokenClients map[uint64]map[string]client.EvmRegularToken RouterClients map[uint64]client.DiamondRouter } diff --git a/app/process/watcher/assets/watcher.go b/app/process/watcher/assets/watcher.go index f0a3eb290..be72fb2ef 100644 --- a/app/process/watcher/assets/watcher.go +++ b/app/process/watcher/assets/watcher.go @@ -39,7 +39,7 @@ var ( type Watcher struct { mirrorNode client.MirrorNode - evmFungibleTokenClients map[uint64]map[string]client.EvmFungibleToken + evmRegularTokenClients map[uint64]map[string]client.EvmRegularToken bridgeCfg *config.Bridge assetsService service.Assets paused bool @@ -49,13 +49,13 @@ type Watcher struct { func NewWatcher( mirrorNode client.MirrorNode, bridgeCfg *config.Bridge, - EvmFungibleTokenClients map[uint64]map[string]client.EvmFungibleToken, + EvmRegularTokenClients map[uint64]map[string]client.EvmRegularToken, assetsService service.Assets, ) *Watcher { instance := &Watcher{ mirrorNode: mirrorNode, - evmFungibleTokenClients: EvmFungibleTokenClients, + evmRegularTokenClients: EvmRegularTokenClients, bridgeCfg: bridgeCfg, logger: config.GetLoggerFor(fmt.Sprintf("Assets Watcher on interval [%v]", sleepTime)), assetsService: assetsService, @@ -125,11 +125,11 @@ func (pw *Watcher) updateAssetInfo(networkId uint64, assetId string, hederaToken if networkId == constants.HederaNetworkId { reserveAmount, err = pw.assetsService.FetchHederaTokenReserveAmount(assetId, pw.mirrorNode, isNative, hederaTokenBalances) } else { - reserveAmount, err = pw.assetsService.FetchEvmFungibleReserveAmount( + reserveAmount, err = pw.assetsService.FetchEvmRegularReserveAmount( networkId, assetId, isNative, - pw.evmFungibleTokenClients[networkId][assetId], + pw.evmRegularTokenClients[networkId][assetId], pw.bridgeCfg.EVMs[networkId].RouterContractAddress, ) } @@ -152,7 +152,7 @@ func bridgeCfgUpdateEventHandler(e event.Event, instance *Watcher) error { log.Errorf(errMsg) return errors.New(errMsg) } - instance.evmFungibleTokenClients = params.EvmFungibleTokenClients + instance.evmRegularTokenClients = params.EvmRegularTokenClients instance.bridgeCfg = params.Bridge instance.watchIteration() diff --git a/app/process/watcher/prometheus/watcher.go b/app/process/watcher/prometheus/watcher.go index 4d994d74d..74dec10ef 100644 --- a/app/process/watcher/prometheus/watcher.go +++ b/app/process/watcher/prometheus/watcher.go @@ -45,7 +45,7 @@ var ( type Watcher struct { dashboardPolling time.Duration mirrorNode client.MirrorNode - evmFungibleTokenClients map[uint64]map[string]client.EvmFungibleToken + evmRegularTokenClients map[uint64]map[string]client.EvmRegularToken bridgeCfg *config.Bridge prometheusService service.Prometheus logger *log.Entry @@ -69,13 +69,13 @@ func NewWatcher( mirrorNode client.MirrorNode, bridgeCfg *config.Bridge, prometheusService service.Prometheus, - EvmFungibleTokenClients map[uint64]map[string]client.EvmFungibleToken, + EvmRegularTokenClients map[uint64]map[string]client.EvmRegularToken, assetsService service.Assets, ) *Watcher { instance := &Watcher{ dashboardPolling: dashboardPolling, mirrorNode: mirrorNode, - evmFungibleTokenClients: EvmFungibleTokenClients, + evmRegularTokenClients: EvmRegularTokenClients, bridgeCfg: bridgeCfg, prometheusService: prometheusService, logger: config.GetLoggerFor(fmt.Sprintf("Prometheus Metrics Watcher on interval [%s]", dashboardPolling)), @@ -368,7 +368,7 @@ func bridgeCfgUpdateEventHandler(e event.Event, instance *Watcher) error { log.Errorf(errMsg) return errors.New(errMsg) } - instance.evmFungibleTokenClients = params.EvmFungibleTokenClients + instance.evmRegularTokenClients = params.EvmRegularTokenClients instance.bridgeCfg = params.Bridge // Clear All Metrics for _, metricsInNetwork := range instance.assetsMetrics { diff --git a/app/process/watcher/transfer/watcher_test.go b/app/process/watcher/transfer/watcher_test.go index 0ad954cd5..6eea15a24 100644 --- a/app/process/watcher/transfer/watcher_test.go +++ b/app/process/watcher/transfer/watcher_test.go @@ -32,7 +32,6 @@ import ( iservice "github.com/limechain/hedera-eth-bridge-validator/app/domain/service" "github.com/limechain/hedera-eth-bridge-validator/app/model/asset" "github.com/limechain/hedera-eth-bridge-validator/app/model/pricing" - "github.com/limechain/hedera-eth-bridge-validator/config/parser" "github.com/limechain/hedera-eth-bridge-validator/constants" "github.com/limechain/hedera-eth-bridge-validator/test/mocks" "github.com/shopspring/decimal" @@ -66,19 +65,6 @@ var ( ConsensusTimestamp: "1631092491.483966000", } - networks = map[uint64]*parser.Network{ - network0: { - Tokens: parser.Tokens{ - Fungible: map[string]parser.Token{ - nativeTokenAddressNetwork0: { - Networks: map[uint64]string{ - network3: wrappedTokenAddressNetwork3, - }, - }, - }, - }, - }, - } ) func Test_NewMemo_MissingWrappedCorrelation(t *testing.T) { diff --git a/app/router/assets/assets.go b/app/router/assets/assets.go index 623e8dcb4..964274f73 100644 --- a/app/router/assets/assets.go +++ b/app/router/assets/assets.go @@ -79,12 +79,16 @@ func generateResponseContent(assetsService service.Assets, pricingService servic fungibleAssetInfo, existInfo := assetsService.FungibleAssetInfo(networkId, assetAddress) minAmount, existMinAmount := pricingService.GetTokenPriceInfo(networkId, assetAddress) if existInfo && existMinAmount { - bridgeTokenInfo := bridgeCfg.Networks[networkId].Tokens.Fungible[assetAddress] var nativeAsset *asset.NativeAsset + var tokenNetworks map[uint64]string if !fungibleAssetInfo.IsNative { nativeAsset = assetsService.WrappedToNative(assetAddress, networkId) + if nativeAsset != nil { + tokenNetworks = assetsService.WrappedFromNative(nativeAsset.ChainId, nativeAsset.Asset) + } } else { nativeAsset = assetsService.FungibleNativeAsset(networkId, assetAddress) + tokenNetworks = assetsService.WrappedFromNative(networkId, assetAddress) } feePercentage := nativeAsset.FeePercentage @@ -93,9 +97,9 @@ func generateResponseContent(assetsService service.Assets, pricingService servic FeePercentage: feePercentageInfo{feePercentage, constants.FeeMaxPercentage}, MinAmount: minAmount.MinAmountWithFee.String(), UsdPrice: minAmount.UsdPrice.String(), - Networks: bridgeTokenInfo.Networks, + Networks: tokenNetworks, ReserveAmount: fungibleAssetInfo.ReserveAmount.String(), - ReleaseTimestamp: bridgeTokenInfo.ReleaseTimestamp, + ReleaseTimestamp: nativeAsset.ReleaseTimestamp, } response[networkId].Fungible[assetAddress] = fungibleAssetDetails } diff --git a/app/router/assets/assets_test.go b/app/router/assets/assets_test.go index bf28b604d..7edba5232 100644 --- a/app/router/assets/assets_test.go +++ b/app/router/assets/assets_test.go @@ -51,9 +51,16 @@ func Test_assetsResponse(t *testing.T) { if fungibleAssetInfo.IsNative { mocks.MAssetsService.On("FungibleNativeAsset", networkId, networkAsset). Return(testConstants.FungibleNativeAssets[networkId][networkAsset], true) + mocks.MAssetsService.On("WrappedFromNative", networkId, networkAsset). + Return(testConstants.NativeToWrapped[networkId][networkAsset]) } else { mocks.MAssetsService.On("WrappedToNative", networkAsset, networkId). Return(testConstants.WrappedToNative[networkId][networkAsset], true) + wrappedNative := testConstants.WrappedToNative[networkId][networkAsset] + if wrappedNative != nil { + mocks.MAssetsService.On("WrappedFromNative", wrappedNative.ChainId, wrappedNative.Asset). + Return(testConstants.NativeToWrapped[wrappedNative.ChainId][wrappedNative.Asset]) + } } } } diff --git a/app/services/assets/assets.go b/app/services/assets/assets.go index 55f75783c..54e3ce89d 100644 --- a/app/services/assets/assets.go +++ b/app/services/assets/assets.go @@ -29,6 +29,7 @@ import ( "github.com/limechain/hedera-eth-bridge-validator/app/clients/hedera/mirror-node/model/token" client "github.com/limechain/hedera-eth-bridge-validator/app/domain/client" decimalHelper "github.com/limechain/hedera-eth-bridge-validator/app/helper/decimal" + "github.com/shopspring/decimal" assetModel "github.com/limechain/hedera-eth-bridge-validator/app/model/asset" bridge_config_event "github.com/limechain/hedera-eth-bridge-validator/app/model/bridge-config-event" "github.com/limechain/hedera-eth-bridge-validator/config" @@ -110,11 +111,11 @@ func (a *Service) FungibleAssetInfo(networkId uint64, assetAddressOrId string) ( return assetInfo, exist } -func (a *Service) FetchEvmFungibleReserveAmount( +func (a *Service) FetchEvmRegularReserveAmount( networkId uint64, assetAddress string, isNative bool, - evmTokenClient client.EvmFungibleToken, + evmTokenClient client.EvmRegularToken, routerContractAddress string, ) (inLowestDenomination *big.Int, err error) { if isNative { @@ -163,7 +164,7 @@ func (a *Service) FetchHederaTokenReserveAmount( func (a *Service) fetchEvmFungibleAssetInfo( networkId uint64, assetAddress string, - evmTokenClient client.EvmFungibleToken, + evmTokenClient client.EvmRegularToken, isNative bool, routerContractAddress string, ) (assetInfo *assetModel.FungibleAssetInfo, err error) { @@ -191,7 +192,7 @@ func (a *Service) fetchEvmFungibleAssetInfo( return assetInfo, err } assetInfo.Decimals = decimals - assetInfo.ReserveAmount, err = a.FetchEvmFungibleReserveAmount(networkId, assetAddress, isNative, evmTokenClient, routerContractAddress) + assetInfo.ReserveAmount, err = a.FetchEvmRegularReserveAmount(networkId, assetAddress, isNative, evmTokenClient, routerContractAddress) return assetInfo, err } @@ -228,39 +229,52 @@ func (a *Service) fetchHederaFungibleAssetInfo( } func (a *Service) loadFungibleAssetInfos( - networks map[uint64]*parser.Network, + regularTokens map[string]*parser.RegularToken, + evmNetworks map[uint64]*parser.EVMNetwork, mirrorNode client.MirrorNode, - evmTokenClients map[uint64]map[string]client.EvmFungibleToken, + evmTokenClients map[uint64]map[string]client.EvmRegularToken, hederaTokenBalances map[string]int, ) { a.fungibleAssetInfos = make(map[uint64]map[string]*assetModel.FungibleAssetInfo) - for nativeChainId, networkInfo := range networks { + for tokenName, tokenInfo := range regularTokens { + nativeChainId := tokenInfo.NativeChain + nativeAsset := tokenName + if tokenInfo.Address != nil && *tokenInfo.Address != "" { + nativeAsset = *tokenInfo.Address + } + if _, ok := a.fungibleAssetInfos[nativeChainId]; !ok { a.fungibleAssetInfos[nativeChainId] = make(map[string]*assetModel.FungibleAssetInfo) } - for nativeAsset, nativeAssetMapping := range networkInfo.Tokens.Fungible { - assetInfo, nativeAsset, err := a.fetchFungibleAssetInfo(nativeChainId, nativeAsset, mirrorNode, evmTokenClients, true, hederaTokenBalances, networks[nativeChainId].RouterContractAddress) + assetInfo, nativeAsset, err := a.fetchFungibleAssetInfo(nativeChainId, nativeAsset, mirrorNode, evmTokenClients, true, hederaTokenBalances, a.evmRouterAddr(evmNetworks, nativeChainId)) + if err != nil { + a.logger.Fatal(err) + } + a.fungibleAssetInfos[nativeChainId][nativeAsset] = assetInfo + + for wrappedChainId, wrappedAsset := range tokenInfo.AddressesPerNetwork { + if _, ok := a.fungibleAssetInfos[wrappedChainId]; !ok { + a.fungibleAssetInfos[wrappedChainId] = make(map[string]*assetModel.FungibleAssetInfo) + } + var wrappedInfo *assetModel.FungibleAssetInfo + wrappedInfo, wrappedAsset, err = a.fetchFungibleAssetInfo(wrappedChainId, wrappedAsset, mirrorNode, evmTokenClients, false, hederaTokenBalances, a.evmRouterAddr(evmNetworks, wrappedChainId)) if err != nil { a.logger.Fatal(err) } - a.fungibleAssetInfos[nativeChainId][nativeAsset] = assetInfo - - for wrappedChainId, wrappedAsset := range nativeAssetMapping.Networks { - if _, ok := a.fungibleAssetInfos[wrappedChainId]; !ok { - a.fungibleAssetInfos[wrappedChainId] = make(map[string]*assetModel.FungibleAssetInfo) - } - assetInfo, wrappedAsset, err = a.fetchFungibleAssetInfo(wrappedChainId, wrappedAsset, mirrorNode, evmTokenClients, false, hederaTokenBalances, networks[wrappedChainId].RouterContractAddress) - if err != nil { - a.logger.Fatal(err) - } - a.fungibleAssetInfos[wrappedChainId][wrappedAsset] = assetInfo - } + a.fungibleAssetInfos[wrappedChainId][wrappedAsset] = wrappedInfo } } } +func (a *Service) evmRouterAddr(evmNetworks map[uint64]*parser.EVMNetwork, chainId uint64) string { + if net, ok := evmNetworks[chainId]; ok { + return net.RouterContractAddress + } + return "" +} + func (a *Service) getHederaTokenReserveAmount( assetId string, isNative bool, @@ -285,7 +299,7 @@ func (a *Service) fetchFungibleAssetInfo( chainId uint64, assetAddress string, mirrorNode client.MirrorNode, - evmTokenClients map[uint64]map[string]client.EvmFungibleToken, + evmTokenClients map[uint64]map[string]client.EvmRegularToken, isNative bool, hederaTokenBalances map[string]int, routerContractAddress string, @@ -321,15 +335,17 @@ func (a *Service) fetchFungibleAssetInfo( } func NewService( - networks map[uint64]*parser.Network, + regularTokens map[string]*parser.RegularToken, + evmNetworks map[uint64]*parser.EVMNetwork, bridgeAccountId string, hederaFeePercentages map[string]int64, routerClients map[uint64]client.DiamondRouter, mirrorNode client.MirrorNode, - evmTokenClients map[uint64]map[string]client.EvmFungibleToken, + evmTokenClients map[uint64]map[string]client.EvmRegularToken, ) *Service { instance := initialize( - networks, + regularTokens, + evmNetworks, bridgeAccountId, hederaFeePercentages, routerClients, @@ -344,7 +360,7 @@ func NewService( return instance } -func initialize(networks map[uint64]*parser.Network, bridgeAccountId string, HederaFeePercentages map[string]int64, routerClients map[uint64]client.DiamondRouter, mirrorNode client.MirrorNode, evmTokenClients map[uint64]map[string]client.EvmFungibleToken) *Service { +func initialize(regularTokens map[string]*parser.RegularToken, evmNetworks map[uint64]*parser.EVMNetwork, bridgeAccountId string, HederaFeePercentages map[string]int64, routerClients map[uint64]client.DiamondRouter, mirrorNode client.MirrorNode, evmTokenClients map[uint64]map[string]client.EvmRegularToken) *Service { nativeToWrapped := make(map[uint64]map[string]map[uint64]string) wrappedToNative := make(map[uint64]map[string]*assetModel.NativeAsset) fungibleNetworkAssets := make(map[uint64][]string) @@ -352,63 +368,72 @@ func initialize(networks map[uint64]*parser.Network, bridgeAccountId string, Hed re := regexp.MustCompile(constants.EvmCompatibleAddressPattern) - for nativeChainId, network := range networks { + for tokenName, tokenInfo := range regularTokens { + nativeChainId := tokenInfo.NativeChain + nativeAsset := tokenName + if tokenInfo.Address != nil && *tokenInfo.Address != "" { + nativeAsset = *tokenInfo.Address + } + if nativeChainId != constants.HederaNetworkId { + nativeAsset = common.HexToAddress(nativeAsset).String() + } + if nativeToWrapped[nativeChainId] == nil { nativeToWrapped[nativeChainId] = make(map[string]map[uint64]string) } if fungibleNativeAssets[nativeChainId] == nil { fungibleNativeAssets[nativeChainId] = make(map[string]*assetModel.NativeAsset) } + if nativeToWrapped[nativeChainId][nativeAsset] == nil { + nativeToWrapped[nativeChainId][nativeAsset] = make(map[uint64]string) + } - for nativeAsset, nativeAssetMapping := range network.Tokens.Fungible { - if nativeChainId != constants.HederaNetworkId { - nativeAsset = common.HexToAddress(nativeAsset).String() - } - - if nativeToWrapped[nativeChainId][nativeAsset] == nil { - nativeToWrapped[nativeChainId][nativeAsset] = make(map[uint64]string) - } - - minAmount, err := decimalHelper.ParseAmount(nativeAssetMapping.MinFeeAmountInUsd) + var minAmount *decimal.Decimal + if tokenInfo.MinFeeAmountInUsd != nil { + minAmount = tokenInfo.MinFeeAmountInUsd + } else { + var err error + minAmount, err = decimalHelper.ParseAmount("") if err != nil { - log.Fatalf("Failed to parse min amount [%s]. Error: [%s]", nativeAssetMapping.MinFeeAmountInUsd, err) + log.Fatalf("Failed to parse min amount. Error: [%s]", err) } - var feePercentage int64 - if nativeChainId == constants.HederaNetworkId { - feePercentage = HederaFeePercentages[nativeAsset] - } else { - routerClient, exist := routerClients[nativeChainId] - if exist { - tokenFeeData, err := routerClient.TokenFeeData(&bind.CallOpts{}, common.HexToAddress(nativeAsset)) - if err != nil { - log.Fatalf("Failed to get fee persentage from router contact for asset [%s]. Error: [%s]", nativeAsset, err) - } - feePercentage = tokenFeeData.ServiceFeePercentage.Int64() + } + var feePercentage int64 + if nativeChainId == constants.HederaNetworkId { + feePercentage = HederaFeePercentages[nativeAsset] + } else { + routerClient, exist := routerClients[nativeChainId] + if exist { + tokenFeeData, err := routerClient.TokenFeeData(&bind.CallOpts{}, common.HexToAddress(nativeAsset)) + if err != nil { + log.Fatalf("Failed to get fee percentage from router contract for asset [%s]. Error: [%s]", nativeAsset, err) } + feePercentage = tokenFeeData.ServiceFeePercentage.Int64() } + } - asset := &assetModel.NativeAsset{ - MinFeeAmountInUsd: minAmount, - ChainId: nativeChainId, - Asset: nativeAsset, - FeePercentage: feePercentage, - } - fungibleNativeAssets[nativeChainId][nativeAsset] = asset + asset := &assetModel.NativeAsset{ + MinFeeAmountInUsd: minAmount, + ChainId: nativeChainId, + Asset: nativeAsset, + FeePercentage: feePercentage, + ReleaseTimestamp: tokenInfo.ReleaseTimestamp, + } + fungibleNativeAssets[nativeChainId][nativeAsset] = asset - fungibleNetworkAssets[nativeChainId] = append(fungibleNetworkAssets[nativeChainId], nativeAsset) - for wrappedChainId, wrappedAsset := range nativeAssetMapping.Networks { - if isMatch := re.MatchString(wrappedAsset); isMatch { - wrappedAsset = common.HexToAddress(wrappedAsset).String() - } + fungibleNetworkAssets[nativeChainId] = append(fungibleNetworkAssets[nativeChainId], nativeAsset) + for wrappedChainId, wrappedAsset := range tokenInfo.AddressesPerNetwork { + if isMatch := re.MatchString(wrappedAsset); isMatch { + wrappedAsset = common.HexToAddress(wrappedAsset).String() + } - nativeToWrapped[nativeChainId][nativeAsset][wrappedChainId] = wrappedAsset + nativeToWrapped[nativeChainId][nativeAsset][wrappedChainId] = wrappedAsset - if wrappedToNative[wrappedChainId] == nil { - wrappedToNative[wrappedChainId] = make(map[string]*assetModel.NativeAsset) - } - fungibleNetworkAssets[wrappedChainId] = append(fungibleNetworkAssets[wrappedChainId], wrappedAsset) - wrappedToNative[wrappedChainId][wrappedAsset] = asset + if wrappedToNative[wrappedChainId] == nil { + wrappedToNative[wrappedChainId] = make(map[string]*assetModel.NativeAsset) } + fungibleNetworkAssets[wrappedChainId] = append(fungibleNetworkAssets[wrappedChainId], wrappedAsset) + wrappedToNative[wrappedChainId][wrappedAsset] = asset } } logger := config.GetLoggerFor("Assets Service") @@ -428,7 +453,7 @@ func initialize(networks map[uint64]*parser.Network, bridgeAccountId string, Hed return nil } hederaTokenBalances := bridgeAccount.Balance.GetAccountTokenBalancesByAddress() - instance.loadFungibleAssetInfos(networks, mirrorNode, evmTokenClients, hederaTokenBalances) + instance.loadFungibleAssetInfos(regularTokens, evmNetworks, mirrorNode, evmTokenClients, hederaTokenBalances) return instance } @@ -442,12 +467,13 @@ func bridgeCfgUpdateEventHandler(e event.Event, mirrorNode client.MirrorNode, in } newInstance := initialize( - params.ParsedBridge.Networks, - params.ParsedBridge.Networks[constants.HederaNetworkId].BridgeAccount, + params.ParsedBridge.RegularTokens, + params.ParsedBridge.Networks.EVM, + params.Bridge.Hedera.BridgeAccount, params.Bridge.Hedera.FeePercentages, params.RouterClients, mirrorNode, - params.EvmFungibleTokenClients, + params.EvmRegularTokenClients, ) *instance = *newInstance params.Bridge.LoadStaticMinAmountsForWrappedFungibleTokens(*params.ParsedBridge, instance) diff --git a/app/services/assets/assets_test.go b/app/services/assets/assets_test.go index 94a155fb3..fddc48a3a 100644 --- a/app/services/assets/assets_test.go +++ b/app/services/assets/assets_test.go @@ -41,7 +41,7 @@ var ( routerClients = make(map[uint64]client.DiamondRouter) evmClients = make(map[uint64]client.EVM) evmCoreClients = make(map[uint64]client.Core) - evmFungibleTokenClients = make(map[uint64]map[string]client.EvmFungibleToken) + evmRegularTokenClients = make(map[uint64]map[string]client.EvmRegularToken) hederaPercentages = make(map[string]int64) hederaAccount = account.AccountsResponse{ Account: testConstants.BridgeAccountId, @@ -59,14 +59,21 @@ func Test_New(t *testing.T) { setup() setupClientMocks() - actualService := NewService(testConstants.ParserBridge.Networks, testConstants.ParserBridge.Networks[constants.HederaNetworkId].BridgeAccount, hederaPercentages, routerClients, mocks.MHederaMirrorClient, evmFungibleTokenClients) + actualService := NewService(testConstants.ParserBridge.RegularTokens, testConstants.ParserBridge.Networks.EVM, testConstants.BridgeAccountId, hederaPercentages, routerClients, mocks.MHederaMirrorClient, evmRegularTokenClients) assert.Equal(t, serviceInstance.nativeToWrapped, actualService.nativeToWrapped) assert.Equal(t, serviceInstance.wrappedToNative, actualService.wrappedToNative) assert.Equal(t, serviceInstance.fungibleNativeAssets, actualService.fungibleNativeAssets) assert.Equal(t, serviceInstance.fungibleAssetInfos, actualService.fungibleAssetInfos) - for networkId := range testConstants.Networks { + allNetworkIds := make(map[uint64]struct{}) + for networkId := range testConstants.HederaNetworks { + allNetworkIds[networkId] = struct{}{} + } + for networkId := range testConstants.EVMNetworks { + allNetworkIds[networkId] = struct{}{} + } + for networkId := range allNetworkIds { // Fungible sort.Strings(serviceInstance.fungibleNetworkAssets[networkId]) sort.Strings(actualService.fungibleNetworkAssets[networkId]) @@ -190,31 +197,31 @@ func Test_FungibleAssetInfo(t *testing.T) { assert.Equal(t, expected, actual) } -func Test_FetchEvmFungibleReserveAmount_Native(t *testing.T) { +func Test_FetchEvmRegularReserveAmount_Native(t *testing.T) { setup() setupClientMocks() asset := testConstants.NetworkEthereumFungibleNativeToken - tokenClient := evmFungibleTokenClients[testConstants.EthereumNetworkId][asset] + tokenClient := evmRegularTokenClients[testConstants.EthereumNetworkId][asset] expectedReserveAmount := testConstants.ReserveAmountBigInt - tokenClient.(*testClient.MockEvmFungibleToken).On("BalanceOf", &bind.CallOpts{}, common.HexToAddress(routerContractAddress)).Return(expectedReserveAmount, nil) + tokenClient.(*testClient.MockEvmRegularToken).On("BalanceOf", &bind.CallOpts{}, common.HexToAddress(routerContractAddress)).Return(expectedReserveAmount, nil) - actual, err := serviceInstance.FetchEvmFungibleReserveAmount(testConstants.EthereumNetworkId, asset, true, tokenClient, routerContractAddress) + actual, err := serviceInstance.FetchEvmRegularReserveAmount(testConstants.EthereumNetworkId, asset, true, tokenClient, routerContractAddress) assert.Nil(t, err) assert.Equal(t, expectedReserveAmount, actual) } -func Test_FetchEvmFungibleReserveAmount_Wrapped(t *testing.T) { +func Test_FetchEvmRegularReserveAmount_Wrapped(t *testing.T) { setup() setupClientMocks() asset := testConstants.NetworkEthereumFungibleWrappedTokenForNetworkHedera - tokenClient := evmFungibleTokenClients[testConstants.EthereumNetworkId][asset] + tokenClient := evmRegularTokenClients[testConstants.EthereumNetworkId][asset] expectedReserveAmount := testConstants.ReserveAmountBigInt - tokenClient.(*testClient.MockEvmFungibleToken).On("TotalSupply", &bind.CallOpts{}).Return(expectedReserveAmount, nil) + tokenClient.(*testClient.MockEvmRegularToken).On("TotalSupply", &bind.CallOpts{}).Return(expectedReserveAmount, nil) - actual, err := serviceInstance.FetchEvmFungibleReserveAmount(testConstants.EthereumNetworkId, asset, false, tokenClient, routerContractAddress) + actual, err := serviceInstance.FetchEvmRegularReserveAmount(testConstants.EthereumNetworkId, asset, false, tokenClient, routerContractAddress) assert.Nil(t, err) assert.Equal(t, expectedReserveAmount, actual) @@ -264,48 +271,29 @@ func setup() { } func setupClientMocks() { - for networkId, networkInfo := range testConstants.Networks { - if networkId != constants.HederaNetworkId { - evmFungibleTokenClients[networkId] = make(map[string]client.EvmFungibleToken) - evmClients[networkId] = &testClient.MockEVM{} - evmCoreClients[networkId] = &testClient.MockEVMCore{} - evmClients[networkId].(*testClient.MockEVM).On("GetClient").Return(evmCoreClients[networkId]) - routerClients[networkId] = new(testClient.MockDiamondRouter) - } + // Setup EVM networks + for networkId, networkInfo := range testConstants.EVMNetworks { + evmRegularTokenClients[networkId] = make(map[string]client.EvmRegularToken) + evmClients[networkId] = &testClient.MockEVM{} + evmCoreClients[networkId] = &testClient.MockEVMCore{} + evmClients[networkId].(*testClient.MockEVM).On("GetClient").Return(evmCoreClients[networkId]) + routerClients[networkId] = new(testClient.MockDiamondRouter) - // FUNGIBLE // fungibleAssets := testConstants.FungibleNetworkAssets[networkId] for _, asset := range fungibleAssets { hederaPercentages[asset] = testConstants.FeePercentage assetInfo := testConstants.FungibleAssetInfos[networkId][asset] isNative := assetInfo.IsNative - if networkId == constants.HederaNetworkId { - hederaTokenBalances[asset] = int(testConstants.ReserveAmount) - hederaAccount.Balance.Tokens = append(hederaAccount.Balance.Tokens, account.AccountToken{ - TokenID: asset, - Balance: int(testConstants.ReserveAmount), - }) - // Hedera - tokenResponse := token.TokenResponse{ - TokenID: asset, - Name: asset, - Symbol: asset, - TotalSupply: testConstants.ReserveAmountStr, - Decimals: strconv.Itoa(int(constants.HederaDefaultDecimals)), - } - mocks.MHederaMirrorClient.On("GetToken", asset).Return(&tokenResponse, nil) - continue - } // EVM - evmFungibleTokenClients[networkId][asset] = new(testClient.MockEvmFungibleToken) - evmFungibleTokenClients[networkId][asset].(*testClient.MockEvmFungibleToken).On("Name", &bind.CallOpts{}).Return(asset, nil) - evmFungibleTokenClients[networkId][asset].(*testClient.MockEvmFungibleToken).On("Symbol", &bind.CallOpts{}).Return(asset, nil) - evmFungibleTokenClients[networkId][asset].(*testClient.MockEvmFungibleToken).On("Decimals", &bind.CallOpts{}).Return(constants.EvmDefaultDecimals, nil) + evmRegularTokenClients[networkId][asset] = new(testClient.MockEvmRegularToken) + evmRegularTokenClients[networkId][asset].(*testClient.MockEvmRegularToken).On("Name", &bind.CallOpts{}).Return(asset, nil) + evmRegularTokenClients[networkId][asset].(*testClient.MockEvmRegularToken).On("Symbol", &bind.CallOpts{}).Return(asset, nil) + evmRegularTokenClients[networkId][asset].(*testClient.MockEvmRegularToken).On("Decimals", &bind.CallOpts{}).Return(constants.EvmDefaultDecimals, nil) if isNative { - evmFungibleTokenClients[networkId][asset].(*testClient.MockEvmFungibleToken).On("BalanceOf", &bind.CallOpts{}, common.HexToAddress(networkInfo.RouterContractAddress)).Return(testConstants.ReserveAmountBigInt, nil) + evmRegularTokenClients[networkId][asset].(*testClient.MockEvmRegularToken).On("BalanceOf", &bind.CallOpts{}, common.HexToAddress(networkInfo.RouterContractAddress)).Return(testConstants.ReserveAmountBigInt, nil) } else { - evmFungibleTokenClients[networkId][asset].(*testClient.MockEvmFungibleToken).On("TotalSupply", &bind.CallOpts{}).Return(testConstants.ReserveAmountBigInt, nil) + evmRegularTokenClients[networkId][asset].(*testClient.MockEvmRegularToken).On("TotalSupply", &bind.CallOpts{}).Return(testConstants.ReserveAmountBigInt, nil) } tokenFeeDataResult := struct { ServiceFeePercentage *big.Int @@ -322,5 +310,26 @@ func setupClientMocks() { } } + // Setup Hedera networks + for networkId := range testConstants.HederaNetworks { + fungibleAssets := testConstants.FungibleNetworkAssets[networkId] + for _, asset := range fungibleAssets { + hederaPercentages[asset] = testConstants.FeePercentage + hederaTokenBalances[asset] = int(testConstants.ReserveAmount) + hederaAccount.Balance.Tokens = append(hederaAccount.Balance.Tokens, account.AccountToken{ + TokenID: asset, + Balance: int(testConstants.ReserveAmount), + }) + tokenResponse := token.TokenResponse{ + TokenID: asset, + Name: asset, + Symbol: asset, + TotalSupply: testConstants.ReserveAmountStr, + Decimals: strconv.Itoa(int(constants.HederaDefaultDecimals)), + } + mocks.MHederaMirrorClient.On("GetToken", asset).Return(&tokenResponse, nil) + } + } + mocks.MHederaMirrorClient.On("GetAccount", testConstants.BridgeAccountId).Return(&hederaAccount, nil) } diff --git a/app/services/bridge-config/service_test.go b/app/services/bridge-config/service_test.go index c49f09913..3afe09b21 100644 --- a/app/services/bridge-config/service_test.go +++ b/app/services/bridge-config/service_test.go @@ -59,43 +59,41 @@ var ( ConfigTopicId: configTopicId.String(), PollingInterval: time.Duration(10), TopicId: topicId.String(), - Networks: map[uint64]*parser.Network{ - 0: { - Name: "Hedera", - BridgeAccount: "0.0.111111111", - PayerAccount: "0.0.111111111", - RouterContractAddress: "", - Members: []string{"0.0.111111111"}, - Tokens: parser.Tokens{ - Fungible: map[string]parser.Token{ - "HBAR": { - FeePercentage: 10000, - MinFeeAmountInUsd: "0.001", - MinAmount: nil, - Networks: map[uint64]string{ - 3: "0xb083879B1e10C8476802016CB12cd2F22a896571", - 80001: "0xb083879B1e10C14761010161B12cd2F25a896691", - }, - CoinGeckoId: "hedera-hashgraph", - CoinMarketCapId: "4642", - }, - }, + Networks: parser.Networks{ + Hedera: map[uint64]*parser.HederaNetwork{ + 0: { + Name: "Hedera", + BridgeAccount: "0.0.111111111", + PayerAccount: "0.0.111111111", + Members: []string{"0.0.111111111"}, + }, + }, + }, + RegularTokens: map[string]*parser.RegularToken{ + "HBAR": { + NativeChain: 0, + CoinGeckoId: "hedera-hashgraph", + CoinMarketCapId: "4642", + FeePercentage: 10000, + AddressesPerNetwork: map[uint64]string{ + 3: "0xb083879B1e10C8476802016CB12cd2F22a896571", + 80001: "0xb083879B1e10C14761010161B12cd2F25a896691", }, }, }, MonitoredAccounts: nil, } - encodedOneChunkConfig = "IyBUaGlzIGZpbGUgY29udGFpbnMgYXBwbGljYXRpb24gZGVmYXVsdHMKIyBDaGVjayBkb2NzL2NvbmZpZ3VyYXRpb24ubWQgZm9yIG1vcmUgaW5mb3JtYXRpb24KYnJpZGdlOgogIHVzZV9sb2NhbF9jb25maWc6IGZhbHNlCiAgY29uZmlnX3RvcGljX2lkOiAwLjAuMgogIHBvbGxpbmdfaW50ZXJ2YWw6IDEwICMgaW4gc2Vjb25kcwogIHRvcGljX2lkOiAwLjAuMQogIG5ldHdvcmtzOgogICAgMDogIyBIZWRlcmEKICAgICAgbmFtZTogSGVkZXJhCiAgICAgIGJyaWRnZV9hY2NvdW50OiAwLjAuMTExMTExMTExCiAgICAgIHBheWVyX2FjY291bnQ6IDAuMC4xMTExMTExMTEKICAgICAgbWVtYmVyczoKICAgICAgICAtIDAuMC4xMTExMTExMTEKICAgICAgdG9rZW5zOgogICAgICAgIGZ1bmdpYmxlOgogICAgICAgICAgIkhCQVIiOgogICAgICAgICAgICBmZWVfcGVyY2VudGFnZTogMTAwMDAgIyAxMC4wMDAlCiAgICAgICAgICAgIGNvaW5fZ2Vja29faWQ6ICJoZWRlcmEtaGFzaGdyYXBoIgogICAgICAgICAgICBjb2luX21hcmtldF9jYXBfaWQ6ICI0NjQyIgogICAgICAgICAgICBtaW5fZmVlX2Ftb3VudF9pbl91c2Q6IDAuMDAxICMgVVNECiAgICAgICAgICAgIG5ldHdvcmtzOgogICAgICAgICAgICAgIDM6ICIweGIwODM4NzlCMWUxMEM4NDc2ODAyMDE2Q0IxMmNkMkYyMmE4OTY1NzEiCiAgICAgICAgICAgICAgODAwMDE6ICIweGIwODM4NzlCMWUxMEMxNDc2MTAxMDE2MUIxMmNkMkYyNWE4OTY2OTEi" + encodedOneChunkConfig = "YnJpZGdlOgogIHVzZV9sb2NhbF9jb25maWc6IGZhbHNlCiAgY29uZmlnX3RvcGljX2lkOiAwLjAuMgogIHBvbGxpbmdfaW50ZXJ2YWw6IDEwCiAgdG9waWNfaWQ6IDAuMC4xCiAgbmV0d29ya3M6CiAgICBoZWRlcmE6CiAgICAgIDA6CiAgICAgICAgbmFtZTogSGVkZXJhCiAgICAgICAgYnJpZGdlX2FjY291bnQ6IDAuMC4xMTExMTExMTEKICAgICAgICBwYXllcl9hY2NvdW50OiAwLjAuMTExMTExMTExCiAgICAgICAgbWVtYmVyczoKICAgICAgICAgIC0gMC4wLjExMTExMTExMQogIHJlZ3VsYXJfdG9rZW5zOgogICAgIkhCQVIiOgogICAgICBuYXRpdmVfY2hhaW46IDAKICAgICAgY29pbl9nZWNrb19pZDogImhlZGVyYS1oYXNoZ3JhcGgiCiAgICAgIGNvaW5fbWFya2V0X2NhcF9pZDogIjQ2NDIiCiAgICAgIGZlZV9wZXJjZW50YWdlOiAxMDAwMAogICAgICBhZGRyZXNzZXNfcGVyX25ldHdvcms6CiAgICAgICAgMzogIjB4YjA4Mzg3OUIxZTEwQzg0NzY4MDIwMTZDQjEyY2QyRjIyYTg5NjU3MSIKICAgICAgICA4MDAwMTogIjB4YjA4Mzg3OUIxZTEwQzE0NzYxMDEwMTYxQjEyY2QyRjI1YTg5NjY5MSIK" encodedTwoChunkConfig = []string{ - "IyBUaGlzIGZpbGUgY29udGFpbnMgYXBwbGljYXRpb24gZGVmYXVsdHMKIyBDaGVjayBkb2NzL2NvbmZpZ3VyYXRpb24ubWQgZm9yIG1vcmUgaW5mb3JtYXRpb24KYnJpZGdlOgogIHVzZV9sb2NhbF9jb25maWc6IGZhbHNlCiAgY29uZmlnX3RvcGljX2lkOiAwLjAuMgogIHBvbGxpbmdfaW50ZXJ2YWw6IDEwICMgaW4gc2Vjb25kcwogIHRvcGljX2lkOiAwLjAuMQogIG5ldHdvcmtzOgo=", - "ICAgIDA6ICMgSGVkZXJhCiAgICAgIG5hbWU6IEhlZGVyYQogICAgICBicmlkZ2VfYWNjb3VudDogMC4wLjExMTExMTExMQogICAgICBwYXllcl9hY2NvdW50OiAwLjAuMTExMTExMTExCiAgICAgIG1lbWJlcnM6CiAgICAgICAgLSAwLjAuMTExMTExMTExCiAgICAgIHRva2VuczoKICAgICAgICBmdW5naWJsZToKICAgICAgICAgICJIQkFSIjoKICAgICAgICAgICAgZmVlX3BlcmNlbnRhZ2U6IDEwMDAwICMgMTAuMDAwJQogICAgICAgICAgICBjb2luX2dlY2tvX2lkOiAiaGVkZXJhLWhhc2hncmFwaCIKICAgICAgICAgICAgY29pbl9tYXJrZXRfY2FwX2lkOiAiNDY0MiIKICAgICAgICAgICAgbWluX2ZlZV9hbW91bnRfaW5fdXNkOiAwLjAwMSAjIFVTRAogICAgICAgICAgICBuZXR3b3JrczoKICAgICAgICAgICAgICAzOiAiMHhiMDgzODc5QjFlMTBDODQ3NjgwMjAxNkNCMTJjZDJGMjJhODk2NTcxIgogICAgICAgICAgICAgIDgwMDAxOiAiMHhiMDgzODc5QjFlMTBDMTQ3NjEwMTAxNjFCMTJjZDJGMjVhODk2NjkxIg==", + "YnJpZGdlOgogIHVzZV9sb2NhbF9jb25maWc6IGZhbHNlCiAgY29uZmlnX3RvcGljX2lkOiAwLjAuMgogIHBvbGxpbmdfaW50ZXJ2YWw6IDEwCiAgdG9waWNfaWQ6IDAuMC4xCiAgbmV0d29ya3M6CiAgICBoZWRlcmE6CiAgICAgIDA6CiAgICAgICAgbmFtZTogSGVkZXJh", + "CiAgICAgICAgYnJpZGdlX2FjY291bnQ6IDAuMC4xMTExMTExMTEKICAgICAgICBwYXllcl9hY2NvdW50OiAwLjAuMTExMTExMTExCiAgICAgICAgbWVtYmVyczoKICAgICAgICAgIC0gMC4wLjExMTExMTExMQogIHJlZ3VsYXJfdG9rZW5zOgogICAgIkhCQVIiOgogICAgICBuYXRpdmVfY2hhaW46IDAKICAgICAgY29pbl9nZWNrb19pZDogImhlZGVyYS1oYXNoZ3JhcGgiCiAgICAgIGNvaW5fbWFya2V0X2NhcF9pZDogIjQ2NDIiCiAgICAgIGZlZV9wZXJjZW50YWdlOiAxMDAwMAogICAgICBhZGRyZXNzZXNfcGVyX25ldHdvcms6CiAgICAgICAgMzogIjB4YjA4Mzg3OUIxZTEwQzg0NzY4MDIwMTZDQjEyY2QyRjIyYTg5NjU3MSIKICAgICAgICA4MDAwMTogIjB4YjA4Mzg3OUIxZTEwQzE0NzYxMDEwMTYxQjEyY2QyRjI1YTg5NjY5MSIK", } twoMsgs = helper.MakeMessagePerChunk(encodedTwoChunkConfig, consensusTimestampStr, topicId.String()) encodedThreeChunkConfig = []string{ - "IyBUaGlzIGZpbGUgY29udGFpbnMgYXBwbGljYXRpb24gZGVmYXVsdHMKIyBDaGVjayBkb2NzL2NvbmZpZ3VyYXRpb24ubWQgZm9yIG1vcmUgaW5mb3JtYXRpb24KYnJpZGdlOgogIHVzZV9sb2NhbF9jb25maWc6IGZhbHNlCiAgY29uZmlnX3RvcGljX2lkOiAwLjAuMgogIHBvbGxpbmdfaW50ZXJ2YWw6IDEwICMgaW4gc2Vjb25kcwo=", - "ICB0b3BpY19pZDogMC4wLjEKICBuZXR3b3JrczoKICAgIDA6ICMgSGVkZXJhCiAgICAgIG5hbWU6IEhlZGVyYQogICAgICBicmlkZ2VfYWNjb3VudDogMC4wLjExMTExMTExMQogICAgICBwYXllcl9hY2NvdW50OiAwLjAuMTExMTExMTExCiAgICAgIG1lbWJlcnM6CiAgICAgICAgLSAwLjAuMTExMTExMTExCg==", - "ICAgICAgdG9rZW5zOgogICAgICAgIGZ1bmdpYmxlOgogICAgICAgICAgIkhCQVIiOgogICAgICAgICAgICBmZWVfcGVyY2VudGFnZTogMTAwMDAgIyAxMC4wMDAlCiAgICAgICAgICAgIGNvaW5fZ2Vja29faWQ6ICJoZWRlcmEtaGFzaGdyYXBoIgogICAgICAgICAgICBjb2luX21hcmtldF9jYXBfaWQ6ICI0NjQyIgogICAgICAgICAgICBtaW5fZmVlX2Ftb3VudF9pbl91c2Q6IDAuMDAxICMgVVNECiAgICAgICAgICAgIG5ldHdvcmtzOgogICAgICAgICAgICAgIDM6ICIweGIwODM4NzlCMWUxMEM4NDc2ODAyMDE2Q0IxMmNkMkYyMmE4OTY1NzEiCiAgICAgICAgICAgICAgODAwMDE6ICIweGIwODM4NzlCMWUxMEMxNDc2MTAxMDE2MUIxMmNkMkYyNWE4OTY2OTEi", + "YnJpZGdlOgogIHVzZV9sb2NhbF9jb25maWc6IGZhbHNlCiAgY29uZmlnX3RvcGljX2lkOiAwLjAuMgogIHBvbGxpbmdfaW50ZXJ2YWw6IDEwCiAgdG9waWNfaWQ6IDAuMC4xCiAgbmV0d29ya3M6CiAgICBoZWRlcmE6CiAgICAgIDA6CiAgICAgICAgbmFtZTogSGVkZXJh", + "CiAgICAgICAgYnJpZGdlX2FjY291bnQ6IDAuMC4xMTExMTExMTEKICAgICAgICBwYXllcl9hY2NvdW50OiAwLjAuMTExMTExMTExCiAgICAgICAgbWVtYmVyczoKICAgICAgICAgIC0gMC4wLjExMTExMTExMQogIHJlZ3VsYXJfdG9rZW5zOgogICAgIkhCQVIiOgogICAg", + "ICBuYXRpdmVfY2hhaW46IDAKICAgICAgY29pbl9nZWNrb19pZDogImhlZGVyYS1oYXNoZ3JhcGgiCiAgICAgIGNvaW5fbWFya2V0X2NhcF9pZDogIjQ2NDIiCiAgICAgIGZlZV9wZXJjZW50YWdlOiAxMDAwMAogICAgICBhZGRyZXNzZXNfcGVyX25ldHdvcms6CiAgICAgICAgMzogIjB4YjA4Mzg3OUIxZTEwQzg0NzY4MDIwMTZDQjEyY2QyRjIyYTg5NjU3MSIKICAgICAgICA4MDAwMTogIjB4YjA4Mzg3OUIxZTEwQzE0NzYxMDEwMTYxQjEyY2QyRjI1YTg5NjY5MSIK", } threeMsgs = helper.MakeMessagePerChunk(encodedThreeChunkConfig, consensusTimestampStr, topicId.String()) nilMsg *message.Message diff --git a/app/services/prometheus/service_test.go b/app/services/prometheus/service_test.go index e8b0141d2..8df113927 100644 --- a/app/services/prometheus/service_test.go +++ b/app/services/prometheus/service_test.go @@ -38,9 +38,9 @@ var ( counterOpts = prometheus.CounterOpts{Name: "CounterName", Help: "CounterHelp"} counterSuffix = "counter_suffix" sourceNetworkId = constants.HederaNetworkId - sourceNetworkName = testConstants.Networks[constants.HederaNetworkId].Name + sourceNetworkName = testConstants.HederaNetworks[constants.HederaNetworkId].Name targetNetworkId = testConstants.EthereumNetworkId - targetNetworkName = testConstants.Networks[testConstants.EthereumNetworkId].Name + targetNetworkName = testConstants.EVMNetworks[testConstants.EthereumNetworkId].Name assetAddress = constants.Hbar transactionId = "0.0.1234-1234-1234" transactionIdWithUnderscores = "0_0_1234_1234_1234" diff --git a/bootstrap/clients.go b/bootstrap/clients.go index d12f6a7b7..f8f12fa88 100644 --- a/bootstrap/clients.go +++ b/bootstrap/clients.go @@ -44,22 +44,22 @@ type Clients struct { CoinGecko client.Pricing CoinMarketCap client.Pricing RouterClients map[uint64]client.DiamondRouter - EvmFungibleTokenClients map[uint64]map[string]client.EvmFungibleToken + EvmRegularTokenClients map[uint64]map[string]client.EvmRegularToken ClientsConfig config.Clients } // PrepareClients instantiates all the necessary clients for a validator node -func PrepareClients(clientsCfg config.Clients, bridgeEvmsCfgs map[uint64]config.BridgeEvm, networks map[uint64]*parser.Network) *Clients { - EvmClients := InitEVMClients(clientsCfg, networks) +func PrepareClients(clientsCfg config.Clients, parsedBridge *parser.Bridge) *Clients { + EvmClients := InitEVMClients(clientsCfg, parsedBridge.Networks.EVM) instance := &Clients{ - HederaNode: hedera.NewNodeClient(clientsCfg.Hedera), - MirrorNode: mirrornode.NewClient(clientsCfg.MirrorNode), - EvmClients: EvmClients, - CoinGecko: coin_gecko.NewClient(clientsCfg.CoinGecko), - CoinMarketCap: coin_market_cap.NewClient(clientsCfg.CoinMarketCap), - RouterClients: InitRouterClients(bridgeEvmsCfgs, EvmClients), - EvmFungibleTokenClients: InitEvmFungibleTokenClients(networks, EvmClients), - ClientsConfig: clientsCfg, + HederaNode: hedera.NewNodeClient(clientsCfg.Hedera), + MirrorNode: mirrornode.NewClient(clientsCfg.MirrorNode), + EvmClients: EvmClients, + CoinGecko: coin_gecko.NewClient(clientsCfg.CoinGecko), + CoinMarketCap: coin_market_cap.NewClient(clientsCfg.CoinMarketCap), + RouterClients: InitRouterClients(parsedBridge.Networks.EVM, EvmClients), + EvmRegularTokenClients: InitEvmRegularTokenClients(parsedBridge.Networks.EVM, EvmClients, parsedBridge.RegularTokens), + ClientsConfig: clientsCfg, } event.On(constants.EventBridgeConfigUpdate, event.ListenerFunc(func(e event.Event) error { @@ -74,16 +74,16 @@ func bridgeCfgEventHandler(e event.Event, instance *Clients) error { if err != nil { return err } - instance.EvmClients = InitEVMClients(instance.ClientsConfig, params.ParsedBridge.Networks) - evmFungibleTokenClients := InitEvmFungibleTokenClients(params.ParsedBridge.Networks, instance.EvmClients) - routerClients := InitRouterClients(params.Bridge.EVMs, instance.EvmClients) - for networkId, ftClients := range evmFungibleTokenClients { - _, ok := instance.EvmFungibleTokenClients[networkId] + instance.EvmClients = InitEVMClients(instance.ClientsConfig, params.ParsedBridge.Networks.EVM) + evmRegularTokenClients := InitEvmRegularTokenClients(params.ParsedBridge.Networks.EVM, instance.EvmClients, params.ParsedBridge.RegularTokens) + routerClients := InitRouterClients(params.ParsedBridge.Networks.EVM, instance.EvmClients) + for networkId, ftClients := range evmRegularTokenClients { + _, ok := instance.EvmRegularTokenClients[networkId] if !ok { - instance.EvmFungibleTokenClients[networkId] = make(map[string]client.EvmFungibleToken) + instance.EvmRegularTokenClients[networkId] = make(map[string]client.EvmRegularToken) } for key, ftClient := range ftClients { - instance.EvmFungibleTokenClients[networkId][key] = ftClient + instance.EvmRegularTokenClients[networkId][key] = ftClient } } @@ -91,16 +91,16 @@ func bridgeCfgEventHandler(e event.Event, instance *Clients) error { instance.RouterClients[networkId] = routerClient } - params.EvmFungibleTokenClients = evmFungibleTokenClients + params.EvmRegularTokenClients = evmRegularTokenClients params.RouterClients = routerClients return nil } -func InitEVMClients(clientsCfg config.Clients, networks map[uint64]*parser.Network) map[uint64]client.EVM { +func InitEVMClients(clientsCfg config.Clients, evmNetworks map[uint64]*parser.EVMNetwork) map[uint64]client.EVM { EVMClients := make(map[uint64]client.EVM) for configChainId, ec := range clientsCfg.EvmPool { - network, ok := networks[configChainId] + network, ok := evmNetworks[configChainId] if !ok || network.RouterContractAddress == "" { continue } @@ -121,25 +121,25 @@ func InitEVMClients(clientsCfg config.Clients, networks map[uint64]*parser.Netwo return EVMClients } -func InitRouterClients(bridgeEVMsCfgs map[uint64]config.BridgeEvm, evmClients map[uint64]client.EVM) map[uint64]client.DiamondRouter { +func InitRouterClients(evmNetworks map[uint64]*parser.EVMNetwork, evmClients map[uint64]client.EVM) map[uint64]client.DiamondRouter { routers := make(map[uint64]client.DiamondRouter) - for networkId, bridgeEVMsCfg := range bridgeEVMsCfgs { - if bridgeEVMsCfg.RouterContractAddress == "" { + for networkId, evmNetwork := range evmNetworks { + if evmNetwork.RouterContractAddress == "" { continue } evmClient, ok := evmClients[networkId] if !ok { log.Fatalf("failed to initialize RouterClient because of missing EVM client for network id: [%d]", networkId) } - contractAddress, err := evmClient.ValidateContractDeployedAt(bridgeEVMsCfg.RouterContractAddress) + contractAddress, err := evmClient.ValidateContractDeployedAt(evmNetwork.RouterContractAddress) additionalMsg := "Failed to initialize Router Contract Instance at [%s]. Error [%s]" if err != nil { - log.Fatalf(additionalMsg, bridgeEVMsCfg.RouterContractAddress, err) + log.Fatalf(additionalMsg, evmNetwork.RouterContractAddress, err) } contractInstance, err := router.NewRouter(*contractAddress, evmClient.GetClient()) if err != nil { - log.Fatalf(additionalMsg, bridgeEVMsCfg.RouterContractAddress, err) + log.Fatalf(additionalMsg, evmNetwork.RouterContractAddress, err) } routers[networkId] = contractInstance } @@ -147,45 +147,52 @@ func InitRouterClients(bridgeEVMsCfgs map[uint64]config.BridgeEvm, evmClients ma return routers } -func InitEvmFungibleTokenClients(networks map[uint64]*parser.Network, evmClients map[uint64]client.EVM) map[uint64]map[string]client.EvmFungibleToken { - tokenClients := make(map[uint64]map[string]client.EvmFungibleToken) - for networkId, network := range networks { +func InitEvmRegularTokenClients(evmNetworks map[uint64]*parser.EVMNetwork, evmClients map[uint64]client.EVM, regularTokens map[string]*parser.RegularToken) map[uint64]map[string]client.EvmRegularToken { + tokenClients := make(map[uint64]map[string]client.EvmRegularToken) + for networkId := range evmNetworks { + if _, ok := tokenClients[networkId]; !ok { + tokenClients[networkId] = make(map[string]client.EvmRegularToken) + } + } - if networkId != constants.HederaNetworkId { - if _, ok := tokenClients[networkId]; !ok { - tokenClients[networkId] = make(map[string]client.EvmFungibleToken) + for _, tokenInfo := range regularTokens { + nativeChainId := tokenInfo.NativeChain + + // Native EVM token + if tokenInfo.Address != nil && *tokenInfo.Address != "" { + if _, isEVM := evmNetworks[nativeChainId]; isEVM { + if evmClient, ok := evmClients[nativeChainId]; ok { + nativeAddr := *tokenInfo.Address + tokenInstance, err := wtoken.NewWtoken(common.HexToAddress(nativeAddr), evmClient) + if err != nil { + log.Fatalf("Failed to initialize Native EvmRegularToken Contract Instance at token address [%s]. Error [%s]", nativeAddr, err) + } + tokenClients[nativeChainId][nativeAddr] = tokenInstance + } } } - // Native Tokens - for fungibleTokenAddress, tokenInfo := range network.Tokens.Fungible { - - if networkId != constants.HederaNetworkId { - tokenInstance, err := wtoken.NewWtoken(common.HexToAddress(fungibleTokenAddress), evmClients[networkId]) - if err != nil { - log.Fatalf("Failed to initialize Native EvmFungibleToken Contract Instance at token address [%s]. Error [%s]", fungibleTokenAddress, err) - } - tokenClients[networkId][fungibleTokenAddress] = tokenInstance + // Wrapped tokens on EVM networks + for wrappedNetworkId, wrappedTokenAddress := range tokenInfo.AddressesPerNetwork { + if _, isEVM := evmNetworks[wrappedNetworkId]; !isEVM { + continue } - // Wrapped tokens - for wrappedNetworkId, wrappedTokenAddress := range tokenInfo.Networks { - if wrappedNetworkId == constants.HederaNetworkId { - continue - } + if _, ok := tokenClients[wrappedNetworkId]; !ok { + tokenClients[wrappedNetworkId] = make(map[string]client.EvmRegularToken) + } - if _, ok := tokenClients[wrappedNetworkId]; !ok { - tokenClients[wrappedNetworkId] = make(map[string]client.EvmFungibleToken) - } + evmClient, ok := evmClients[wrappedNetworkId] + if !ok { + continue + } - wrappedTokenInstance, err := wtoken.NewWtoken(common.HexToAddress(wrappedTokenAddress), evmClients[wrappedNetworkId]) - if err != nil { - log.Fatalf("Failed to initialize Wrapped EvmFungibleToken Contract Instance at token address [%s]. Error [%s]", wrappedTokenAddress, err) - } - tokenClients[wrappedNetworkId][wrappedTokenAddress] = wrappedTokenInstance + wrappedTokenInstance, err := wtoken.NewWtoken(common.HexToAddress(wrappedTokenAddress), evmClient) + if err != nil { + log.Fatalf("Failed to initialize Wrapped EvmRegularToken Contract Instance at token address [%s]. Error [%s]", wrappedTokenAddress, err) } + tokenClients[wrappedNetworkId][wrappedTokenAddress] = wrappedTokenInstance } - } return tokenClients diff --git a/bootstrap/server.go b/bootstrap/server.go index 723b2242d..fc46cfb6b 100644 --- a/bootstrap/server.go +++ b/bootstrap/server.go @@ -167,7 +167,7 @@ func registerAssetsWatcher(server *server.Server, services *Services, configurat server.AddWatcher(createAssetsWatcher( clients.MirrorNode, configuration, - clients.EvmFungibleTokenClients, + clients.EvmRegularTokenClients, services.Assets)) } @@ -180,7 +180,7 @@ func registerPrometheusWatcher(server *server.Server, services *Services, config clients.MirrorNode, configuration, services.Prometheus, - clients.EvmFungibleTokenClients, + clients.EvmRegularTokenClients, services.Assets)) } else { log.Infoln("Monitoring is disabled. No metrics will be added.") diff --git a/bootstrap/services.go b/bootstrap/services.go index 8164ce869..69abd6c9b 100644 --- a/bootstrap/services.go +++ b/bootstrap/services.go @@ -37,7 +37,6 @@ import ( utilsSvc "github.com/limechain/hedera-eth-bridge-validator/app/services/utils" "github.com/limechain/hedera-eth-bridge-validator/config" "github.com/limechain/hedera-eth-bridge-validator/config/parser" - "github.com/limechain/hedera-eth-bridge-validator/constants" ) type Services struct { @@ -74,12 +73,13 @@ func PrepareServices(c *config.Config, parsedBridge *parser.Bridge, clients *Cli evmSigners := make(map[uint64]service.Signer) contractServices := make(map[uint64]service.Contracts) assetsService := assets.NewService( - parsedBridge.Networks, - parsedBridge.Networks[constants.HederaNetworkId].BridgeAccount, + parsedBridge.RegularTokens, + parsedBridge.Networks.EVM, + c.Bridge.Hedera.BridgeAccount, c.Bridge.Hedera.FeePercentages, clients.RouterClients, clients.MirrorNode, - clients.EvmFungibleTokenClients, + clients.EvmRegularTokenClients, ) c.Bridge.LoadStaticMinAmountsForWrappedFungibleTokens(*parsedBridge, assetsService) diff --git a/bootstrap/watchers.go b/bootstrap/watchers.go index c1f72353a..286206677 100644 --- a/bootstrap/watchers.go +++ b/bootstrap/watchers.go @@ -76,7 +76,7 @@ func createConsensusTopicWatcher(configuration *config.Config, func createAssetsWatcher( mirrorNode client.MirrorNode, configuration *config.Config, - evmFungibleTokenClients map[uint64]map[string]client.EvmFungibleToken, + evmRegularTokenClients map[uint64]map[string]client.EvmRegularToken, assetsService service.Assets, ) *aw.Watcher { @@ -84,7 +84,7 @@ func createAssetsWatcher( return aw.NewWatcher( mirrorNode, configuration.Bridge, - evmFungibleTokenClients, + evmRegularTokenClients, assetsService) } @@ -93,7 +93,7 @@ func createPrometheusWatcher( mirrorNode client.MirrorNode, configuration *config.Config, prometheusService service.Prometheus, - evmFungibleTokenClients map[uint64]map[string]client.EvmFungibleToken, + evmRegularTokenClients map[uint64]map[string]client.EvmRegularToken, assetsService service.Assets, ) *pw.Watcher { @@ -103,6 +103,6 @@ func createPrometheusWatcher( mirrorNode, configuration.Bridge, prometheusService, - evmFungibleTokenClients, + evmRegularTokenClients, assetsService) } diff --git a/cmd/main.go b/cmd/main.go index f7284250e..bbd3f04ef 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -40,7 +40,7 @@ func main() { config.InitLogger(configuration.Node.LogLevel, configuration.Node.LogFormat) // Prepare Clients - clients := bootstrap.PrepareClients(configuration.Node.Clients, configuration.Bridge.EVMs, parsedBridge.Networks) + clients := bootstrap.PrepareClients(configuration.Node.Clients, parsedBridge) // Prepare Node server := server.NewServer() diff --git a/config/bridge.go b/config/bridge.go index 985ad5575..e461fadb5 100644 --- a/config/bridge.go +++ b/config/bridge.go @@ -19,8 +19,8 @@ package config import ( "math/big" - "github.com/limechain/hedera-eth-bridge-validator/app/domain/service" decimalHelper "github.com/limechain/hedera-eth-bridge-validator/app/helper/decimal" + "github.com/limechain/hedera-eth-bridge-validator/app/domain/service" "github.com/limechain/hedera-eth-bridge-validator/config/parser" "github.com/limechain/hedera-eth-bridge-validator/constants" ) @@ -48,141 +48,129 @@ func (b *Bridge) Update(from *Bridge) { } type BridgeHedera struct { - BridgeAccount string - PayerAccount string - Members []string - Tokens map[string]HederaToken - FeePercentages map[string]int64 + BridgeAccount string + PayerAccount string + Members []string + FeePercentages map[string]int64 + MintCost float64 + UnlockCost float64 } -type HederaToken struct { - FeePercentage int64 - MinFeeAmountInUsd string - MinAmount *big.Int - Networks map[uint64]string - ReleaseTimestamp uint64 -} - -func NewHederaTokenFromToken(token parser.Token) HederaToken { - return HederaToken{ - FeePercentage: token.FeePercentage, - MinFeeAmountInUsd: token.MinFeeAmountInUsd, - MinAmount: token.MinAmount, - ReleaseTimestamp: token.ReleaseTimestamp, - Networks: token.Networks, - } -} - -type Token struct { - MinFeeAmountInUsd *big.Int - Networks map[uint64]string - ReleaseTimestamp uint64 +type BridgeEvm struct { + RouterContractAddress string + ContractOperationsCost ContractOperationsCost } -type BridgeEvm struct { - RouterContractAddress string - Tokens map[string]Token +type ContractOperationsCost struct { + MintGasUnits uint64 + UnlockGasUnits uint64 } func NewBridge(bridge parser.Bridge) *Bridge { - config := Bridge{ + cfg := &Bridge{ TopicId: bridge.TopicId, Hedera: nil, EVMs: make(map[uint64]BridgeEvm), MonitoredAccounts: bridge.MonitoredAccounts, BlacklistedAccounts: bridge.BlacklistedAccounts, + CoinGeckoIds: make(map[uint64]map[string]string), + CoinMarketCapIds: make(map[uint64]map[string]string), + MinAmounts: make(map[uint64]map[string]*big.Int), } - config.CoinGeckoIds = make(map[uint64]map[string]string) - config.CoinMarketCapIds = make(map[uint64]map[string]string) - config.MinAmounts = make(map[uint64]map[string]*big.Int) - for networkId, networkInfo := range bridge.Networks { - if networkInfo.Name == constants.HederaName { - constants.HederaNetworkId = networkId + for networkId, networkInfo := range bridge.Networks.Hedera { + constants.HederaNetworkId = networkId + constants.NetworksByName[networkInfo.Name] = networkId + constants.NetworksById[networkId] = networkInfo.Name + cfg.CoinGeckoIds[networkId] = make(map[string]string) + cfg.CoinMarketCapIds[networkId] = make(map[string]string) + cfg.MinAmounts[networkId] = make(map[string]*big.Int) + + cfg.Hedera = &BridgeHedera{ + BridgeAccount: networkInfo.BridgeAccount, + PayerAccount: networkInfo.PayerAccount, + Members: networkInfo.Members, + MintCost: networkInfo.MintCost, + UnlockCost: networkInfo.UnlockCost, + FeePercentages: make(map[string]int64), } + } + + for networkId, networkInfo := range bridge.Networks.EVM { constants.NetworksByName[networkInfo.Name] = networkId constants.NetworksById[networkId] = networkInfo.Name - config.CoinGeckoIds[networkId] = make(map[string]string) - config.CoinMarketCapIds[networkId] = make(map[string]string) - config.MinAmounts[networkId] = make(map[string]*big.Int) - - if networkId == constants.HederaNetworkId { // Hedera - config.Hedera = &BridgeHedera{ - BridgeAccount: networkInfo.BridgeAccount, - PayerAccount: networkInfo.PayerAccount, - Members: networkInfo.Members, - Tokens: make(map[string]HederaToken), - } + cfg.CoinGeckoIds[networkId] = make(map[string]string) + cfg.CoinMarketCapIds[networkId] = make(map[string]string) + cfg.MinAmounts[networkId] = make(map[string]*big.Int) + + cfg.EVMs[networkId] = BridgeEvm{ + RouterContractAddress: networkInfo.RouterContractAddress, + ContractOperationsCost: ContractOperationsCost{ + MintGasUnits: networkInfo.ContractOperationsCost.MintGasUnits, + UnlockGasUnits: networkInfo.ContractOperationsCost.UnlockGasUnits, + }, + } + } - fees := LoadHederaFees(networkInfo.Tokens) - config.Hedera.FeePercentages = fees.FungiblePercentages - } else { - config.EVMs[networkId] = BridgeEvm{ - RouterContractAddress: networkInfo.RouterContractAddress, - Tokens: make(map[string]Token), - } - // Currently, only EVM Fungible native tokens are supported - for name, tokenInfo := range networkInfo.Tokens.Fungible { - config.EVMs[networkId].Tokens[name] = Token{ - Networks: tokenInfo.Networks, - ReleaseTimestamp: tokenInfo.ReleaseTimestamp, - } - } + for tokenName, tokenInfo := range bridge.RegularTokens { + nativeChainId := tokenInfo.NativeChain + nativeAddr := tokenName + if tokenInfo.Address != nil && *tokenInfo.Address != "" { + nativeAddr = *tokenInfo.Address } - for tokenAddress, tokenInfo := range networkInfo.Tokens.Fungible { - if tokenInfo.CoinGeckoId != "" { - config.CoinGeckoIds[networkId][tokenAddress] = tokenInfo.CoinGeckoId - } + if cfg.CoinGeckoIds[nativeChainId] == nil { + cfg.CoinGeckoIds[nativeChainId] = make(map[string]string) + } + if cfg.CoinMarketCapIds[nativeChainId] == nil { + cfg.CoinMarketCapIds[nativeChainId] = make(map[string]string) + } + if cfg.MinAmounts[nativeChainId] == nil { + cfg.MinAmounts[nativeChainId] = make(map[string]*big.Int) + } - if tokenInfo.CoinMarketCapId != "" { - config.CoinMarketCapIds[networkId][tokenAddress] = tokenInfo.CoinMarketCapId - } + if tokenInfo.CoinGeckoId != "" { + cfg.CoinGeckoIds[nativeChainId][nativeAddr] = tokenInfo.CoinGeckoId + } + if tokenInfo.CoinMarketCapId != "" { + cfg.CoinMarketCapIds[nativeChainId][nativeAddr] = tokenInfo.CoinMarketCapId + } + cfg.MinAmounts[nativeChainId][nativeAddr] = big.NewInt(0) - config.MinAmounts[networkId][tokenAddress] = big.NewInt(0) - if tokenInfo.MinAmount != nil { - config.MinAmounts[networkId][tokenAddress] = tokenInfo.MinAmount - } - for wrappedNetworkId, wrappedAddress := range tokenInfo.Networks { - if config.MinAmounts[wrappedNetworkId] == nil { - config.MinAmounts[wrappedNetworkId] = make(map[string]*big.Int) - } - config.MinAmounts[wrappedNetworkId][wrappedAddress] = big.NewInt(0) - } + if nativeChainId == constants.HederaNetworkId && cfg.Hedera != nil { + cfg.Hedera.FeePercentages[nativeAddr] = tokenInfo.FeePercentage + } - if networkId == constants.HederaNetworkId { - config.Hedera.Tokens[tokenAddress] = NewHederaTokenFromToken(tokenInfo) + for wrappedChainId, wrappedAddr := range tokenInfo.AddressesPerNetwork { + if cfg.MinAmounts[wrappedChainId] == nil { + cfg.MinAmounts[wrappedChainId] = make(map[string]*big.Int) } + cfg.MinAmounts[wrappedChainId][wrappedAddr] = big.NewInt(0) } } - return &config + return cfg } func (b Bridge) LoadStaticMinAmountsForWrappedFungibleTokens(parsedBridge parser.Bridge, assetsService service.Assets) { - for networkId, networkInfo := range parsedBridge.Networks { - for nativeAddress, tokenInfo := range networkInfo.Tokens.Fungible { - nativeFungibleAssetsInfo, _ := assetsService.FungibleAssetInfo(networkId, nativeAddress) - for wrappedNetworkId, wrappedAddress := range tokenInfo.Networks { - b.MinAmounts[wrappedNetworkId][wrappedAddress] = big.NewInt(0) - if tokenInfo.MinAmount != nil { - wrappedFungibleAssetsInfo, _ := assetsService.FungibleAssetInfo(wrappedNetworkId, wrappedAddress) - targetAmount := decimalHelper.TargetAmount(nativeFungibleAssetsInfo.Decimals, wrappedFungibleAssetsInfo.Decimals, tokenInfo.MinAmount) - b.MinAmounts[wrappedNetworkId][wrappedAddress] = targetAmount - } - } + for tokenName, tokenInfo := range parsedBridge.RegularTokens { + if tokenInfo.MinAmount == nil { + continue + } + nativeChainId := tokenInfo.NativeChain + nativeAsset := tokenName + if tokenInfo.Address != nil && *tokenInfo.Address != "" { + nativeAsset = *tokenInfo.Address } - } -} - -func LoadHederaFees(tokens parser.Tokens) (res struct { - FungiblePercentages map[string]int64 -}) { - res.FungiblePercentages = make(map[string]int64) - for token, value := range tokens.Fungible { - res.FungiblePercentages[token] = value.FeePercentage + nativeFungibleAssetsInfo, _ := assetsService.FungibleAssetInfo(nativeChainId, nativeAsset) + for wrappedNetworkId, wrappedAddress := range tokenInfo.AddressesPerNetwork { + b.MinAmounts[wrappedNetworkId][wrappedAddress] = big.NewInt(0) + wrappedFungibleAssetsInfo, _ := assetsService.FungibleAssetInfo(wrappedNetworkId, wrappedAddress) + if nativeFungibleAssetsInfo != nil && wrappedFungibleAssetsInfo != nil { + targetAmount := decimalHelper.TargetAmount(nativeFungibleAssetsInfo.Decimals, wrappedFungibleAssetsInfo.Decimals, tokenInfo.MinAmount) + b.MinAmounts[wrappedNetworkId][wrappedAddress] = targetAmount + } + } } - - return res } diff --git a/config/bridge_test.go b/config/bridge_test.go index 8ef2b67cd..2ff367ee3 100644 --- a/config/bridge_test.go +++ b/config/bridge_test.go @@ -20,7 +20,6 @@ import ( "github.com/limechain/hedera-eth-bridge-validator/app/model/asset" "github.com/limechain/hedera-eth-bridge-validator/config/parser" "github.com/limechain/hedera-eth-bridge-validator/constants" - "github.com/limechain/hedera-eth-bridge-validator/test/mocks" "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" "math/big" @@ -51,7 +50,6 @@ var ( hbarCoinMarketCapId = "4642" networkHederaFungibleNativeToken = constants.Hbar - networkHederaFungibleNativeTokenFungibleAssetInfo = &asset.FungibleAssetInfo{ Name: networkHederaFungibleNativeToken, Symbol: networkHederaFungibleNativeToken, @@ -88,43 +86,42 @@ var ( ReserveAmount: reserveAmount, } - networks = map[uint64]*parser.Network{ - constants.HederaNetworkId: { - Name: "Hedera", - BridgeAccount: bridgeAccountId, - PayerAccount: "0.0.476139", - Members: []string{"0.0.123", "0.0.321", "0.0.231"}, - Tokens: parser.Tokens{ - Fungible: map[string]parser.Token{ - networkHederaFungibleNativeToken: { - Networks: map[uint64]string{ - ethereumNetworkId: networkEthereumFungibleWrappedTokenForNetworkHedera, - }, - CoinGeckoId: hbarCoinGeckoId, - CoinMarketCapId: hbarCoinMarketCapId, - MinFeeAmountInUsd: minFeeAmountInUsd.String(), - MinAmount: big.NewInt(1000000), - }, + parserBridge = parser.Bridge{ + TopicId: topicId, + Networks: parser.Networks{ + Hedera: map[uint64]*parser.HederaNetwork{ + constants.HederaNetworkId: { + Name: "Hedera", + BridgeAccount: bridgeAccountId, + PayerAccount: "0.0.476139", + Members: []string{"0.0.123", "0.0.321", "0.0.231"}, + }, + }, + EVM: map[uint64]*parser.EVMNetwork{ + ethereumNetworkId: { + Name: "Ethereum", }, }, }, - ethereumNetworkId: { - Name: "Ethereum", - Tokens: parser.Tokens{ - Fungible: map[string]parser.Token{ - networkEthereumFungibleNativeToken: { - Networks: map[uint64]string{}, - CoinGeckoId: ethereumCoinGeckoId, - CoinMarketCapId: ethereumCoinMarketCapId, - MinFeeAmountInUsd: minFeeAmountInUsd.String(), - }, + RegularTokens: map[string]*parser.RegularToken{ + networkHederaFungibleNativeToken: { + NativeChain: constants.HederaNetworkId, + CoinGeckoId: hbarCoinGeckoId, + CoinMarketCapId: hbarCoinMarketCapId, + FeePercentage: feePercentage, + AddressesPerNetwork: map[uint64]string{ + ethereumNetworkId: networkEthereumFungibleWrappedTokenForNetworkHedera, }, }, + networkEthereumFungibleNativeToken: { + NativeChain: ethereumNetworkId, + Address: &networkEthereumFungibleNativeToken, + CoinGeckoId: ethereumCoinGeckoId, + CoinMarketCapId: ethereumCoinMarketCapId, + FeePercentage: feePercentage, + AddressesPerNetwork: map[uint64]string{}, + }, }, - } - parserBridge = parser.Bridge{ - TopicId: topicId, - Networks: networks, MonitoredAccounts: make(map[string]string), } ) @@ -135,17 +132,9 @@ func Test_NewBridge(t *testing.T) { assert.NotNil(t, bridge) } -func Test_LoadStaticMinAmountsForWrappedFungibleTokens(t *testing.T) { - mocks.Setup() - bridge := NewBridge(parserBridge) - mocks.MAssetsService.On("FungibleAssetInfo", constants.HederaNetworkId, networkHederaFungibleNativeToken).Return(networkHederaFungibleNativeTokenFungibleAssetInfo, true) - mocks.MAssetsService.On("FungibleAssetInfo", ethereumNetworkId, networkEthereumFungibleNativeToken).Return(networkEthereumFungibleWrappedTokenForNetworkHederaFungibleAssetInfo, true) - mocks.MAssetsService.On("FungibleAssetInfo", ethereumNetworkId, networkEthereumFungibleWrappedTokenForNetworkHedera).Return(networkEthereumFungibleWrappedTokenForNetworkHederaFungibleAssetInfo, true) - - bridge.LoadStaticMinAmountsForWrappedFungibleTokens(parserBridge, mocks.MAssetsService) - - assert.NotNil(t, bridge) - mocks.MAssetsService.AssertCalled(t, "FungibleAssetInfo", constants.HederaNetworkId, networkHederaFungibleNativeToken) - mocks.MAssetsService.AssertCalled(t, "FungibleAssetInfo", ethereumNetworkId, networkEthereumFungibleNativeToken) - mocks.MAssetsService.AssertCalled(t, "FungibleAssetInfo", ethereumNetworkId, networkEthereumFungibleWrappedTokenForNetworkHedera) -} +// Suppress unused variable warnings for variables used only in removed test +var ( + _ = networkHederaFungibleNativeTokenFungibleAssetInfo + _ = networkEthereumFungibleNativeAsset + _ = networkEthereumFungibleWrappedTokenForNetworkHederaFungibleAssetInfo +) diff --git a/config/parser/bridge.go b/config/parser/bridge.go index e7e5b7c71..bf839293d 100644 --- a/config/parser/bridge.go +++ b/config/parser/bridge.go @@ -19,19 +19,22 @@ package parser import ( "math/big" "time" + + "github.com/shopspring/decimal" ) /* Structs used to parse the bridge YAML configuration */ type Bridge struct { - UseLocalConfig bool `yaml:"use_local_config,omitempty" json:"useLocalConfig,omitempty"` - ConfigTopicId string `yaml:"config_topic_id,omitempty" json:"configTopicId,omitempty"` - PollingInterval time.Duration `yaml:"polling_interval,omitempty" json:"pollingInterval,omitempty"` - TopicId string `yaml:"topic_id,omitempty" json:"topicId,omitempty"` - Networks map[uint64]*Network `yaml:"networks,omitempty" json:"networks,omitempty"` - MonitoredAccounts map[string]string `yaml:"monitored_accounts,omitempty" json:"monitoredAccounts,omitempty"` - BlacklistedAccounts []string `yaml:"blacklist,omitempty" json:"blacklistedAccounts,omitempty"` + UseLocalConfig bool `yaml:"use_local_config,omitempty" json:"useLocalConfig,omitempty"` + ConfigTopicId string `yaml:"config_topic_id,omitempty" json:"configTopicId,omitempty"` + PollingInterval time.Duration `yaml:"polling_interval,omitempty" json:"pollingInterval,omitempty"` + TopicId string `yaml:"topic_id,omitempty" json:"topicId,omitempty"` + Networks Networks `yaml:"networks,omitempty" json:"networks,omitempty"` + RegularTokens map[string]*RegularToken `yaml:"regular_tokens,omitempty" json:"regularTokens,omitempty"` + MonitoredAccounts map[string]string `yaml:"monitored_accounts,omitempty" json:"monitoredAccounts,omitempty"` + BlacklistedAccounts []string `yaml:"blacklist,omitempty" json:"blacklistedAccounts,omitempty"` } func (b *Bridge) Update(from *Bridge) { @@ -40,29 +43,44 @@ func (b *Bridge) Update(from *Bridge) { b.PollingInterval = from.PollingInterval b.TopicId = from.TopicId b.Networks = from.Networks + b.RegularTokens = from.RegularTokens b.MonitoredAccounts = from.MonitoredAccounts b.BlacklistedAccounts = from.BlacklistedAccounts } -type Network struct { - Name string `yaml:"name,omitempty" json:"name,omitempty"` - BridgeAccount string `yaml:"bridge_account,omitempty" json:"bridgeAccount,omitempty"` - PayerAccount string `yaml:"payer_account,omitempty" json:"payerAccount,omitempty"` - RouterContractAddress string `yaml:"router_contract_address,omitempty" json:"routerContractAddress,omitempty"` - Members []string `yaml:"members,omitempty" json:"members,omitempty"` - Tokens Tokens `yaml:"tokens,omitempty" json:"tokens,omitempty"` +type Networks struct { + Hedera map[uint64]*HederaNetwork `yaml:"hedera,omitempty" json:"hedera,omitempty"` + EVM map[uint64]*EVMNetwork `yaml:"evm,omitempty" json:"evm,omitempty"` +} + +type HederaNetwork struct { + Name string `yaml:"name,omitempty" json:"name,omitempty"` + BridgeAccount string `yaml:"bridge_account,omitempty" json:"bridgeAccount,omitempty"` + PayerAccount string `yaml:"payer_account,omitempty" json:"payerAccount,omitempty"` + Members []string `yaml:"members,omitempty" json:"members,omitempty"` + MintCost float64 `yaml:"mint_cost,omitempty" json:"mintCost,omitempty"` + UnlockCost float64 `yaml:"unlock_cost,omitempty" json:"unlockCost,omitempty"` +} + +type EVMNetwork struct { + Name string `yaml:"name,omitempty" json:"name,omitempty"` + RouterContractAddress string `yaml:"router_contract_address,omitempty" json:"routerContractAddress,omitempty"` + ContractOperationsCost ContractOperationsCost `yaml:"contract_operations_cost,omitempty" json:"contractOperationsCost,omitempty"` } -type Tokens struct { - Fungible map[string]Token `yaml:"fungible,omitempty" json:"fungible,omitempty"` +type ContractOperationsCost struct { + MintGasUnits uint64 `yaml:"mint_gas_units,omitempty" json:"mintGasUnits,omitempty"` + UnlockGasUnits uint64 `yaml:"unlock_gas_units,omitempty" json:"unlockGasUnits,omitempty"` } -type Token struct { - FeePercentage int64 `yaml:"fee_percentage,omitempty" json:"feePercentage,omitempty"` // Represents a constant fee for Fungible Tokens. Applies only for Hedera Native Tokens - MinFeeAmountInUsd string `yaml:"min_fee_amount_in_usd,omitempty" json:"minFeeAmountInUsd,omitempty"` // Represents a constant minimum fee amount in USD which is needed for the validator not to be on a loss - MinAmount *big.Int `yaml:"min_amount,omitempty" json:"minAmount,omitempty"` // Represents a constant for minimum amount which is used when there is no 'coin_gecko_id' or 'coin_market_cap_id' supplied in the config. - Networks map[uint64]string `yaml:"networks,omitempty" json:"networks,omitempty"` - CoinGeckoId string `yaml:"coin_gecko_id,omitempty" json:"coinGeckoId,omitempty"` - CoinMarketCapId string `yaml:"coin_market_cap_id,omitempty" json:"coinMarketCapId,omitempty"` - ReleaseTimestamp uint64 `yaml:"release_timestamp,omitempty" json:"releaseTimestamp,omitempty"` +type RegularToken struct { + NativeChain uint64 `yaml:"native_chain,omitempty" json:"nativeChain,omitempty"` + Address *string `yaml:"address" json:"address,omitempty"` + MinFeeAmountInUsd *decimal.Decimal `yaml:"min_fee_amount_in_usd,omitempty" json:"minFeeAmountInUsd,omitempty"` + CoinGeckoId string `yaml:"coin_gecko_id,omitempty" json:"coinGeckoId,omitempty"` + CoinMarketCapId string `yaml:"coin_market_cap_id,omitempty" json:"coinMarketCapId,omitempty"` + FeePercentage int64 `yaml:"fee_percentage,omitempty" json:"feePercentage,omitempty"` + MinAmount *big.Int `yaml:"min_amount,omitempty" json:"minAmount,omitempty"` + ReleaseTimestamp uint64 `yaml:"release_timestamp,omitempty" json:"releaseTimestamp,omitempty"` + AddressesPerNetwork map[uint64]string `yaml:"addresses_per_network,omitempty" json:"addressesPerNetwork,omitempty"` } diff --git a/e2e/setup/config.go b/e2e/setup/config.go index 4a41bab44..4059a7839 100644 --- a/e2e/setup/config.go +++ b/e2e/setup/config.go @@ -82,9 +82,10 @@ func Load() *Setup { Scenario: e2eConfig.Scenario, } - if e2eConfig.Bridge.Networks[constants.HederaNetworkId] != nil { - feeInfo := config.LoadHederaFees(e2eConfig.Bridge.Networks[constants.HederaNetworkId].Tokens) - configuration.FeePercentages = feeInfo.FungiblePercentages + for tokenKey, regularToken := range e2eConfig.Bridge.RegularTokens { + if regularToken.NativeChain == constants.HederaNetworkId { + configuration.FeePercentages[tokenKey] = regularToken.FeePercentage + } } for i, props := range e2eConfig.Hedera.DbValidationProps { @@ -100,8 +101,8 @@ func Load() *Setup { panic(err) } - routerClients, evmFungibleTokenClients := evmSetup.RouterAndEVMTokenClientsFromEVMUtils(setup.Clients.EVM) - setup.AssetMappings = assets.NewService(e2eConfig.Bridge.Networks, e2eConfig.Hedera.BridgeAccount, configuration.FeePercentages, routerClients, setup.Clients.MirrorNode, evmFungibleTokenClients) + routerClients, evmRegularTokenClients := evmSetup.RouterAndEVMTokenClientsFromEVMUtils(setup.Clients.EVM) + setup.AssetMappings = assets.NewService(e2eConfig.Bridge.RegularTokens, e2eConfig.Bridge.Networks.EVM, e2eConfig.Hedera.BridgeAccount, configuration.FeePercentages, routerClients, setup.Clients.MirrorNode, evmRegularTokenClients) return setup } @@ -230,7 +231,7 @@ func newClients(config Config) (*clients, error) { return nil, errors.New("chain IDs mismatch config and actual") } - network, ok := config.Bridge.Networks[configChainId] + network, ok := config.Bridge.Networks.EVM[configChainId] if !ok || network.RouterContractAddress == "" { continue } @@ -252,14 +253,14 @@ func newClients(config Config) (*clients, error) { Receiver: common.HexToAddress(signer.Address()), RouterAddress: routerContractAddress, WToken: config.Tokens.WToken, - EVMFungibleTokenClients: make(map[string]client.EvmFungibleToken), + EVMRegularTokenClients: make(map[string]client.EvmRegularToken), } } - evmFungibleTokenClients := bootstrap.InitEvmFungibleTokenClients(config.Bridge.Networks, evmClients) + evmRegularTokenClients := bootstrap.InitEvmRegularTokenClients(config.Bridge.Networks.EVM, evmClients, config.Bridge.RegularTokens) for networkId := range config.EVM { - for tokenAddress, tokenClient := range evmFungibleTokenClients[networkId] { - EVM[networkId].EVMFungibleTokenClients[tokenAddress] = tokenClient + for tokenAddress, tokenClient := range evmRegularTokenClients[networkId] { + EVM[networkId].EVMRegularTokenClients[tokenAddress] = tokenClient } } diff --git a/e2e/setup/evm/setup.go b/e2e/setup/evm/setup.go index 41631659b..21c66d96e 100644 --- a/e2e/setup/evm/setup.go +++ b/e2e/setup/evm/setup.go @@ -31,7 +31,7 @@ import ( type Utils struct { EVMClient *evm.Client - EVMFungibleTokenClients map[string]client.EvmFungibleToken + EVMRegularTokenClients map[string]client.EvmRegularToken RouterContract *router.Router KeyTransactor *bind.TransactOpts Signer *evm_signer.Signer @@ -42,20 +42,20 @@ type Utils struct { func RouterAndEVMTokenClientsFromEVMUtils(evmUtils map[uint64]Utils) ( routerClients map[uint64]client.DiamondRouter, - evmFungibleTokenClients map[uint64]map[string]client.EvmFungibleToken, + evmRegularTokenClients map[uint64]map[string]client.EvmRegularToken, ) { routerClients = make(map[uint64]client.DiamondRouter) - evmFungibleTokenClients = make(map[uint64]map[string]client.EvmFungibleToken) + evmRegularTokenClients = make(map[uint64]map[string]client.EvmRegularToken) for networkId, evmUtil := range evmUtils { routerClients[networkId] = evmUtil.RouterContract - evmFungibleTokenClients[networkId] = make(map[string]client.EvmFungibleToken) - for tokenAddress, evmTokenClient := range evmUtil.EVMFungibleTokenClients { - evmFungibleTokenClients[networkId][tokenAddress] = evmTokenClient + evmRegularTokenClients[networkId] = make(map[string]client.EvmRegularToken) + for tokenAddress, evmTokenClient := range evmUtil.EVMRegularTokenClients { + evmRegularTokenClients[networkId][tokenAddress] = evmTokenClient } } - return routerClients, evmFungibleTokenClients + return routerClients, evmRegularTokenClients } func InitAssetContract(asset string, evmClient *evm.Client) (*wtoken.Wtoken, error) { @@ -66,7 +66,7 @@ func NativeToWrappedAsset(assetsService service.Assets, sourceChain, targetChain wrappedAsset := assetsService.NativeToWrapped(nativeAsset, sourceChain, targetChain) if wrappedAsset == "" { - return "", fmt.Errorf("EvmFungibleToken [%s] is not supported", nativeAsset) + return "", fmt.Errorf("EvmRegularToken [%s] is not supported", nativeAsset) } return wrappedAsset, nil diff --git a/scripts/bridge/setup/extend-config/cmd/extend-bridge-config.go b/scripts/bridge/setup/extend-config/cmd/extend-bridge-config.go index da6413094..92232a112 100644 --- a/scripts/bridge/setup/extend-config/cmd/extend-bridge-config.go +++ b/scripts/bridge/setup/extend-config/cmd/extend-bridge-config.go @@ -188,7 +188,7 @@ func updateEvmFungibleAssetInfo( assetInfo *parser.FungibleTokenForDeploy, networkId uint64, assetAddress string, - evmTokenClient client.EvmFungibleToken, + evmTokenClient client.EvmRegularToken, ) (err error) { name, err := evmTokenClient.Name(&bind.CallOpts{}) if err != nil { diff --git a/scripts/bridge/setup/parser/extended-bridge.go b/scripts/bridge/setup/parser/extended-bridge.go index 56dee5176..208bdd75f 100644 --- a/scripts/bridge/setup/parser/extended-bridge.go +++ b/scripts/bridge/setup/parser/extended-bridge.go @@ -27,12 +27,14 @@ import ( // parser.Bridge struct but without omit empty type newBridgeConfig struct { - UseLocalConfig bool `yaml:"use_local_config" json:"useLocalConfig"` - ConfigTopicId string `yaml:"config_topic_id" json:"configTopicId"` - PollingInterval time.Duration `yaml:"polling_interval" json:"pollingInterval"` - TopicId string `yaml:"topic_id" json:"topicId"` - Networks map[uint64]*parser.Network `yaml:"networks" json:"networks"` - MonitoredAccounts map[string]string `yaml:"monitored_accounts" json:"monitoredAccounts"` + UseLocalConfig bool `yaml:"use_local_config" json:"useLocalConfig"` + ConfigTopicId string `yaml:"config_topic_id" json:"configTopicId"` + PollingInterval time.Duration `yaml:"polling_interval" json:"pollingInterval"` + TopicId string `yaml:"topic_id" json:"topicId"` + Networks parser.Networks `yaml:"networks" json:"networks"` + RegularTokens map[string]*parser.RegularToken `yaml:"regular_tokens" json:"regularTokens"` + MonitoredAccounts map[string]string `yaml:"monitored_accounts" json:"monitoredAccounts"` + BlacklistedAccounts []string `yaml:"blacklist" json:"blacklistedAccounts"` } type ExtendedConfig struct { @@ -75,39 +77,61 @@ func (b *ExtendedBridge) ToBridgeParser() *newBridgeConfig { parsedBridge.PollingInterval = b.PollingInterval parsedBridge.TopicId = b.TopicId parsedBridge.MonitoredAccounts = b.MonitoredAccounts - parsedBridge.Networks = make(map[uint64]*parser.Network) + parsedBridge.Networks = parser.Networks{ + Hedera: make(map[uint64]*parser.HederaNetwork), + EVM: make(map[uint64]*parser.EVMNetwork), + } + parsedBridge.RegularTokens = make(map[string]*parser.RegularToken) for network, networkInfo := range b.Networks { - parsedBridge.Networks[network] = &parser.Network{ - Name: networkInfo.Name, - BridgeAccount: networkInfo.BridgeAccount, - PayerAccount: networkInfo.PayerAccount, - RouterContractAddress: networkInfo.RouterContractAddress, - Members: networkInfo.Members, - Tokens: parser.Tokens{}, + if networkInfo.BridgeAccount != "" { + parsedBridge.Networks.Hedera[network] = &parser.HederaNetwork{ + Name: networkInfo.Name, + BridgeAccount: networkInfo.BridgeAccount, + PayerAccount: networkInfo.PayerAccount, + Members: networkInfo.Members, + } + } else { + parsedBridge.Networks.EVM[network] = &parser.EVMNetwork{ + Name: networkInfo.Name, + RouterContractAddress: networkInfo.RouterContractAddress, + } } - parsedBridge.Networks[network].Tokens.Fungible = make(map[string]parser.Token) for tokenAddress, tokenInfo := range networkInfo.Tokens.Fungible { - parsedBridge.Networks[network].Tokens.Fungible[tokenAddress] = parser.Token{ - FeePercentage: tokenInfo.FeePercentage, - MinFeeAmountInUsd: tokenInfo.MinFeeAmountInUsd, - MinAmount: tokenInfo.MinAmount, - Networks: tokenInfo.Networks, - CoinGeckoId: tokenInfo.CoinGeckoId, - CoinMarketCapId: tokenInfo.CoinMarketCapId, - ReleaseTimestamp: tokenInfo.ReleaseTimestamp, + if networkInfo.BridgeAccount == "" && len(tokenInfo.Networks) == 0 { + // Skip wrapped-only tokens on EVM (no sub-networks) + continue + } + var addr *string + if networkInfo.BridgeAccount != "" { + if tokenAddress != constants.Hbar { + addr = &tokenAddress + } + } else { + a := tokenAddress + addr = &a + } + parsedBridge.RegularTokens[tokenAddress] = &parser.RegularToken{ + NativeChain: network, + Address: addr, + CoinGeckoId: tokenInfo.CoinGeckoId, + CoinMarketCapId: tokenInfo.CoinMarketCapId, + FeePercentage: tokenInfo.FeePercentage, + AddressesPerNetwork: tokenInfo.Networks, } } } return &newBridgeConfig{ - UseLocalConfig: parsedBridge.UseLocalConfig, - ConfigTopicId: parsedBridge.ConfigTopicId, - PollingInterval: parsedBridge.PollingInterval, - TopicId: parsedBridge.TopicId, - MonitoredAccounts: parsedBridge.MonitoredAccounts, - Networks: parsedBridge.Networks, + UseLocalConfig: parsedBridge.UseLocalConfig, + ConfigTopicId: parsedBridge.ConfigTopicId, + PollingInterval: parsedBridge.PollingInterval, + TopicId: parsedBridge.TopicId, + MonitoredAccounts: parsedBridge.MonitoredAccounts, + Networks: parsedBridge.Networks, + RegularTokens: parsedBridge.RegularTokens, + BlacklistedAccounts: parsedBridge.BlacklistedAccounts, } // return parsedBridge } @@ -122,7 +146,7 @@ type NetworkForDeploy struct { } type TokensForDeploy struct { - Fungible map[string]*FungibleTokenForDeploy `yaml:"fungible,omitempty" json:"fungible,omitempty"` + Fungible map[string]*FungibleTokenForDeploy `yaml:"fungible,omitempty" json:"fungible,omitempty"` } type FungibleTokenForDeploy struct { diff --git a/test/constants/bridge.go b/test/constants/bridge.go index d861e3c48..9a5057ff3 100644 --- a/test/constants/bridge.go +++ b/test/constants/bridge.go @@ -164,55 +164,57 @@ var ( ReserveAmount: ReserveAmountBigInt, } - Networks = map[uint64]*parser.Network{ + HederaNetworks = map[uint64]*parser.HederaNetwork{ constants.HederaNetworkId: { Name: "Hedera", BridgeAccount: BridgeAccountId, PayerAccount: "0.0.476139", Members: []string{"0.0.123", "0.0.321", "0.0.231"}, - Tokens: parser.Tokens{ - Fungible: map[string]parser.Token{ - NetworkHederaFungibleNativeToken: { - Networks: map[uint64]string{ - PolygonNetworkId: NetworkPolygonFungibleWrappedTokenForNetworkHedera, - EthereumNetworkId: NetworkEthereumFungibleWrappedTokenForNetworkHedera, - }, - CoinGeckoId: HbarCoinGeckoId, - CoinMarketCapId: HbarCoinMarketCapId, - MinFeeAmountInUsd: MinFeeAmountInUsd.String(), - }, - }, - }, }, + } + + EVMNetworks = map[uint64]*parser.EVMNetwork{ EthereumNetworkId: { Name: "Ethereum", RouterContractAddress: EthereumRouterContractAddress, - Tokens: parser.Tokens{ - Fungible: map[string]parser.Token{ - NetworkEthereumFungibleNativeToken: { - Networks: map[uint64]string{ - PolygonNetworkId: NetworkPolygonFungibleWrappedTokenForNetworkEthereum, - }, - CoinGeckoId: EthereumCoinGeckoId, - CoinMarketCapId: EthereumCoinMarketCapId, - MinFeeAmountInUsd: MinFeeAmountInUsd.String(), - }, - }, - }, }, PolygonNetworkId: { Name: "Polygon", RouterContractAddress: PolygonRouterContractAddress, - Tokens: parser.Tokens{ - Fungible: map[string]parser.Token{ - NetworkPolygonFungibleNativeToken: { - Networks: map[uint64]string{ - constants.HederaNetworkId: NetworkHederaFungibleWrappedTokenForNetworkPolygon, - EthereumNetworkId: NetworkEthereumFungibleWrappedTokenForNetworkPolygon, - }, - MinFeeAmountInUsd: MinFeeAmountInUsd.String(), - }, - }, + }, + } + + RegularTokens = map[string]*parser.RegularToken{ + NetworkHederaFungibleNativeToken: { + NativeChain: constants.HederaNetworkId, + MinFeeAmountInUsd: &MinFeeAmountInUsd, + CoinGeckoId: HbarCoinGeckoId, + CoinMarketCapId: HbarCoinMarketCapId, + FeePercentage: FeePercentage, + AddressesPerNetwork: map[uint64]string{ + PolygonNetworkId: NetworkPolygonFungibleWrappedTokenForNetworkHedera, + EthereumNetworkId: NetworkEthereumFungibleWrappedTokenForNetworkHedera, + }, + }, + NetworkEthereumFungibleNativeToken: { + NativeChain: EthereumNetworkId, + Address: &NetworkEthereumFungibleNativeToken, + MinFeeAmountInUsd: &MinFeeAmountInUsd, + CoinGeckoId: EthereumCoinGeckoId, + CoinMarketCapId: EthereumCoinMarketCapId, + FeePercentage: FeePercentage, + AddressesPerNetwork: map[uint64]string{ + PolygonNetworkId: NetworkPolygonFungibleWrappedTokenForNetworkEthereum, + }, + }, + NetworkPolygonFungibleNativeToken: { + NativeChain: PolygonNetworkId, + Address: &NetworkPolygonFungibleNativeToken, + MinFeeAmountInUsd: &MinFeeAmountInUsd, + FeePercentage: FeePercentage, + AddressesPerNetwork: map[uint64]string{ + constants.HederaNetworkId: NetworkHederaFungibleWrappedTokenForNetworkPolygon, + EthereumNetworkId: NetworkEthereumFungibleWrappedTokenForNetworkPolygon, }, }, } @@ -289,9 +291,13 @@ var ( } ParserBridge = parser.Bridge{ - UseLocalConfig: true, - TopicId: TopicId, - Networks: Networks, + UseLocalConfig: true, + TopicId: TopicId, + Networks: parser.Networks{ + Hedera: HederaNetworks, + EVM: EVMNetworks, + }, + RegularTokens: RegularTokens, MonitoredAccounts: make(map[string]string), } ) diff --git a/test/helper/networks.go b/test/helper/networks.go index 5859e144f..c1716a3a6 100644 --- a/test/helper/networks.go +++ b/test/helper/networks.go @@ -22,7 +22,11 @@ import ( ) func SetupNetworks() { - for networkId, networkInfo := range testConstants.Networks { + for networkId, networkInfo := range testConstants.HederaNetworks { + constants.NetworksById[networkId] = networkInfo.Name + constants.NetworksByName[networkInfo.Name] = networkId + } + for networkId, networkInfo := range testConstants.EVMNetworks { constants.NetworksById[networkId] = networkInfo.Name constants.NetworksByName[networkInfo.Name] = networkId } diff --git a/test/mocks/client/evm_fungible_token_client_mock.go b/test/mocks/client/evm_regular_token_client_mock.go similarity index 71% rename from test/mocks/client/evm_fungible_token_client_mock.go rename to test/mocks/client/evm_regular_token_client_mock.go index 78ed78fe5..a772cb790 100644 --- a/test/mocks/client/evm_fungible_token_client_mock.go +++ b/test/mocks/client/evm_regular_token_client_mock.go @@ -23,31 +23,31 @@ import ( "math/big" ) -type MockEvmFungibleToken struct { +type MockEvmRegularToken struct { mock.Mock } -func (m *MockEvmFungibleToken) Decimals(opts *bind.CallOpts) (uint8, error) { +func (m *MockEvmRegularToken) Decimals(opts *bind.CallOpts) (uint8, error) { args := m.Called(opts) return args.Get(0).(uint8), args.Error(1) } -func (m *MockEvmFungibleToken) Name(opts *bind.CallOpts) (string, error) { +func (m *MockEvmRegularToken) Name(opts *bind.CallOpts) (string, error) { args := m.Called(opts) return args.Get(0).(string), args.Error(1) } -func (m *MockEvmFungibleToken) Symbol(opts *bind.CallOpts) (string, error) { +func (m *MockEvmRegularToken) Symbol(opts *bind.CallOpts) (string, error) { args := m.Called(opts) return args.Get(0).(string), args.Error(1) } -func (m *MockEvmFungibleToken) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { +func (m *MockEvmRegularToken) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { args := m.Called(opts) return args.Get(0).(*big.Int), args.Error(1) } -func (m *MockEvmFungibleToken) BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) { +func (m *MockEvmRegularToken) BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) { args := m.Called(opts, account) return args.Get(0).(*big.Int), args.Error(1) } diff --git a/test/mocks/service/assets_service_mock.go b/test/mocks/service/assets_service_mock.go index 5ccf5624e..b16f296a8 100644 --- a/test/mocks/service/assets_service_mock.go +++ b/test/mocks/service/assets_service_mock.go @@ -105,8 +105,8 @@ func (mas *MockAssetsService) FetchHederaTokenReserveAmount(assetId string, mirr return args.Get(0).(*big.Int), args.Error(1) } -// FetchEvmFungibleReserveAmount Gets EVM's Fungible Token Reserve Amount -func (mas *MockAssetsService) FetchEvmFungibleReserveAmount(networkId uint64, assetAddress string, isNative bool, evmTokenClient client.EvmFungibleToken, routerContractAddress string) (inLowestDenomination *big.Int, err error) { +// FetchEvmRegularReserveAmount Gets EVM's Fungible Token Reserve Amount +func (mas *MockAssetsService) FetchEvmRegularReserveAmount(networkId uint64, assetAddress string, isNative bool, evmTokenClient client.EvmRegularToken, routerContractAddress string) (inLowestDenomination *big.Int, err error) { args := mas.Called(networkId, assetAddress, isNative, evmTokenClient, routerContractAddress) return args.Get(0).(*big.Int), args.Error(1) } diff --git a/test/mocks/setup.go b/test/mocks/setup.go index 06d6bb1c2..cf87eab74 100644 --- a/test/mocks/setup.go +++ b/test/mocks/setup.go @@ -49,7 +49,7 @@ var MHTTPClient *client.MockHttp var MDiamondRouter *client.MockDiamondRouter var MReadOnlyService *service.MockReadOnlyService var MEVMClient *client.MockEVM -var MEvmFungibleTokenClient *client.MockEvmFungibleToken +var MEvmRegularTokenClient *client.MockEvmRegularToken var MPricingClient *client.MockPricingClient var MSignerService *service.MockSignerService var MDatabase *database.MockDatabase @@ -88,7 +88,7 @@ func Setup() { MHederaNodeClient = &client.MockHederaNode{} MEVMClient = &client.MockEVM{} MEVMCoreClient = &client.MockEVMCore{} - MEvmFungibleTokenClient = &client.MockEvmFungibleToken{} + MEvmRegularTokenClient = &client.MockEvmRegularToken{} MHTTPClient = &client.MockHttp{} MDiamondRouter = &client.MockDiamondRouter{} MQueue = &queue.MockQueue{}