diff --git a/rollup/internal/config/relayer.go b/rollup/internal/config/relayer.go index a7b2f03f2..1a1d3a1a4 100644 --- a/rollup/internal/config/relayer.go +++ b/rollup/internal/config/relayer.go @@ -1,37 +1,10 @@ package config import ( - "fmt" - "strings" - "github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/rpc" ) -const ( - FIXED ExchangeRateMode = "Fixed" - BINANCE_API ExchangeRateMode = "BinanceApi" - UNISWAP ExchangeRateMode = "Uniswap" -) - -// ExchangeRateMode the mode to retrieve exchange rate -type ExchangeRateMode string - -func (m *ExchangeRateMode) UnmarshalText(data []byte) error { - candidates := []string{ - string(FIXED), - string(BINANCE_API), - // string(UNISWAP), not supported yet - } - for _, i := range candidates { - if string(data) == i { - *m = ExchangeRateMode(i) - return nil - } - } - return fmt.Errorf("invalid mode: %s, must be one of %s", string(data), strings.Join(candidates, ",")) -} - // SenderConfig The config for transaction sender type SenderConfig struct { // The RPC endpoint of the ethereum or scroll public node. @@ -97,10 +70,10 @@ type RelayerConfig struct { // AlternativeGasTokenConfig The configuration for handling token exchange rates when updating the gas price oracle. type AlternativeGasTokenConfig struct { - Enabled bool `json:"enabled"` - Mode ExchangeRateMode `json:"mode"` - FixedExchangeRate float64 `json:"fixed_exchange_rate"` // fixed exchange rate of L2 gas token / L1 gas token - TokenSymbolPair string `json:"token_symbol_pair"` // The pair should be L2 gas token symbol + L1 gas token symbol + Enabled bool `json:"enabled"` + Mode string `json:"mode"` + FixedExchangeRate float64 `json:"fixed_exchange_rate"` // fixed exchange rate of L2 gas token / L1 gas token + TokenSymbolPair string `json:"token_symbol_pair"` // The pair should be L2 gas token symbol + L1 gas token symbol } // GasOracleConfig The config for updating gas price oracle. diff --git a/rollup/internal/controller/relayer/l1_relayer.go b/rollup/internal/controller/relayer/l1_relayer.go index c53212335..ed2f39eb1 100644 --- a/rollup/internal/controller/relayer/l1_relayer.go +++ b/rollup/internal/controller/relayer/l1_relayer.go @@ -17,12 +17,11 @@ import ( "scroll-tech/common/types" "scroll-tech/common/utils" - rutils "scroll-tech/rollup/internal/utils" - bridgeAbi "scroll-tech/rollup/abi" "scroll-tech/rollup/internal/config" "scroll-tech/rollup/internal/controller/sender" "scroll-tech/rollup/internal/orm" + rutils "scroll-tech/rollup/internal/utils" ) // Layer1Relayer is responsible for updating L1 gas price oracle contract on L2. @@ -158,10 +157,10 @@ func (r *Layer1Relayer) ProcessGasPriceOracle() { // The exchange rate represent the number of native token on L1 required to exchange for 1 native token on L2. var exchangeRate float64 switch r.cfg.GasOracleConfig.AlternativeGasTokenConfig.Mode { - case config.FIXED: + case "Fixed": exchangeRate = r.cfg.GasOracleConfig.AlternativeGasTokenConfig.FixedExchangeRate - case config.BINANCE_API: - exchangeRate, err = rutils.GetExchangeRateFromBinanceApi(r.cfg.GasOracleConfig.AlternativeGasTokenConfig.TokenSymbolPair) + case "BinanceApi": + exchangeRate, err = rutils.GetExchangeRateFromBinanceApi(r.cfg.GasOracleConfig.AlternativeGasTokenConfig.TokenSymbolPair, 5) if err != nil { log.Error("Failed to get gas token exchange rate from Binance api", "tokenSymbolPair", r.cfg.GasOracleConfig.AlternativeGasTokenConfig.TokenSymbolPair, "err", err) return diff --git a/rollup/internal/controller/relayer/l2_relayer.go b/rollup/internal/controller/relayer/l2_relayer.go index 96d682066..a3a4f0960 100644 --- a/rollup/internal/controller/relayer/l2_relayer.go +++ b/rollup/internal/controller/relayer/l2_relayer.go @@ -331,15 +331,14 @@ func (r *Layer2Relayer) ProcessGasPriceOracle() { // The exchange rate represent the number of native token on L1 required to exchange for 1 native token on L2. var exchangeRate float64 switch r.cfg.GasOracleConfig.AlternativeGasTokenConfig.Mode { - case config.FIXED: + case "Fixed": exchangeRate = r.cfg.GasOracleConfig.AlternativeGasTokenConfig.FixedExchangeRate - case config.BINANCE_API: - exchangeRate, err = rutils.GetExchangeRateFromBinanceApi(r.cfg.GasOracleConfig.AlternativeGasTokenConfig.TokenSymbolPair) + case "BinanceApi": + exchangeRate, err = rutils.GetExchangeRateFromBinanceApi(r.cfg.GasOracleConfig.AlternativeGasTokenConfig.TokenSymbolPair, 5) if err != nil { log.Error("Failed to get gas token exchange rate from Binance api", "tokenSymbolPair", r.cfg.GasOracleConfig.AlternativeGasTokenConfig.TokenSymbolPair, "err", err) return } - default: log.Error("Invalid alternative gas token mode", "mode", r.cfg.GasOracleConfig.AlternativeGasTokenConfig.Mode) return diff --git a/rollup/internal/utils/exchange_rate.go b/rollup/internal/utils/exchange_rate.go index 39957452a..72c32681f 100644 --- a/rollup/internal/utils/exchange_rate.go +++ b/rollup/internal/utils/exchange_rate.go @@ -6,6 +6,7 @@ import ( "io" "net/http" "strconv" + "time" "github.com/scroll-tech/go-ethereum/log" ) @@ -16,42 +17,57 @@ type BinanceResponse struct { Price string `json:"price"` } -func GetExchangeRateFromBinanceApi(tokenSymbolPair string) (float64, error) { - // make HTTP GET request - resp, err := http.Get(fmt.Sprintf(BinanceApiEndpoint, tokenSymbolPair)) - if err != nil { - return 0, fmt.Errorf("error making HTTP request: %w", err) - } - defer func() { - err = resp.Body.Close() +func GetExchangeRateFromBinanceApi(tokenSymbolPair string, maxRetries int) (float64, error) { + for i := 0; i < maxRetries; i++ { + if i > 0 { + time.Sleep(5 * time.Second) + } + + // make HTTP GET request + resp, err := http.Get(fmt.Sprintf(BinanceApiEndpoint, tokenSymbolPair)) if err != nil { - log.Error("error closing response body", "err", err) + log.Error("error making HTTP request", "err", err) + continue } - }() + defer func() { + err = resp.Body.Close() + if err != nil { + log.Error("error closing response body", "err", err) + } + }() - // check for successful response - if resp.StatusCode != http.StatusOK { - return 0, fmt.Errorf("unexpected status code: %d", resp.StatusCode) - } + // check for successful response + if resp.StatusCode != http.StatusOK { + log.Error("unexpected status code", "code", resp.StatusCode) + continue + } - // read response body - body, err := io.ReadAll(resp.Body) - if err != nil { - return 0, fmt.Errorf("error reading response body: %w", err) - } + // read response body + body, err := io.ReadAll(resp.Body) + if err != nil { + log.Error("error reading response body", "err", err) + continue + } - // unmarshal JSON response - var data BinanceResponse - err = json.Unmarshal(body, &data) - if err != nil { - return 0, fmt.Errorf("error unmarshaling JSON: %w", err) - } + // unmarshal JSON response + var data BinanceResponse + err = json.Unmarshal(body, &data) + if err != nil { + log.Error("error unmarshaling JSON", "err", err) + continue + } + + // convert price string to float64 + price, err := strconv.ParseFloat(data.Price, 64) + if err != nil { + log.Error("error parsing price string", "err", err) + continue + } - // convert price string to float64 - price, err := strconv.ParseFloat(data.Price, 64) - if err != nil { - return 0, fmt.Errorf("error parsing price string: %w", err) + // successful response, return price + return price, nil } - return price, nil + // all retries failed, return error + return 0, fmt.Errorf("failed to get exchange rate after %d retries", maxRetries) }