diff --git a/.changeset/green-crabs-joke.md b/.changeset/green-crabs-joke.md new file mode 100644 index 00000000000..4e9480e9c89 --- /dev/null +++ b/.changeset/green-crabs-joke.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#bugfix Update DA oracle config struct members to pointers diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go index 0f84d80a1f8..fa40dca6b85 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go @@ -600,7 +600,11 @@ type TestDAOracleConfig struct { evmconfig.DAOracle } -func (d *TestDAOracleConfig) OracleType() toml.DAOracleType { return toml.DAOracleOPStack } +func (d *TestDAOracleConfig) OracleType() *toml.DAOracleType { + oracleType := toml.DAOracleOPStack + return &oracleType +} + func (d *TestDAOracleConfig) OracleAddress() *types.EIP55Address { a, err := types.NewEIP55Address("0x420000000000000000000000000000000000000F") if err != nil { @@ -608,7 +612,10 @@ func (d *TestDAOracleConfig) OracleAddress() *types.EIP55Address { } return &a } -func (d *TestDAOracleConfig) CustomGasPriceCalldata() string { return "" } + +func (d *TestDAOracleConfig) CustomGasPriceCalldata() *string { + return nil +} func (g *TestGasEstimatorConfig) BlockHistory() evmconfig.BlockHistory { return &TestBlockHistoryConfig{} diff --git a/core/chains/evm/config/chain_scoped_gas_estimator.go b/core/chains/evm/config/chain_scoped_gas_estimator.go index 1e04690b12f..764efc20191 100644 --- a/core/chains/evm/config/chain_scoped_gas_estimator.go +++ b/core/chains/evm/config/chain_scoped_gas_estimator.go @@ -127,7 +127,7 @@ type daOracleConfig struct { c toml.DAOracle } -func (d *daOracleConfig) OracleType() toml.DAOracleType { +func (d *daOracleConfig) OracleType() *toml.DAOracleType { return d.c.OracleType } @@ -137,9 +137,9 @@ func (d *daOracleConfig) OracleAddress() *types.EIP55Address { } // CustomGasPriceCalldata returns the calldata for a custom gas price API. -func (d *daOracleConfig) CustomGasPriceCalldata() string { +func (d *daOracleConfig) CustomGasPriceCalldata() *string { // TODO: CCIP-3710 update once custom calldata oracle is added - return "" + return nil } type limitJobTypeConfig struct { diff --git a/core/chains/evm/config/config.go b/core/chains/evm/config/config.go index 6d4bcf159b5..f2a571f94b0 100644 --- a/core/chains/evm/config/config.go +++ b/core/chains/evm/config/config.go @@ -165,9 +165,9 @@ type BlockHistory interface { } type DAOracle interface { - OracleType() toml.DAOracleType + OracleType() *toml.DAOracleType OracleAddress() *types.EIP55Address - CustomGasPriceCalldata() string + CustomGasPriceCalldata() *string } type FeeHistory interface { diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go index cc6a8d4eabf..4a1f73094d5 100644 --- a/core/chains/evm/config/toml/config.go +++ b/core/chains/evm/config/toml/config.go @@ -759,9 +759,9 @@ func (u *FeeHistoryEstimator) setFrom(f *FeeHistoryEstimator) { } type DAOracle struct { - OracleType DAOracleType + OracleType *DAOracleType OracleAddress *types.EIP55Address - CustomGasPriceCalldata string + CustomGasPriceCalldata *string } type DAOracleType string @@ -772,6 +772,17 @@ const ( DAOracleZKSync = DAOracleType("zksync") ) +func (o *DAOracle) ValidateConfig() (err error) { + if o.OracleType != nil { + if *o.OracleType == DAOracleOPStack { + if o.OracleAddress == nil { + err = multierr.Append(err, commonconfig.ErrMissing{Name: "OracleAddress", Msg: "required for 'opstack' oracle types"}) + } + } + } + return +} + func (o DAOracleType) IsValid() bool { switch o { case "", DAOracleOPStack, DAOracleArbitrum, DAOracleZKSync: @@ -781,11 +792,15 @@ func (o DAOracleType) IsValid() bool { } func (d *DAOracle) setFrom(f *DAOracle) { - d.OracleType = f.OracleType + if v := f.OracleType; v != nil { + d.OracleType = v + } if v := f.OracleAddress; v != nil { d.OracleAddress = v } - d.CustomGasPriceCalldata = f.CustomGasPriceCalldata + if v := f.CustomGasPriceCalldata; v != nil { + d.CustomGasPriceCalldata = v + } } type KeySpecificConfig []KeySpecific diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go index cac6efb7271..a162cdd014a 100644 --- a/core/chains/evm/gas/models.go +++ b/core/chains/evm/gas/models.go @@ -76,6 +76,7 @@ func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, chaintype ch "priceMax", geCfg.PriceMax(), "priceMin", geCfg.PriceMin(), "estimateLimit", geCfg.EstimateLimit(), + "daOracleType", geCfg.DAOracle().OracleType(), "daOracleAddress", geCfg.DAOracle().OracleAddress(), ) df := geCfg.EIP1559DynamicFees() diff --git a/core/chains/evm/gas/rollups/da_oracle_test_helper.go b/core/chains/evm/gas/rollups/da_oracle_test_helper.go index 6dfa96d3118..ce5343f9863 100644 --- a/core/chains/evm/gas/rollups/da_oracle_test_helper.go +++ b/core/chains/evm/gas/rollups/da_oracle_test_helper.go @@ -13,7 +13,7 @@ type TestDAOracle struct { toml.DAOracle } -func (d *TestDAOracle) OracleType() toml.DAOracleType { +func (d *TestDAOracle) OracleType() *toml.DAOracleType { return d.DAOracle.OracleType } @@ -21,7 +21,7 @@ func (d *TestDAOracle) OracleAddress() *types.EIP55Address { return d.DAOracle.OracleAddress } -func (d *TestDAOracle) CustomGasPriceCalldata() string { +func (d *TestDAOracle) CustomGasPriceCalldata() *string { return d.DAOracle.CustomGasPriceCalldata } @@ -31,9 +31,9 @@ func CreateTestDAOracle(t *testing.T, oracleType toml.DAOracleType, oracleAddres return &TestDAOracle{ DAOracle: toml.DAOracle{ - OracleType: oracleType, + OracleType: &oracleType, OracleAddress: &oracleAddr, - CustomGasPriceCalldata: customGasPriceCalldata, + CustomGasPriceCalldata: &customGasPriceCalldata, }, } } diff --git a/core/chains/evm/gas/rollups/l1_oracle.go b/core/chains/evm/gas/rollups/l1_oracle.go index 28172051fb7..df6fbd9fa44 100644 --- a/core/chains/evm/gas/rollups/l1_oracle.go +++ b/core/chains/evm/gas/rollups/l1_oracle.go @@ -2,6 +2,7 @@ package rollups import ( "context" + "errors" "fmt" "math/big" "slices" @@ -56,7 +57,12 @@ func NewL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chai var l1Oracle L1Oracle var err error if daOracle != nil { - switch daOracle.OracleType() { + oracleType := daOracle.OracleType() + if oracleType == nil { + return nil, errors.New("required field OracleType is nil in non-nil DAOracle config") + } + + switch *oracleType { case toml.DAOracleOPStack: l1Oracle, err = NewOpStackL1GasOracle(lggr, ethClient, chainType, daOracle) case toml.DAOracleArbitrum: diff --git a/core/chains/evm/gas/rollups/op_l1_oracle.go b/core/chains/evm/gas/rollups/op_l1_oracle.go index 4f1e8c67cb7..764a1bfb875 100644 --- a/core/chains/evm/gas/rollups/op_l1_oracle.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle.go @@ -2,6 +2,7 @@ package rollups import ( "context" + "errors" "fmt" "math/big" "strings" @@ -21,6 +22,7 @@ import ( evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" ) // Reads L2-specific precompiles and caches the l1GasPrice set by the L2. @@ -30,12 +32,12 @@ type optimismL1Oracle struct { pollPeriod time.Duration logger logger.SugaredLogger - daOracleConfig evmconfig.DAOracle - l1GasPriceMu sync.RWMutex - l1GasPrice priceEntry - isEcotone bool - isFjord bool - upgradeCheckTs time.Time + daOracleAddress common.Address + l1GasPriceMu sync.RWMutex + l1GasPrice priceEntry + isEcotone bool + isFjord bool + upgradeCheckTs time.Time chInitialised chan struct{} chStop services.StopChan @@ -88,6 +90,20 @@ const ( ) func NewOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType, daOracle evmconfig.DAOracle) (*optimismL1Oracle, error) { + if daOracle.OracleType() == nil { + return nil, errors.New("OracleType is required but was nil") + } + if *daOracle.OracleType() != toml.DAOracleOPStack { + return nil, fmt.Errorf("expected %s oracle type, got %s", toml.DAOracleOPStack, *daOracle.OracleType()) + } + if daOracle.CustomGasPriceCalldata() != nil && *daOracle.CustomGasPriceCalldata() != "" { + lggr.Warnf("CustomGasPriceCalldata is set but will be ignored for OPStack DA oracle") + } + if daOracle.OracleAddress() == nil || *daOracle.OracleAddress() == "" { + return nil, errors.New("OracleAddress is required but was nil or empty") + } + oracleAddress := *daOracle.OracleAddress() + getL1FeeMethodAbi, err := abi.JSON(strings.NewReader(GetL1FeeAbiString)) if err != nil { return nil, fmt.Errorf("failed to parse L1 gas cost method ABI for chain: %s", chainType) @@ -141,10 +157,10 @@ func NewOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainTy pollPeriod: PollPeriod, logger: logger.Sugared(logger.Named(lggr, fmt.Sprintf("L1GasOracle(%s)", chainType))), - daOracleConfig: daOracle, - isEcotone: false, - isFjord: false, - upgradeCheckTs: time.Time{}, + daOracleAddress: oracleAddress.Address(), + isEcotone: false, + isFjord: false, + upgradeCheckTs: time.Time{}, chInitialised: make(chan struct{}), chStop: make(chan struct{}), @@ -276,6 +292,7 @@ func (o *optimismL1Oracle) checkForUpgrade(ctx context.Context) error { if time.Since(o.upgradeCheckTs) < upgradePollingPeriod { return nil } + o.upgradeCheckTs = time.Now() rpcBatchCalls := []rpc.BatchElem{ { @@ -283,7 +300,7 @@ func (o *optimismL1Oracle) checkForUpgrade(ctx context.Context) error { Args: []any{ map[string]interface{}{ "from": common.Address{}, - "to": o.daOracleConfig.OracleAddress().String(), + "to": o.daOracleAddress.String(), "data": hexutil.Bytes(o.isFjordCalldata), }, "latest", @@ -295,7 +312,7 @@ func (o *optimismL1Oracle) checkForUpgrade(ctx context.Context) error { Args: []any{ map[string]interface{}{ "from": common.Address{}, - "to": o.daOracleConfig.OracleAddress().String(), + "to": o.daOracleAddress.String(), "data": hexutil.Bytes(o.isEcotoneCalldata), }, "latest", @@ -336,9 +353,8 @@ func (o *optimismL1Oracle) checkForUpgrade(ctx context.Context) error { } func (o *optimismL1Oracle) getV1GasPrice(ctx context.Context) (*big.Int, error) { - l1OracleAddress := o.daOracleConfig.OracleAddress().Address() b, err := o.client.CallContract(ctx, ethereum.CallMsg{ - To: &l1OracleAddress, + To: &o.daOracleAddress, Data: o.l1BaseFeeCalldata, }, nil) if err != nil { @@ -360,7 +376,7 @@ func (o *optimismL1Oracle) getEcotoneFjordGasPrice(ctx context.Context) (*big.In Args: []any{ map[string]interface{}{ "from": common.Address{}, - "to": o.daOracleConfig.OracleAddress().String(), + "to": o.daOracleAddress.String(), "data": hexutil.Bytes(o.l1BaseFeeCalldata), }, "latest", @@ -372,7 +388,7 @@ func (o *optimismL1Oracle) getEcotoneFjordGasPrice(ctx context.Context) (*big.In Args: []any{ map[string]interface{}{ "from": common.Address{}, - "to": o.daOracleConfig.OracleAddress().String(), + "to": o.daOracleAddress.String(), "data": hexutil.Bytes(o.baseFeeScalarCalldata), }, "latest", @@ -384,7 +400,7 @@ func (o *optimismL1Oracle) getEcotoneFjordGasPrice(ctx context.Context) (*big.In Args: []any{ map[string]interface{}{ "from": common.Address{}, - "to": o.daOracleConfig.OracleAddress().String(), + "to": o.daOracleAddress.String(), "data": hexutil.Bytes(o.blobBaseFeeCalldata), }, "latest", @@ -396,7 +412,7 @@ func (o *optimismL1Oracle) getEcotoneFjordGasPrice(ctx context.Context) (*big.In Args: []any{ map[string]interface{}{ "from": common.Address{}, - "to": o.daOracleConfig.OracleAddress().String(), + "to": o.daOracleAddress.String(), "data": hexutil.Bytes(o.blobBaseFeeScalarCalldata), }, "latest", @@ -408,7 +424,7 @@ func (o *optimismL1Oracle) getEcotoneFjordGasPrice(ctx context.Context) (*big.In Args: []any{ map[string]interface{}{ "from": common.Address{}, - "to": o.daOracleConfig.OracleAddress().String(), + "to": o.daOracleAddress.String(), "data": hexutil.Bytes(o.decimalsCalldata), }, "latest", diff --git a/core/chains/evm/txmgr/test_helpers.go b/core/chains/evm/txmgr/test_helpers.go index 960d921e879..27f94b28ee7 100644 --- a/core/chains/evm/txmgr/test_helpers.go +++ b/core/chains/evm/txmgr/test_helpers.go @@ -82,7 +82,10 @@ type TestDAOracleConfig struct { evmconfig.DAOracle } -func (d *TestDAOracleConfig) OracleType() toml.DAOracleType { return toml.DAOracleOPStack } +func (d *TestDAOracleConfig) OracleType() *toml.DAOracleType { + oracleType := toml.DAOracleOPStack + return &oracleType +} func (d *TestDAOracleConfig) OracleAddress() *types.EIP55Address { a, err := types.NewEIP55Address("0x420000000000000000000000000000000000000F") if err != nil { @@ -90,7 +93,7 @@ func (d *TestDAOracleConfig) OracleAddress() *types.EIP55Address { } return &a } -func (d *TestDAOracleConfig) CustomGasPriceCalldata() string { return "" } +func (d *TestDAOracleConfig) CustomGasPriceCalldata() *string { return nil } func (g *TestGasEstimatorConfig) BlockHistory() evmconfig.BlockHistory { return &TestBlockHistoryConfig{} diff --git a/core/config/docs/docs_test.go b/core/config/docs/docs_test.go index bb572773c4a..9fca08ee99b 100644 --- a/core/config/docs/docs_test.go +++ b/core/config/docs/docs_test.go @@ -97,8 +97,8 @@ func TestDoc(t *testing.T) { docDefaults.Transactions.AutoPurge.Threshold = nil docDefaults.Transactions.AutoPurge.MinAttempts = nil - // GasEstimator.DAOracle.OracleAddress is only set if DA oracle config is used - docDefaults.GasEstimator.DAOracle.OracleAddress = nil + // Fallback DA oracle is not set + docDefaults.GasEstimator.DAOracle = evmcfg.DAOracle{} assertTOML(t, fallbackDefaults, docDefaults) }) diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 4171c7af164..b3533398518 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -1398,9 +1398,16 @@ func TestConfig_full(t *testing.T) { if got.EVM[c].Transactions.AutoPurge.DetectionApiUrl == nil { got.EVM[c].Transactions.AutoPurge.DetectionApiUrl = new(commoncfg.URL) } + if got.EVM[c].GasEstimator.DAOracle.OracleType == nil { + oracleType := evmcfg.DAOracleOPStack + got.EVM[c].GasEstimator.DAOracle.OracleType = &oracleType + } if got.EVM[c].GasEstimator.DAOracle.OracleAddress == nil { got.EVM[c].GasEstimator.DAOracle.OracleAddress = new(types.EIP55Address) } + if got.EVM[c].GasEstimator.DAOracle.CustomGasPriceCalldata == nil { + got.EVM[c].GasEstimator.DAOracle.CustomGasPriceCalldata = new(string) + } } cfgtest.AssertFieldsNotNil(t, got) diff --git a/docs/CONFIG.md b/docs/CONFIG.md index ba36c8d258d..0b52274cff8 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -2445,7 +2445,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'opstack' OracleAddress = '0x420000000000000000000000000000000000000F' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 300 @@ -3906,7 +3905,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'opstack' OracleAddress = '0x4200000000000000000000000000000000000005' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 400 @@ -4014,7 +4012,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'zksync' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 50 @@ -4330,7 +4327,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'zksync' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 50 @@ -4438,7 +4434,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'zksync' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 50 @@ -4548,7 +4543,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'opstack' OracleAddress = '0x420000000000000000000000000000000000000F' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 300 @@ -5384,7 +5378,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'opstack' OracleAddress = '0x420000000000000000000000000000000000000F' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 300 @@ -5493,7 +5486,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'opstack' OracleAddress = '0x4200000000000000000000000000000000000005' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 400 @@ -5913,7 +5905,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'opstack' OracleAddress = '0x420000000000000000000000000000000000000F' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 300 @@ -6126,7 +6117,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'arbitrum' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 100 @@ -6235,7 +6225,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'arbitrum' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 100 @@ -6344,7 +6333,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'arbitrum' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 100 @@ -6872,7 +6860,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'opstack' OracleAddress = '0x420000000000000000000000000000000000000F' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 2000 @@ -6984,7 +6971,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'opstack' OracleAddress = '0x420000000000000000000000000000000000000F' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 2000 @@ -7713,7 +7699,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'opstack' OracleAddress = '0x420000000000000000000000000000000000000F' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 300 @@ -7822,7 +7807,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'opstack' OracleAddress = '0x420000000000000000000000000000000000000F' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 300 @@ -7931,7 +7915,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'arbitrum' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 100 @@ -8040,7 +8023,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'arbitrum' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 100 @@ -8148,7 +8130,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'arbitrum' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 100 @@ -8257,7 +8238,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'opstack' OracleAddress = '0x5300000000000000000000000000000000000002' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 50 @@ -8366,7 +8346,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'opstack' OracleAddress = '0x5300000000000000000000000000000000000002' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 50 @@ -8579,7 +8558,6 @@ CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'opstack' OracleAddress = '0x420000000000000000000000000000000000000F' -CustomGasPriceCalldata = '' [HeadTracker] HistoryDepth = 300