Skip to content

Commit

Permalink
[SHIP-1523] Add X Layer (#12747)
Browse files Browse the repository at this point in the history
* Add X Layer

* go mod tidy

* Add ChainType for XLayer to ignore transactions with 0 gasPrice

* revert switch stmt

* update changeset

* fix test

* add BlockHistoryEstimator test for XLayer
  • Loading branch information
friedemannf authored Apr 30, 2024
1 parent e50d38b commit 2729ef7
Show file tree
Hide file tree
Showing 11 changed files with 241 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/sixty-readers-mix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

Add support for X Layer (X1) #added
4 changes: 3 additions & 1 deletion common/config/chaintype.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const (
ChainScroll ChainType = "scroll"
ChainWeMix ChainType = "wemix"
ChainXDai ChainType = "xdai" // Deprecated: use ChainGnosis instead
ChainXLayer ChainType = "xlayer"
ChainZkSync ChainType = "zksync"
)

Expand All @@ -31,13 +32,14 @@ var ErrInvalidChainType = fmt.Errorf("must be one of %s or omitted", strings.Joi
string(ChainOptimismBedrock),
string(ChainScroll),
string(ChainWeMix),
string(ChainXLayer),
string(ChainZkSync),
}, ", "))

// IsValid returns true if the ChainType value is known or empty.
func (c ChainType) IsValid() bool {
switch c {
case "", ChainArbitrum, ChainCelo, ChainGnosis, ChainKroma, ChainMetis, ChainOptimismBedrock, ChainScroll, ChainWeMix, ChainXDai, ChainZkSync:
case "", ChainArbitrum, ChainCelo, ChainGnosis, ChainKroma, ChainMetis, ChainOptimismBedrock, ChainScroll, ChainWeMix, ChainXDai, ChainXLayer, ChainZkSync:
return true
}
return false
Expand Down
25 changes: 25 additions & 0 deletions core/chains/evm/config/toml/defaults/XLayer_Mainnet.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
ChainID = '196'
ChainType = 'xlayer'
FinalityDepth = 500
NoNewHeadsThreshold = '6m'
MinIncomingConfirmations = 1
LogPollInterval = '30s'
RPCBlockQueryDelay = 15
RPCDefaultBatchSize = 100

[OCR]
ContractConfirmations = 1

[Transactions]
ResendAfterThreshold = '3m'

[GasEstimator]
PriceMin = '100 mwei'
BumpPercent = 40
BumpMin = '100 mwei'

[GasEstimator.BlockHistory]
BlockHistorySize = 12

[HeadTracker]
HistoryDepth = 2000
25 changes: 25 additions & 0 deletions core/chains/evm/config/toml/defaults/XLayer_Sepolia.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
ChainID = '195'
ChainType = 'xlayer'
FinalityDepth = 500
NoNewHeadsThreshold = '12m'
MinIncomingConfirmations = 1
LogPollInterval = '30s'
RPCBlockQueryDelay = 15
RPCDefaultBatchSize = 100

[OCR]
ContractConfirmations = 1

[Transactions]
ResendAfterThreshold = '3m'

[GasEstimator]
PriceMin = '1 mwei'
BumpPercent = 40
BumpMin = '20 mwei'

[GasEstimator.BlockHistory]
BlockHistorySize = 12

[HeadTracker]
HistoryDepth = 2000
5 changes: 5 additions & 0 deletions core/chains/evm/gas/block_history_estimator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,11 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) {
cfg.ChainTypeF = string(config.ChainXDai)
bhe.Recalculate(cltest.Head(0))
require.Equal(t, assets.NewWeiI(80), gas.GetGasPrice(bhe))

// And for X Layer
cfg.ChainTypeF = string(config.ChainXLayer)
bhe.Recalculate(cltest.Head(0))
require.Equal(t, assets.NewWeiI(80), gas.GetGasPrice(bhe))
})

