diff --git a/services/rfq/relayer/quoter/quoter.go b/services/rfq/relayer/quoter/quoter.go index 564d671a53..2caa917140 100644 --- a/services/rfq/relayer/quoter/quoter.go +++ b/services/rfq/relayer/quoter/quoter.go @@ -75,12 +75,19 @@ func NewQuoterManager(config relconfig.Config, metricsHandler metrics.Handler, i qt := make(map[string][]string) // fix any casing issues. - for token, destTokens := range config.QuotableTokens { - processedDestTokens := make([]string, len(destTokens)) - for i := range destTokens { - processedDestTokens[i] = strings.ToLower(destTokens[i]) + for tokenID, destTokenIDs := range config.QuotableTokens { + processedDestTokens := make([]string, len(destTokenIDs)) + for i := range destTokenIDs { + processedDestTokens[i], err = relconfig.SanitizeTokenID(destTokenIDs[i]) + if err != nil { + return nil, fmt.Errorf("error sanitizing dest token ID: %w", err) + } + } + sanitizedID, err := relconfig.SanitizeTokenID(tokenID) + if err != nil { + return nil, fmt.Errorf("error sanitizing token ID: %w", err) } - qt[strings.ToLower(token)] = processedDestTokens + qt[sanitizedID] = processedDestTokens } var ss client.ScreenerClient @@ -140,7 +147,7 @@ func (m *Manager) ShouldProcess(parentCtx context.Context, quote reldb.QuoteRequ // allowed pairs for this origin token on the destination destPairs := m.quotableTokens[quote.GetOriginIDPair()] - if !(slices.Contains(destPairs, strings.ToLower(quote.GetDestIDPair()))) { + if !(slices.Contains(destPairs, quote.GetDestIDPair())) { span.AddEvent(fmt.Sprintf("%s not in %s or %s not found", quote.GetDestIDPair(), strings.Join(destPairs, ", "), quote.GetOriginIDPair())) return false, nil } @@ -250,8 +257,7 @@ func (m *Manager) generateQuotes(ctx context.Context, chainID int, address commo var quotes []model.PutQuoteRequest for keyTokenID, itemTokenIDs := range m.quotableTokens { for _, tokenID := range itemTokenIDs { - // TODO: probably a better way to do this. - if strings.ToLower(tokenID) == strings.ToLower(destTokenID) { + if tokenID == destTokenID { originStr := strings.Split(keyTokenID, "-")[0] origin, err := strconv.Atoi(originStr) if err != nil { diff --git a/services/rfq/relayer/quoter/quoter_test.go b/services/rfq/relayer/quoter/quoter_test.go index 2bf9799d74..ae4279d89a 100644 --- a/services/rfq/relayer/quoter/quoter_test.go +++ b/services/rfq/relayer/quoter/quoter_test.go @@ -28,7 +28,7 @@ func (s *QuoterSuite) TestGenerateQuotes() { expectedQuotes := []model.PutQuoteRequest{ { OriginChainID: int(s.origin), - OriginTokenAddr: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + OriginTokenAddr: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", DestChainID: int(s.destination), DestTokenAddr: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", DestAmount: balance.String(), diff --git a/services/rfq/relayer/relconfig/config.go b/services/rfq/relayer/relconfig/config.go index 71ad2c43c5..52357396ba 100644 --- a/services/rfq/relayer/relconfig/config.go +++ b/services/rfq/relayer/relconfig/config.go @@ -5,6 +5,7 @@ import ( "fmt" "math/big" "os" + "strconv" "strings" "time" @@ -114,6 +115,24 @@ type ChainFeeParams struct { L1FeeDestGasEstimate int `yaml:"l1_fee_dest_gas_estimate"` } +const tokenIDDelimiter = "-" + +// SanitizeTokenID takes a raw string, makes sure it is a valid token ID, +// and returns the token ID as string with a checksummed address. +func SanitizeTokenID(id string) (sanitized string, err error) { + split := strings.Split(id, tokenIDDelimiter) + if len(split) != 2 { + return sanitized, fmt.Errorf("invalid token ID: %s", id) + } + chainID, err := strconv.Atoi(split[0]) + if err != nil { + return sanitized, fmt.Errorf("invalid chain ID: %s", split[0]) + } + addr := common.HexToAddress(split[1]) + sanitized = fmt.Sprintf("%d%s%s", chainID, tokenIDDelimiter, addr.Hex()) + return sanitized, nil +} + // LoadConfig loads the config from the given path. func LoadConfig(path string) (config Config, err error) { input, err := os.ReadFile(filepath.Clean(path)) @@ -222,8 +241,7 @@ func (c Config) GetTokenName(chain uint32, addr string) (string, error) { return "", fmt.Errorf("no chain config for chain %d", chain) } for tokenName, tokenConfig := range chainConfig.Tokens { - // TODO: probably a better way to do this. - if strings.ToLower(tokenConfig.Address) == strings.ToLower(addr) { + if common.HexToAddress(tokenConfig.Address).Hex() == common.HexToAddress(addr).Hex() { return tokenName, nil } } @@ -335,7 +353,7 @@ func (c Config) GetMinQuoteAmount(chainID int, addr common.Address) *big.Int { var tokenCfg *TokenConfig for _, cfg := range chainCfg.Tokens { - if strings.EqualFold(cfg.Address, addr.String()) { + if common.HexToAddress(cfg.Address).Hex() == addr.Hex() { cfgCopy := cfg tokenCfg = &cfgCopy break diff --git a/services/rfq/relayer/reldb/db.go b/services/rfq/relayer/reldb/db.go index 723cce855d..c3901f190e 100644 --- a/services/rfq/relayer/reldb/db.go +++ b/services/rfq/relayer/reldb/db.go @@ -5,7 +5,6 @@ import ( "database/sql/driver" "errors" "fmt" - "strings" "github.com/ethereum/go-ethereum/common" "github.com/synapsecns/sanguine/core/dbcommon" @@ -74,14 +73,14 @@ type QuoteRequest struct { // for some reason, this is specified as [chainid]-[tokenaddr] in the config. // this represents the origin pair. func (q QuoteRequest) GetOriginIDPair() string { - return strings.ToLower(fmt.Sprintf("%d-%s", q.Transaction.OriginChainId, q.Transaction.OriginToken.String())) + return fmt.Sprintf("%d-%s", q.Transaction.OriginChainId, q.Transaction.OriginToken.Hex()) } // GetDestIDPair gets the destination chain id and token address pair. // for some reason, this is specified as [chainid]-[tokenaddr] in the config. // this represents the destination pair. func (q QuoteRequest) GetDestIDPair() string { - return strings.ToLower(fmt.Sprintf("%d-%s", q.Transaction.DestChainId, q.Transaction.DestToken.String())) + return fmt.Sprintf("%d-%s", q.Transaction.DestChainId, q.Transaction.DestToken.Hex()) } // QuoteRequestStatus is the status of a quote request in the db.