synapsecns/sanguine

View on GitHub
services/rfq/relayer/relconfig/config_test.go

Summary

Maintainability
F
4 days
Test Coverage
package relconfig_test

import (
    "context"
    "testing"
    "time"

    "github.com/stretchr/testify/assert"

    "github.com/ethereum/go-ethereum/accounts/abi"
    "github.com/ethereum/go-ethereum/common"
    "github.com/synapsecns/sanguine/services/rfq/relayer/relconfig"
)

//nolint:maintidx
func TestChainGetters(t *testing.T) {
    chainID := 1
    badChainID := 2
    usdcAddr := "0x123"
    cfgWithBase := relconfig.Config{
        Chains: map[int]relconfig.ChainConfig{
            chainID: {
                RFQAddress:              "0x123",
                Confirmations:           1,
                NativeToken:             "MATIC",
                DeadlineBufferSeconds:   10,
                OriginGasEstimate:       10000,
                DestGasEstimate:         20000,
                L1FeeChainID:            10,
                L1FeeOriginGasEstimate:  30000,
                L1FeeDestGasEstimate:    40000,
                MinGasToken:             "1000",
                QuotePct:                relconfig.NewFloatPtr(0),
                QuoteFixedFeeMultiplier: relconfig.NewFloatPtr(1.1),
                RebalanceConfigs: relconfig.RebalanceConfigs{
                    Synapse: &relconfig.SynapseCCTPRebalanceConfig{
                        SynapseCCTPAddress: "0x456",
                    },
                    Circle: &relconfig.CircleCCTPRebalanceConfig{
                        TokenMessengerAddress: "0x789",
                    },
                    Scroll: &relconfig.ScrollRebalanceConfig{
                        L1GatewayAddress:         "0xabc",
                        L1ScrollMessengerAddress: "0xdef",
                        L2GatewayAddress:         "0xghi",
                    },
                },
            },
        },
        BaseChainConfig: relconfig.ChainConfig{
            RFQAddress:              "0x1234",
            Confirmations:           2,
            NativeToken:             "ARB",
            DeadlineBufferSeconds:   11,
            OriginGasEstimate:       10001,
            DestGasEstimate:         20001,
            L1FeeChainID:            11,
            L1FeeOriginGasEstimate:  30001,
            L1FeeDestGasEstimate:    40001,
            MinGasToken:             "1001",
            QuotePct:                relconfig.NewFloatPtr(51),
            QuoteFixedFeeMultiplier: relconfig.NewFloatPtr(1.2),
            RebalanceConfigs: relconfig.RebalanceConfigs{
                Synapse: &relconfig.SynapseCCTPRebalanceConfig{
                    SynapseCCTPAddress: "0x456",
                },
                Circle: &relconfig.CircleCCTPRebalanceConfig{
                    TokenMessengerAddress: "0x789",
                },
                Scroll: &relconfig.ScrollRebalanceConfig{
                    L1GatewayAddress:         "0xabc",
                    L1ScrollMessengerAddress: "0xdef",
                    L2GatewayAddress:         "0xghi",
                },
            },
        },
    }
    cfg := relconfig.Config{
        Chains: map[int]relconfig.ChainConfig{
            chainID: {
                RFQAddress:              "0x123",
                Confirmations:           1,
                NativeToken:             "MATIC",
                DeadlineBufferSeconds:   10,
                OriginGasEstimate:       10000,
                DestGasEstimate:         20000,
                L1FeeChainID:            10,
                L1FeeOriginGasEstimate:  30000,
                L1FeeDestGasEstimate:    40000,
                MinGasToken:             "1000",
                QuotePct:                relconfig.NewFloatPtr(50),
                QuoteFixedFeeMultiplier: relconfig.NewFloatPtr(1.1),
                Tokens: map[string]relconfig.TokenConfig{
                    "USDC": {
                        Address:            usdcAddr,
                        Decimals:           6,
                        MaxRebalanceAmount: "1000",
                    },
                },
                RebalanceConfigs: relconfig.RebalanceConfigs{
                    Synapse: &relconfig.SynapseCCTPRebalanceConfig{
                        SynapseCCTPAddress: "0x456",
                    },
                    Circle: &relconfig.CircleCCTPRebalanceConfig{
                        TokenMessengerAddress: "0x789",
                    },
                    Scroll: &relconfig.ScrollRebalanceConfig{
                        L1GatewayAddress:         "0xabc",
                        L1ScrollMessengerAddress: "0xdef",
                        L2GatewayAddress:         "0xghi",
                    },
                },
            },
        },
    }

    t.Run("GetConfirmations", func(t *testing.T) {
        defaultVal, err := cfg.GetConfirmations(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, defaultVal, relconfig.DefaultChainConfig.Confirmations)

        baseVal, err := cfgWithBase.GetConfirmations(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, baseVal, cfgWithBase.BaseChainConfig.Confirmations)

        chainVal, err := cfgWithBase.GetConfirmations(chainID)
        assert.NoError(t, err)
        assert.Equal(t, chainVal, cfgWithBase.Chains[chainID].Confirmations)
    })

    t.Run("GetNativeToken", func(t *testing.T) {
        defaultVal, err := cfg.GetNativeToken(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, defaultVal, relconfig.DefaultChainConfig.NativeToken)

        baseVal, err := cfgWithBase.GetNativeToken(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, baseVal, cfgWithBase.BaseChainConfig.NativeToken)

        chainVal, err := cfgWithBase.GetNativeToken(chainID)
        assert.NoError(t, err)
        assert.Equal(t, chainVal, cfgWithBase.Chains[chainID].NativeToken)
    })

    t.Run("GetDeadlineBuffer", func(t *testing.T) {
        defaultVal, err := cfg.GetDeadlineBuffer(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, defaultVal, time.Duration(relconfig.DefaultChainConfig.DeadlineBufferSeconds)*time.Second)

        baseVal, err := cfgWithBase.GetDeadlineBuffer(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, baseVal, time.Duration(cfgWithBase.BaseChainConfig.DeadlineBufferSeconds)*time.Second)

        chainVal, err := cfgWithBase.GetDeadlineBuffer(chainID)
        assert.NoError(t, err)
        assert.Equal(t, chainVal, time.Duration(cfgWithBase.Chains[chainID].DeadlineBufferSeconds)*time.Second)
    })

    t.Run("GetOriginGasEstimate", func(t *testing.T) {
        defaultVal, err := cfg.GetOriginGasEstimate(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, defaultVal, relconfig.DefaultChainConfig.OriginGasEstimate)

        baseVal, err := cfgWithBase.GetOriginGasEstimate(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, baseVal, cfgWithBase.BaseChainConfig.OriginGasEstimate)

        chainVal, err := cfgWithBase.GetOriginGasEstimate(chainID)
        assert.NoError(t, err)
        assert.Equal(t, chainVal, cfgWithBase.Chains[chainID].OriginGasEstimate)
    })

    t.Run("GetDestGasEstimate", func(t *testing.T) {
        defaultVal, err := cfg.GetDestGasEstimate(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, defaultVal, relconfig.DefaultChainConfig.DestGasEstimate)

        baseVal, err := cfgWithBase.GetDestGasEstimate(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, baseVal, cfgWithBase.BaseChainConfig.DestGasEstimate)

        chainVal, err := cfgWithBase.GetDestGasEstimate(chainID)
        assert.NoError(t, err)
        assert.Equal(t, chainVal, cfgWithBase.Chains[chainID].DestGasEstimate)
    })

    t.Run("GetL1FeeChainID", func(t *testing.T) {
        defaultVal, err := cfg.GetL1FeeChainID(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, defaultVal, relconfig.DefaultChainConfig.L1FeeChainID)

        baseVal, err := cfgWithBase.GetL1FeeChainID(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, baseVal, cfgWithBase.BaseChainConfig.L1FeeChainID)

        chainVal, err := cfgWithBase.GetL1FeeChainID(chainID)
        assert.NoError(t, err)
        assert.Equal(t, chainVal, cfgWithBase.Chains[chainID].L1FeeChainID)
    })

    t.Run("GetL1FeeOriginGasEstimate", func(t *testing.T) {
        defaultVal, err := cfg.GetL1FeeOriginGasEstimate(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, defaultVal, relconfig.DefaultChainConfig.L1FeeOriginGasEstimate)

        baseVal, err := cfgWithBase.GetL1FeeOriginGasEstimate(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, baseVal, cfgWithBase.BaseChainConfig.L1FeeOriginGasEstimate)

        chainVal, err := cfgWithBase.GetL1FeeOriginGasEstimate(chainID)
        assert.NoError(t, err)
        assert.Equal(t, chainVal, cfgWithBase.Chains[chainID].L1FeeOriginGasEstimate)
    })

    t.Run("GetL1FeeDestGasEstimate", func(t *testing.T) {
        defaultVal, err := cfg.GetL1FeeDestGasEstimate(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, defaultVal, relconfig.DefaultChainConfig.L1FeeDestGasEstimate)

        baseVal, err := cfgWithBase.GetL1FeeDestGasEstimate(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, baseVal, cfgWithBase.BaseChainConfig.L1FeeDestGasEstimate)

        chainVal, err := cfgWithBase.GetL1FeeDestGasEstimate(chainID)
        assert.NoError(t, err)
        assert.Equal(t, chainVal, cfgWithBase.Chains[chainID].L1FeeDestGasEstimate)
    })

    t.Run("GetMinGasToken", func(t *testing.T) {
        defaultVal, err := cfg.GetMinGasToken(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, defaultVal.String(), relconfig.DefaultChainConfig.MinGasToken)

        baseVal, err := cfgWithBase.GetMinGasToken(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, baseVal.String(), cfgWithBase.BaseChainConfig.MinGasToken)

        chainVal, err := cfgWithBase.GetMinGasToken(chainID)
        assert.NoError(t, err)
        assert.Equal(t, chainVal.String(), cfgWithBase.Chains[chainID].MinGasToken)
    })

    t.Run("GetQuotePct", func(t *testing.T) {
        defaultVal, err := cfg.GetQuotePct(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, defaultVal, 100.)

        baseVal, err := cfgWithBase.GetQuotePct(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, baseVal, 51.)

        chainVal, err := cfgWithBase.GetQuotePct(chainID)
        assert.NoError(t, err)
        assert.Equal(t, chainVal, 0.)
    })

    t.Run("GetQuoteFixedFeeMultiplier", func(t *testing.T) {
        defaultVal, err := cfg.GetQuoteFixedFeeMultiplier(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, defaultVal, *relconfig.DefaultChainConfig.QuoteFixedFeeMultiplier)

        baseVal, err := cfgWithBase.GetQuoteFixedFeeMultiplier(badChainID)
        assert.NoError(t, err)
        assert.Equal(t, baseVal, *cfgWithBase.BaseChainConfig.QuoteFixedFeeMultiplier)

        chainVal, err := cfgWithBase.GetQuoteFixedFeeMultiplier(chainID)
        assert.NoError(t, err)
        assert.Equal(t, chainVal, *cfgWithBase.Chains[chainID].QuoteFixedFeeMultiplier)
    })

    t.Run("GetMaxRebalanceAmount", func(t *testing.T) {
        defaultVal := cfg.GetMaxRebalanceAmount(badChainID, common.HexToAddress(usdcAddr))
        assert.Equal(t, defaultVal.String(), abi.MaxInt256.String())

        chainVal := cfg.GetMaxRebalanceAmount(chainID, common.HexToAddress(usdcAddr))
        assert.Equal(t, chainVal.String(), "1000000000")
    })
}