t.Run("handles unreasonably large gas prices (larger than a 64 bit int can hold)", func(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions core/chains/evm/gas/chain_specific.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
// chainSpecificIsUsable allows for additional logic specific to a particular
// Config that determines whether a transaction should be used for gas estimation
func chainSpecificIsUsable(tx evmtypes.Transaction, baseFee *assets.Wei, chainType config.ChainType, minGasPriceWei *assets.Wei) bool {
if chainType == config.ChainGnosis || chainType == config.ChainXDai {
if chainType == config.ChainGnosis || chainType == config.ChainXDai || chainType == config.ChainXLayer {
// GasPrice 0 on most chains is great since it indicates cheap/free transactions.
// However, Gnosis reserves a special type of "bridge" transaction with 0 gas
// However, Gnosis and XLayer reserve a special type of "bridge" transaction with 0 gas
// price that is always processed at top priority. Ordinary transactions
// must be priced at least 1GWei, so we have to discard anything priced
// below that (unless the contract is whitelisted).
Expand Down
2 changes: 1 addition & 1 deletion core/config/docs/chains-evm.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ BlockBackfillDepth = 10 # Default
# BlockBackfillSkip enables skipping of very long backfills.
BlockBackfillSkip = false # Default
# ChainType is automatically detected from chain ID. Set this to force a certain chain type regardless of chain ID.
# Available types: `arbitrum`, `celo`, `gnosis`, `kroma`, `metis`, `optimismBedrock`, `scroll`, `wemix`, `zksync`
# Available types: `arbitrum`, `celo`, `gnosis`, `kroma`, `metis`, `optimismBedrock`, `scroll`, `wemix`, `xlayer`, `zksync`
#
# `xdai` has been deprecated and will be removed in v2.13.0, use `gnosis` instead.
ChainType = 'arbitrum' # Example
Expand Down
4 changes: 2 additions & 2 deletions core/services/chainlink/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1264,7 +1264,7 @@ func TestConfig_Validate(t *testing.T) {
- 1: 6 errors:
- ChainType: invalid value (Foo): must not be set with this chain id
- Nodes: missing: must have at least one node
- ChainType: invalid value (Foo): must be one of arbitrum, celo, gnosis, kroma, metis, optimismBedrock, scroll, wemix, zksync or omitted
- ChainType: invalid value (Foo): must be one of arbitrum, celo, gnosis, kroma, metis, optimismBedrock, scroll, wemix, xlayer, zksync or omitted
- HeadTracker.HistoryDepth: invalid value (30): must be equal to or greater than FinalityDepth
- GasEstimator: 2 errors:
- FeeCapDefault: invalid value (101 wei): must be equal to PriceMax (99 wei) since you are using FixedPrice estimation with gas bumping disabled in EIP1559 mode - PriceMax will be used as the FeeCap for transactions instead of FeeCapDefault
Expand All @@ -1273,7 +1273,7 @@ func TestConfig_Validate(t *testing.T) {
- 2: 5 errors:
- ChainType: invalid value (Arbitrum): only "optimismBedrock" can be used with this chain id
- Nodes: missing: must have at least one node
- ChainType: invalid value (Arbitrum): must be one of arbitrum, celo, gnosis, kroma, metis, optimismBedrock, scroll, wemix, zksync or omitted
- ChainType: invalid value (Arbitrum): must be one of arbitrum, celo, gnosis, kroma, metis, optimismBedrock, scroll, wemix, xlayer, zksync or omitted
- FinalityDepth: invalid value (0): must be greater than or equal to 1
- MinIncomingConfirmations: invalid value (0): must be greater than or equal to 1
- 3.Nodes: 5 errors:
Expand Down
2 changes: 1 addition & 1 deletion core/services/ocr/contract_tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ func (t *OCRContractTracker) LatestBlockHeight(ctx context.Context) (blockheight
// care about the block height; we have no way of getting the L1 block
// height anyway
return 0, nil
case "", config.ChainArbitrum, config.ChainCelo, config.ChainGnosis, config.ChainKroma, config.ChainOptimismBedrock, config.ChainScroll, config.ChainWeMix, config.ChainXDai, config.ChainZkSync:
case "", config.ChainArbitrum, config.ChainCelo, config.ChainGnosis, config.ChainKroma, config.ChainOptimismBedrock, config.ChainScroll, config.ChainWeMix, config.ChainXDai, config.ChainXLayer, config.ChainZkSync:
// continue
}
latestBlockHeight := t.getLatestBlockHeight()
Expand Down
2 changes: 1 addition & 1 deletion core/services/ocrcommon/block_translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func NewBlockTranslator(cfg Config, client evmclient.Client, lggr logger.Logger)
switch cfg.ChainType() {
case config.ChainArbitrum:
return NewArbitrumBlockTranslator(client, lggr)
case "", config.ChainCelo, config.ChainGnosis, config.ChainKroma, config.ChainMetis, config.ChainOptimismBedrock, config.ChainScroll, config.ChainWeMix, config.ChainXDai, config.ChainZkSync:
case "", config.ChainCelo, config.ChainGnosis, config.ChainKroma, config.ChainMetis, config.ChainOptimismBedrock, config.ChainScroll, config.ChainWeMix, config.ChainXDai, config.ChainXLayer, config.ChainZkSync:
fallthrough
default:
return &l1BlockTranslator{}
Expand Down
172 changes: 171 additions & 1 deletion docs/CONFIG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3005,6 +3005,176 @@ GasLimit = 5400000

</p></details>

<details><summary>XLayer Sepolia (195)</summary><p>

```toml
AutoCreateKey = true
BlockBackfillDepth = 10
BlockBackfillSkip = false
ChainType = 'xlayer'
FinalityDepth = 500
FinalityTagEnabled = false
LogBackfillBatchSize = 1000
LogPollInterval = '30s'
LogKeepBlocksDepth = 100000
LogPrunePageSize = 0
BackupLogPollerBlockDelay = 100
MinIncomingConfirmations = 1
MinContractPayment = '0.00001 link'
NonceAutoSync = true
NoNewHeadsThreshold = '12m0s'
RPCDefaultBatchSize = 100
RPCBlockQueryDelay = 15

[Transactions]
ForwardersEnabled = false
MaxInFlight = 16
MaxQueued = 250
ReaperInterval = '1h0m0s'
ReaperThreshold = '168h0m0s'
ResendAfterThreshold = '3m0s'

[BalanceMonitor]
Enabled = true

[GasEstimator]
Mode = 'BlockHistory'
PriceDefault = '20 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
PriceMin = '1 mwei'
LimitDefault = 500000
LimitMax = 500000
LimitMultiplier = '1'
LimitTransfer = 21000
BumpMin = '20 mwei'
BumpPercent = 40
BumpThreshold = 3
EIP1559DynamicFees = false
FeeCapDefault = '100 gwei'
TipCapDefault = '1 wei'
TipCapMin = '1 wei'

[GasEstimator.BlockHistory]
BatchSize = 25
BlockHistorySize = 12
CheckInclusionBlocks = 12
CheckInclusionPercentile = 90
TransactionPercentile = 60

[HeadTracker]
HistoryDepth = 2000
MaxBufferSize = 3
SamplingInterval = '1s'

[NodePool]
PollFailureThreshold = 5
PollInterval = '10s'
SelectionMode = 'HighestHead'
SyncThreshold = 5
LeaseDuration = '0s'
NodeIsSyncingEnabled = false
FinalizedBlockPollInterval = '5s'

[OCR]
ContractConfirmations = 1
ContractTransmitterTransmitTimeout = '10s'
DatabaseTimeout = '10s'
DeltaCOverride = '168h0m0s'
DeltaCJitterOverride = '1h0m0s'
ObservationGracePeriod = '1s'

[OCR2]
[OCR2.Automation]
GasLimit = 5400000
```

</p></details>

<details><summary>XLayer Mainnet (196)</summary><p>

```toml
AutoCreateKey = true
BlockBackfillDepth = 10
BlockBackfillSkip = false
ChainType = 'xlayer'
FinalityDepth = 500
FinalityTagEnabled = false
LogBackfillBatchSize = 1000
LogPollInterval = '30s'
LogKeepBlocksDepth = 100000
LogPrunePageSize = 0
BackupLogPollerBlockDelay = 100
MinIncomingConfirmations = 1
MinContractPayment = '0.00001 link'
NonceAutoSync = true
NoNewHeadsThreshold = '6m0s'
RPCDefaultBatchSize = 100
RPCBlockQueryDelay = 15

[Transactions]
ForwardersEnabled = false
MaxInFlight = 16
MaxQueued = 250
ReaperInterval = '1h0m0s'
ReaperThreshold = '168h0m0s'
ResendAfterThreshold = '3m0s'

[BalanceMonitor]
Enabled = true

[GasEstimator]
Mode = 'BlockHistory'
PriceDefault = '20 gwei'
PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
PriceMin = '100 mwei'
LimitDefault = 500000
LimitMax = 500000
LimitMultiplier = '1'
LimitTransfer = 21000
BumpMin = '100 mwei'
BumpPercent = 40
BumpThreshold = 3
EIP1559DynamicFees = false
FeeCapDefault = '100 gwei'
TipCapDefault = '1 wei'
TipCapMin = '1 wei'

[GasEstimator.BlockHistory]
BatchSize = 25
BlockHistorySize = 12
CheckInclusionBlocks = 12
CheckInclusionPercentile = 90
TransactionPercentile = 60

[HeadTracker]
HistoryDepth = 2000
MaxBufferSize = 3
SamplingInterval = '1s'

[NodePool]
PollFailureThreshold = 5
PollInterval = '10s'
SelectionMode = 'HighestHead'
SyncThreshold = 5
LeaseDuration = '0s'
NodeIsSyncingEnabled = false
FinalizedBlockPollInterval = '5s'

[OCR]
ContractConfirmations = 1
ContractTransmitterTransmitTimeout = '10s'
DatabaseTimeout = '10s'
DeltaCOverride = '168h0m0s'
DeltaCJitterOverride = '1h0m0s'
ObservationGracePeriod = '1s'

[OCR2]
[OCR2.Automation]
GasLimit = 5400000
```

</p></details>

<details><summary>Fantom Mainnet (250)</summary><p>

```toml
Expand Down Expand Up @@ -6606,7 +6776,7 @@ BlockBackfillSkip enables skipping of very long backfills.
ChainType = 'arbitrum' # Example
```
ChainType is automatically detected from chain ID. Set this to force a certain chain type regardless of chain ID.
Available types: `arbitrum`, `celo`, `gnosis`, `kroma`, `metis`, `optimismBedrock`, `scroll`, `wemix`, `zksync`
Available types: `arbitrum`, `celo`, `gnosis`, `kroma`, `metis`, `optimismBedrock`, `scroll`, `wemix`, `xlayer`, `zksync`

`xdai` has been deprecated and will be removed in v2.13.0, use `gnosis` instead.

Expand Down

0 comments on commit 2729ef7

Please sign in to comment.