// Package config provides a configuration struct and getters for the submitter. // // Config contains configuration for the submitter. It can be loaded from a YAML file. // Chain-specific configuration items can be provided via the `Chains` map, which overrides the global config // for each chain. If a chain-specific item is not provided, the global config is used. package config import ( "math/big" "time" "github.com/ethereum/go-ethereum/params" ) // Config contains configuration for the submitter. // //go:generate go run github.com/vburenin/ifacemaker -f config.go -s Config -i IConfig -p config -o iconfig_generated.go -c "autogenerated file" type Config struct { // GlobalConfig stores the default configuration ChainConfig `yaml:",inline"` // Chains overrides the global config for each chain Chains map[int]ChainConfig `yaml:"chains"` // ReaperInterval is the interval at which scan for transactions to flush ReaperInterval time.Duration `yaml:"reaper_interval"` // MaxRecordAge is the maximum age of a record before it is flushed MaxRecordAge time.Duration `yaml:"max_record_age"` } // ChainConfig contains configuration for a specific chain. type ChainConfig struct { // MaxBatchSize is the maximum number of transactions to send in a batch // if this is zero, the default will be used. This field is ignored if batching is disabled. MaxBatchSize int `yaml:"max_batch_size"` // Batch is whether or not to batch transactions at the rpc level DoNotBatch bool `yaml:"skip_batching"` // MaxGasPrice is the maximum gas price to use for transactions MaxGasPrice *big.Int `yaml:"max_gas_price"` // MinGasPrice is the gas price that will be used if 0 is returned from the gas price oracle MinGasPrice *big.Int `yaml:"min_gas_price"` // BumpIntervalSeconds is the number of seconds to wait before bumping a transaction BumpIntervalSeconds int `yaml:"bump_interval_seconds"` // GasBumpPercentages is the percentage to bump the gas price by // this is applied to the greatrer of the chainprice or the last price GasBumpPercentage int `yaml:"gas_bump_percentage"` // GasEstimate is the gas estimate to use for transactions // if dynamic gas estimation is enabled, this is only used as a default if the estimate fails GasEstimate uint64 `yaml:"gas_estimate"` // DynamicGasEstimate is whether or not to use dynamic gas estimation DynamicGasEstimate bool `yaml:"dynamic_gas_estimate"` // SupportsEIP1559 is whether or not this chain supports EIP1559 SupportsEIP1559 bool `yaml:"supports_eip_1559"` } const ( // DefaultMaxBatchSize is the default maximum number of transactions to send in a batch. DefaultMaxBatchSize = 10 // DefaultBumpIntervalSeconds is the default number of seconds to wait before bumping a transaction. DefaultBumpIntervalSeconds = 30 // DefaultGasBumpPercentage is the default percentage to bump the gas price by. // See: https://github.com/ethereum/go-ethereum/blob/8c5576b1ac89473c7ec15c9b03d1ca02e9499dcc/core/txpool/legacypool/legacypool.go#L146 DefaultGasBumpPercentage = 10 // DefaultGasEstimate is the default gas estimate to use for transactions. DefaultGasEstimate = uint64(1200000) ) // DefaultMaxPrice is the default max price of a tx. var DefaultMaxPrice = big.NewInt(500 * params.GWei) // DefaultMinGasPrice is the default min price of a tx. var DefaultMinGasPrice = big.NewInt(0.01 * params.GWei) // DefaultReaperInterval is the default interval at which to scan for transactions to flush. var DefaultReaperInterval = time.Minute * 5 // DefaultMaxRecordAge is the default maximum age of a record before it is flushed. var DefaultMaxRecordAge = time.Hour * 24 * 7 // note: there's probably a way to clean these getters up with generics, the real problem comes with the fact that // that this would require the caller to override the entire struct, which is not ideal.. // GetReaperInterval returns the reaper interval. func (c *Config) GetReaperInterval() time.Duration { if c.ReaperInterval == 0 { return DefaultReaperInterval } return c.ReaperInterval } // GetMaxRecordAge returns the maximum record age. func (c *Config) GetMaxRecordAge() time.Duration { if c.MaxRecordAge == 0 { return DefaultMaxRecordAge } return c.MaxRecordAge } // GetMaxBatchSize returns the maximum number of transactions to send in a batch. func (c *Config) GetMaxBatchSize(chainID int) int { chainConfig, ok := c.Chains[chainID] if ok && chainConfig.MaxBatchSize != 0 { return chainConfig.MaxBatchSize } maxBatch := c.MaxBatchSize if maxBatch == 0 { return DefaultMaxBatchSize } return maxBatch } // GetBatch returns whether or not to batch transactions at the rpc level. func (c *Config) GetBatch(chainID int) bool { chainConfig, ok := c.Chains[chainID] if ok { return !chainConfig.DoNotBatch } return !c.DoNotBatch } // GetMaxGasPrice returns the maximum gas price to use for transactions. func (c *Config) GetMaxGasPrice(chainID int) (maxPrice *big.Int) { maxPrice = c.MaxGasPrice chainConfig, ok := c.Chains[chainID] if ok && chainConfig.MaxGasPrice != nil { maxPrice = chainConfig.MaxGasPrice } if maxPrice == nil || maxPrice == big.NewInt(0) { maxPrice = DefaultMaxPrice } return } // GetMinGasPrice returns the minimum gas price to use for transactions. func (c *Config) GetMinGasPrice(chainID int) (minPrice *big.Int) { minPrice = c.MinGasPrice chainConfig, ok := c.Chains[chainID] if ok && chainConfig.MinGasPrice != nil { minPrice = chainConfig.MinGasPrice } if minPrice == nil || minPrice == big.NewInt(0) { minPrice = DefaultMinGasPrice } return } // GetBumpInterval returns the number of seconds to wait before bumping a transaction // TODO: test this method. func (c *Config) GetBumpInterval(chainID int) time.Duration { var bumpInterval int chainConfig, ok := c.Chains[chainID] if ok { bumpInterval = chainConfig.BumpIntervalSeconds } // if bumpInterval is not set for the chain, use the global config if bumpInterval == 0 { bumpInterval = c.BumpIntervalSeconds } // if the bump interval isn't set at all, use the default if bumpInterval == 0 { bumpInterval = DefaultBumpIntervalSeconds } return time.Duration(bumpInterval) * time.Second } // GetGasBumpPercentage returns the percentage to bump the gas price by // TODO: test this method. func (c *Config) GetGasBumpPercentage(chainID int) (gasBumpPercentage int) { chainConfig, ok := c.Chains[chainID] if ok { gasBumpPercentage = chainConfig.GasBumpPercentage } // if gasBumpPercentage is not set for the chain, use the global config if gasBumpPercentage == 0 { gasBumpPercentage = c.GasBumpPercentage } // if the gasBumpPercentage isn't set at all, use the default if gasBumpPercentage == 0 { gasBumpPercentage = DefaultGasBumpPercentage } return gasBumpPercentage } // GetGasEstimate returns the gas estimate to use for transactions // TODO: test this method. func (c *Config) GetGasEstimate(chainID int) (gasEstimate uint64) { chainConfig, ok := c.Chains[chainID] if ok { gasEstimate = chainConfig.GasEstimate } // if gasBumpPercentage is not set for the chain, use the global config if gasEstimate == 0 { gasEstimate = c.GasEstimate } // if the gasBumpPercentage isn't set at all, use the default if gasEstimate == 0 { gasEstimate = DefaultGasEstimate } return gasEstimate } // GetDynamicGasEstimate returns whether or not to use dynamic gas estimation // TODO: test this method. func (c *Config) GetDynamicGasEstimate(chainID int) bool { chainConfig, ok := c.Chains[chainID] if ok { return chainConfig.DynamicGasEstimate } return c.DynamicGasEstimate } // SupportsEIP1559 returns whether or not this chain supports EIP1559. func (c *Config) SupportsEIP1559(chainID int) bool { chainConfig, ok := c.Chains[chainID] if ok { return chainConfig.SupportsEIP1559 } return c.ChainConfig.SupportsEIP1559 } // SetGlobalMaxGasPrice is a helper function that sets the global gas price. func (c *Config) SetGlobalMaxGasPrice(maxPrice *big.Int) { c.MaxGasPrice = maxPrice } // SetMinGasPrice is a helper function that sets the base gas price. func (c *Config) SetMinGasPrice(basePrice *big.Int) { c.MinGasPrice = basePrice } // SetGlobalEIP1559Support is a helper function that sets the global EIP1559 support. func (c *Config) SetGlobalEIP1559Support(supportsEIP1559 bool) { c.ChainConfig.SupportsEIP1559 = supportsEIP1559 } var _ IConfig = &Config{}