func TestGetQuoteOffset(t *testing.T) {
    chainID := 1
    usdcAddr := "0x123"
    cfg := relconfig.Config{
        Chains: map[int]relconfig.ChainConfig{
            chainID: {
                RFQAddress:              "0x123",
                Confirmations:           1,
                NativeToken:             "MATIC",
                DeadlineBufferSeconds:   10,
                OriginGasEstimate:       10000,
                DestGasEstimate:         20000,
                L1FeeChainID:            10,
                L1FeeOriginGasEstimate:  30000,
                L1FeeDestGasEstimate:    40000,
                MinGasToken:             "1000",
                QuotePct:                relconfig.NewFloatPtr(50),
                QuoteFixedFeeMultiplier: relconfig.NewFloatPtr(1.1),
                Tokens: map[string]relconfig.TokenConfig{
                    "USDC": {
                        Address:            usdcAddr,
                        Decimals:           6,
                        MaxRebalanceAmount: "1000",
                        QuoteOffsetBps:     100,
                    },
                },
            },
        },
    }

    t.Run("GetQuoteOffsetForOrigin", func(t *testing.T) {
        val, err := cfg.GetQuoteOffsetBps(chainID, "USDC", true)
        assert.NoError(t, err)
        assert.Equal(t, -100., val)
    })

    t.Run("GetQuoteOffsetForDest", func(t *testing.T) {
        val, err := cfg.GetQuoteOffsetBps(chainID, "USDC", false)
        assert.NoError(t, err)
        assert.Equal(t, 100., val)
    })
}

func TestValidation(t *testing.T) {
    t.Run("Valid", func(t *testing.T) {
        cfg := relconfig.Config{
            Chains: map[int]relconfig.ChainConfig{
                1: {
                    Tokens: map[string]relconfig.TokenConfig{
                        "USDC": {
                            InitialBalancePct:     50,
                            MaintenanceBalancePct: 25,
                            RebalanceMethods:      []string{"synapsecctp"},
                        },
                    },
                },
                2: {
                    Tokens: map[string]relconfig.TokenConfig{
                        "USDC": {
                            InitialBalancePct:     50,
                            MaintenanceBalancePct: 25,
                            RebalanceMethods:      []string{"synapsecctp"},
                        },
                    },
                },
            },
        }
        err := cfg.Validate(context.Background(), nil)
        assert.Nil(t, err)
    })

    t.Run("InvalidInitialPct", func(t *testing.T) {
        cfg := relconfig.Config{
            Chains: map[int]relconfig.ChainConfig{
                1: {
                    Tokens: map[string]relconfig.TokenConfig{
                        "USDC": {
                            InitialBalancePct:     51,
                            MaintenanceBalancePct: 50,
                            RebalanceMethods:      []string{"synapsecctp"},
                        },
                    },
                },
                2: {
                    Tokens: map[string]relconfig.TokenConfig{
                        "USDC": {
                            InitialBalancePct:     50,
                            MaintenanceBalancePct: 50,
                            RebalanceMethods:      []string{"synapsecctp"},
                        },
                    },
                },
            },
        }
        err := cfg.Validate(context.Background(), nil)
        assert.NotNil(t, err)
        assert.Equal(t, "total initial percent does not total 100 for USDC: 101.000000", err.Error())
    })

    t.Run("InvalidMaintenancePct", func(t *testing.T) {
        cfg := relconfig.Config{
            Chains: map[int]relconfig.ChainConfig{
                1: {
                    Tokens: map[string]relconfig.TokenConfig{
                        "USDC": {
                            InitialBalancePct:     50,
                            MaintenanceBalancePct: 50,
                            RebalanceMethods:      []string{"synapsecctp"},
                        },
                    },
                },
                2: {
                    Tokens: map[string]relconfig.TokenConfig{
                        "USDC": {
                            InitialBalancePct:     50,
                            MaintenanceBalancePct: 50.1,
                            RebalanceMethods:      []string{"synapsecctp"},
                        },
                    },
                },
            },
        }
        err := cfg.Validate(context.Background(), nil)
        assert.NotNil(t, err)
        assert.Equal(t, "total maintenance percent exceeds 100 for USDC: 100.100000", err.Error())
    })

    t.Run("ValidWithNoRebalanceMethod", func(t *testing.T) {
        cfg := relconfig.Config{
            Chains: map[int]relconfig.ChainConfig{
                1: {
                    Tokens: map[string]relconfig.TokenConfig{
                        "USDC": {
                            InitialBalancePct:     50,
                            MaintenanceBalancePct: 20,
                        },
                    },
                },
                2: {
                    Tokens: map[string]relconfig.TokenConfig{
                        "USDC": {
                            InitialBalancePct:     50,
                            MaintenanceBalancePct: 20,
                        },
                    },
                },
            },
        }
        err := cfg.Validate(context.Background(), nil)
        assert.Nil(t, err)
    })
}

func TestDecodeTokenID(t *testing.T) {
    tests := []struct {
        name      string
        id        string
        wantChain int
        wantAddr  common.Address
        wantErr   bool
    }{
        {
            name:      "valid token ID",
            id:        "1-0x1234567890abcdef1234567890abcdef12345678",
            wantChain: 1,
            wantAddr:  common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678"),
            wantErr:   false,
        },
        {
            name:    "invalid token ID format",
            id:      "1_0x1234567890abcdef1234567890abcdef12345678",
            wantErr: true,
        },
        {
            name:    "invalid chain ID",
            id:      "x-0x1234567890abcdef1234567890abcdef12345678",
            wantErr: true,
        },
        {
            name:    "invalid address",
            id:      "1-0x12345",
            wantErr: true,
        },
    }

    for i := range tests {
        tt := tests[i]
        t.Run(tt.name, func(t *testing.T) {
            gotChain, gotAddr, err := relconfig.DecodeTokenID(tt.id)
            if tt.wantErr {
                assert.Error(t, err)
            } else {
                assert.NoError(t, err)
                assert.Equal(t, tt.wantChain, gotChain)
                assert.Equal(t, tt.wantAddr, gotAddr)
            }
        })
    }
}

const usdcAddr = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
const arbAddr = "0x912CE59144191C1204E64559FE8253a0e49E6548"
const opAddr = "0x4200000000000000000000000000000000000042"

func (v *ValidateDecimalsSuite) TestValidateWrongDecimals() {
    cfg := relconfig.Config{
        Chains: map[int]relconfig.ChainConfig{
            1: {
                Tokens: map[string]relconfig.TokenConfig{
                    "USDC": {
                        Address:  usdcAddr,
                        Decimals: 18, // WRONG
                    },
                },
            },
        },
    }
    err := cfg.Validate(v.GetTestContext(), v.omniClient)
    // we should error because the decimals are wrong
    v.Require().Error(err)
}

func (v *ValidateDecimalsSuite) TestValidateCorrectDecimals() {
    cfg := relconfig.Config{
        Chains: map[int]relconfig.ChainConfig{
            1: {
                Tokens: map[string]relconfig.TokenConfig{
                    "USDC": {
                        Address:  usdcAddr,
                        Decimals: 6,
                    },
                },
            },
        },
    }
    err := cfg.Validate(v.GetTestContext(), v.omniClient)
    v.Require().NoError(err)
}

func (v *ValidateDecimalsSuite) TestMixtureDecimals() {
    cfg := relconfig.Config{
        Chains: map[int]relconfig.ChainConfig{
            1: {
                Tokens: map[string]relconfig.TokenConfig{
                    "USDC": {
                        Address:  usdcAddr,
                        Decimals: 6,
                    },
                },
            },
            42161: {
                Tokens: map[string]relconfig.TokenConfig{
                    "ARB": {
                        Address:  arbAddr,
                        Decimals: 18,
                    },
                },
            },
            10: {
                Tokens: map[string]relconfig.TokenConfig{
                    "OP": {
                        Address:  opAddr,
                        Decimals: 69,
                    },
                },
            },
        },
    }

    err := cfg.Validate(v.GetTestContext(), v.omniClient)
    v.Require().Error(err)
}