From 85a8d09845d6bd30f62b1de4bf8c62f3a77a6c8e Mon Sep 17 00:00:00 2001
From: Simson
Date: Fri, 20 Sep 2024 23:31:52 +0530
Subject: [PATCH] Hedera int with TXM fixes & config (#14129)
* re-changes on top of develop
* Docs update
* changeset
* merged the error tests & Config fix
* Apply suggestions from code review
Co-authored-by: Jordan Krage
* added newly found error
* formatting
* formatting
* updated docs
* Updating config to run with multiple RPCs
* bump seth to v1.2.2
* updated configs
---------
Co-authored-by: Jordan Krage
Co-authored-by: davidcauchi
---
.changeset/many-lamps-rush.md | 5 +
core/chains/evm/client/errors.go | 12 +-
core/chains/evm/client/errors_test.go | 7 +
.../config/toml/defaults/Hedera_Mainnet.toml | 31 +++
.../config/toml/defaults/Hedera_Testnet.toml | 31 +++
docs/CONFIG.md | 204 ++++++++++++++++++
6 files changed, 289 insertions(+), 1 deletion(-)
create mode 100644 .changeset/many-lamps-rush.md
create mode 100644 core/chains/evm/config/toml/defaults/Hedera_Mainnet.toml
create mode 100644 core/chains/evm/config/toml/defaults/Hedera_Testnet.toml
diff --git a/.changeset/many-lamps-rush.md b/.changeset/many-lamps-rush.md
new file mode 100644
index 00000000000..93d779aec95
--- /dev/null
+++ b/.changeset/many-lamps-rush.md
@@ -0,0 +1,5 @@
+---
+"chainlink": patch
+---
+
+#added Hedera configs
diff --git a/core/chains/evm/client/errors.go b/core/chains/evm/client/errors.go
index 6882cca524f..ba13e1bfea8 100644
--- a/core/chains/evm/client/errors.go
+++ b/core/chains/evm/client/errors.go
@@ -267,6 +267,16 @@ var mantle = ClientErrors{
Fatal: regexp.MustCompile(`(: |^)'*invalid sender`),
}
+var hederaFatal = regexp.MustCompile(`(: |^)(execution reverted)(:|$) | ^Transaction gas limit '(\d+)' exceeds block gas limit '(\d+)' | ^Transaction gas limit provided '(\d+)' is insufficient of intrinsic gas required '(\d+)' | ^Oversized data:|status INVALID_SIGNATURE`)
+var hedera = ClientErrors{
+ NonceTooLow: regexp.MustCompile(`Nonce too low`),
+ NonceTooHigh: regexp.MustCompile(`Nonce too high`),
+ TerminallyUnderpriced: regexp.MustCompile(`(Gas price '(\d+)' is below configured minimum gas price '(\d+)')|(Gas price too low)`),
+ InsufficientEth: regexp.MustCompile(`Insufficient funds for transfer| failed precheck with status INSUFFICIENT_PAYER_BALANCE`),
+ ServiceUnavailable: regexp.MustCompile(`Transaction execution returns a null value for transaction`),
+ Fatal: hederaFatal,
+}
+
var gnosis = ClientErrors{
TransactionAlreadyInMempool: regexp.MustCompile(`(: |^)(alreadyknown)`),
}
@@ -278,7 +288,7 @@ var internal = ClientErrors{
TerminallyStuck: regexp.MustCompile(TerminallyStuckMsg),
}
-var clients = []ClientErrors{parity, geth, arbitrum, metis, substrate, avalanche, nethermind, harmony, besu, erigon, klaytn, celo, zkSync, zkEvm, treasure, mantle, aStar, gnosis, internal}
+var clients = []ClientErrors{parity, geth, arbitrum, metis, substrate, avalanche, nethermind, harmony, besu, erigon, klaytn, celo, zkSync, zkEvm, treasure, mantle, aStar, hedera, gnosis, internal}
// ClientErrorRegexes returns a map of compiled regexes for each error type
func ClientErrorRegexes(errsRegex config.ClientErrors) *ClientErrors {
diff --git a/core/chains/evm/client/errors_test.go b/core/chains/evm/client/errors_test.go
index e6478060917..84e518db666 100644
--- a/core/chains/evm/client/errors_test.go
+++ b/core/chains/evm/client/errors_test.go
@@ -46,6 +46,7 @@ func Test_Eth_Errors(t *testing.T) {
{"call failed: OldNonce, Current nonce: 22, nonce of rejected tx: 17", true, "Nethermind"},
{"nonce too low. allowed nonce range: 427 - 447, actual: 426", true, "zkSync"},
{"client error nonce too low", true, "tomlConfig"},
+ {"[Request ID: 2e952947-ffad-408b-aed9-35f3ed152001] Nonce too low. Provided nonce: 15, current nonce: 15", true, "hedera"},
}
for _, test := range tests {
@@ -67,6 +68,7 @@ func Test_Eth_Errors(t *testing.T) {
{"nonce too high", true, "Erigon"},
{"nonce too high. allowed nonce range: 427 - 477, actual: 527", true, "zkSync"},
{"client error nonce too high", true, "tomlConfig"},
+ {"[Request ID: 3ec591b4-9396-49f4-a03f-06c415a7cc6a] Nonce too high. Provided nonce: 16, current nonce: 15", true, "hedera"},
}
for _, test := range tests {
@@ -170,6 +172,7 @@ func Test_Eth_Errors(t *testing.T) {
{"virtual machine entered unexpected state. please contact developers and provide transaction details that caused this error. Error description: The operator included transaction with an unacceptable gas price", true, "zkSync"},
{"client error terminally underpriced", true, "tomlConfig"},
{"gas price less than block base fee", true, "aStar"},
+ {"[Request ID: e4d09e44-19a4-4eb7-babe-270db4c2ebc9] Gas price '830000000000' is below configured minimum gas price '950000000000'", true, "hedera"},
}
for _, test := range tests {
@@ -219,6 +222,8 @@ func Test_Eth_Errors(t *testing.T) {
{"client error insufficient eth", true, "tomlConfig"},
{"transaction would cause overdraft", true, "Geth"},
{"failed to forward tx to sequencer, please try again. Error message: 'insufficient funds for gas * price + value'", true, "Mantle"},
+ {"[Request ID: 9dd78806-58c8-4e6d-89a8-a60962abe705] Error invoking RPC: transaction 0.0.3041916@1717691931.680570179 failed precheck with status INSUFFICIENT_PAYER_BALANCE", true, "hedera"},
+ {"[Request ID: 6198d2a3-590f-4724-aae5-69fecead0c49] Insufficient funds for transfer", true, "hedera"},
}
for _, test := range tests {
err = evmclient.NewSendErrorS(test.message)
@@ -235,6 +240,7 @@ func Test_Eth_Errors(t *testing.T) {
{"i/o timeout", true, "Arbitrum"},
{"network is unreachable", true, "Arbitrum"},
{"client error service unavailable", true, "tomlConfig"},
+ {"[Request ID: 825608a8-fd8a-4b5b-aea7-92999509306d] Error invoking RPC: [Request ID: 825608a8-fd8a-4b5b-aea7-92999509306d] Transaction execution returns a null value for transaction", true, "hedera"},
}
for _, test := range tests {
err = evmclient.NewSendErrorS(test.message)
@@ -409,6 +415,7 @@ func Test_Eth_Errors_Fatal(t *testing.T) {
{"failed to forward tx to sequencer, please try again. Error message: 'invalid sender'", true, "Mantle"},
{"client error fatal", true, "tomlConfig"},
+ {"[Request ID: d9711488-4c1e-4af2-bc1f-7969913d7b60] Error invoking RPC: transaction 0.0.4425573@1718213476.914320044 failed precheck with status INVALID_SIGNATURE", true, "hedera"},
{"invalid chain id for signer", true, "Treasure"},
}
diff --git a/core/chains/evm/config/toml/defaults/Hedera_Mainnet.toml b/core/chains/evm/config/toml/defaults/Hedera_Mainnet.toml
new file mode 100644
index 00000000000..4d5e48816fa
--- /dev/null
+++ b/core/chains/evm/config/toml/defaults/Hedera_Mainnet.toml
@@ -0,0 +1,31 @@
+ChainID = '295'
+ChainType = 'hedera'
+# Considering the 3-5 (6 including a buffer) seconds of finality and 2 seconds block production
+# We set the depth to 6/2 = 3 blocks, setting to 10 for safety
+FinalityDepth = 10
+# Hedera has high TPS, so polling less often
+LogPollInterval = '10s'
+MinIncomingConfirmations = 1
+
+[BalanceMonitor]
+Enabled = true
+
+[GasEstimator]
+Mode = 'SuggestedPrice'
+# Since Hedera dont have mempool and there's no way for a node to front run or a user to bribe a node to submit the transaction earlier than it's consensus timestamp,
+# But they have automated congesting pricing throttling which would mean at high sustained level the gasPrice itself could be increased to prevent malicious behaviour.
+# Disabling the Bumpthreshold as TXM now implicity handles the bumping after checking on-chain nonce & re-broadcast for Hedera chain type
+BumpThreshold = 0
+BumpMin = '10 gwei'
+BumpPercent = 20
+
+[Transactions]
+# To hit throttling you'd need to maintain 15 m gas /sec over a prolonged period of time.
+# Because Hedera's block times are every 2 secs it's less less likely to happen as compared to other chains
+# Setting this to little higher even though Hedera has High TPS, We have seen 10-12s to get the trasaction mined & 20-25s incase of failures
+# Accounting for Node syncs & avoid re-sending txns before fetching the receipt, setting to 2m
+ResendAfterThreshold = '2m'
+
+
+[NodePool]
+SyncThreshold = 10
\ No newline at end of file
diff --git a/core/chains/evm/config/toml/defaults/Hedera_Testnet.toml b/core/chains/evm/config/toml/defaults/Hedera_Testnet.toml
new file mode 100644
index 00000000000..6086a43af2c
--- /dev/null
+++ b/core/chains/evm/config/toml/defaults/Hedera_Testnet.toml
@@ -0,0 +1,31 @@
+ChainID = '296'
+ChainType = 'hedera'
+# Considering the 3-5 (6 including a buffer) seconds of finality and 2 seconds block production
+# We set the depth to 6/2 = 3 blocks, setting to 10 for safety
+FinalityDepth = 10
+# Hedera has high TPS, so polling less often
+LogPollInterval = '10s'
+MinIncomingConfirmations = 1
+
+[BalanceMonitor]
+Enabled = true
+
+[GasEstimator]
+Mode = 'SuggestedPrice'
+# Since Hedera dont have mempool and there's no way for a node to front run or a user to bribe a node to submit the transaction earlier than it's consensus timestamp,
+# But they have automated congesting pricing throttling which would mean at high sustained level the gasPrice itself could be increased to prevent malicious behaviour.
+# Disabling the Bumpthreshold as TXM now implicity handles the bumping after checking on-chain nonce & re-broadcast for Hedera chain type
+BumpThreshold = 0
+BumpMin = '10 gwei'
+BumpPercent = 20
+
+[Transactions]
+# To hit throttling you'd need to maintain 15 m gas /sec over a prolonged period of time.
+# Because Hedera's block times are every 2 secs it's less less likely to happen as compared to other chains
+# Setting this to little higher even though Hedera has High TPS, We have seen 10-12s to get the trasaction mined & 20-25s incase of failures
+# Accounting for Node syncs & avoid re-sending txns before fetching the receipt, setting to 2m
+ResendAfterThreshold = '2m'
+
+
+[NodePool]
+SyncThreshold = 10
\ No newline at end of file
diff --git a/docs/CONFIG.md b/docs/CONFIG.md
index c9262577f10..c3eeaac2827 100644
--- a/docs/CONFIG.md
+++ b/docs/CONFIG.md
@@ -4000,6 +4000,210 @@ GasLimitDefault = 400000
+Hedera Mainnet (295)
+
+```toml
+AutoCreateKey = true
+BlockBackfillDepth = 10
+BlockBackfillSkip = false
+ChainType = 'hedera'
+FinalityDepth = 10
+FinalityTagEnabled = false
+LogBackfillBatchSize = 1000
+LogPollInterval = '10s'
+LogKeepBlocksDepth = 100000
+LogPrunePageSize = 0
+BackupLogPollerBlockDelay = 100
+MinIncomingConfirmations = 1
+MinContractPayment = '0.00001 link'
+NonceAutoSync = true
+NoNewHeadsThreshold = '3m0s'
+LogBroadcasterEnabled = true
+RPCDefaultBatchSize = 250
+RPCBlockQueryDelay = 1
+FinalizedBlockOffset = 0
+NoNewFinalizedHeadsThreshold = '0s'
+
+[Transactions]
+ForwardersEnabled = false
+MaxInFlight = 16
+MaxQueued = 250
+ReaperInterval = '1h0m0s'
+ReaperThreshold = '168h0m0s'
+ResendAfterThreshold = '2m0s'
+
+[Transactions.AutoPurge]
+Enabled = false
+
+[BalanceMonitor]
+Enabled = true
+
+[GasEstimator]
+Mode = 'SuggestedPrice'
+PriceDefault = '20 gwei'
+PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
+PriceMin = '1 gwei'
+LimitDefault = 500000
+LimitMax = 500000
+LimitMultiplier = '1'
+LimitTransfer = 21000
+EstimateLimit = false
+BumpMin = '10 gwei'
+BumpPercent = 20
+BumpThreshold = 0
+EIP1559DynamicFees = false
+FeeCapDefault = '100 gwei'
+TipCapDefault = '1 wei'
+TipCapMin = '1 wei'
+
+[GasEstimator.BlockHistory]
+BatchSize = 25
+BlockHistorySize = 8
+CheckInclusionBlocks = 12
+CheckInclusionPercentile = 90
+TransactionPercentile = 60
+
+[GasEstimator.FeeHistory]
+CacheTimeout = '10s'
+
+[HeadTracker]
+HistoryDepth = 100
+MaxBufferSize = 3
+SamplingInterval = '1s'
+MaxAllowedFinalityDepth = 10000
+FinalityTagBypass = true
+
+[NodePool]
+PollFailureThreshold = 5
+PollInterval = '10s'
+SelectionMode = 'HighestHead'
+SyncThreshold = 10
+LeaseDuration = '0s'
+NodeIsSyncingEnabled = false
+FinalizedBlockPollInterval = '5s'
+EnforceRepeatableRead = false
+DeathDeclarationDelay = '10s'
+
+[OCR]
+ContractConfirmations = 4
+ContractTransmitterTransmitTimeout = '10s'
+DatabaseTimeout = '10s'
+DeltaCOverride = '168h0m0s'
+DeltaCJitterOverride = '1h0m0s'
+ObservationGracePeriod = '1s'
+
+[OCR2]
+[OCR2.Automation]
+GasLimit = 5400000
+
+[Workflow]
+GasLimitDefault = 400000
+```
+
+
+
+Hedera Testnet (296)
+
+```toml
+AutoCreateKey = true
+BlockBackfillDepth = 10
+BlockBackfillSkip = false
+ChainType = 'hedera'
+FinalityDepth = 10
+FinalityTagEnabled = false
+LogBackfillBatchSize = 1000
+LogPollInterval = '10s'
+LogKeepBlocksDepth = 100000
+LogPrunePageSize = 0
+BackupLogPollerBlockDelay = 100
+MinIncomingConfirmations = 1
+MinContractPayment = '0.00001 link'
+NonceAutoSync = true
+NoNewHeadsThreshold = '3m0s'
+LogBroadcasterEnabled = true
+RPCDefaultBatchSize = 250
+RPCBlockQueryDelay = 1
+FinalizedBlockOffset = 0
+NoNewFinalizedHeadsThreshold = '0s'
+
+[Transactions]
+ForwardersEnabled = false
+MaxInFlight = 16
+MaxQueued = 250
+ReaperInterval = '1h0m0s'
+ReaperThreshold = '168h0m0s'
+ResendAfterThreshold = '2m0s'
+
+[Transactions.AutoPurge]
+Enabled = false
+
+[BalanceMonitor]
+Enabled = true
+
+[GasEstimator]
+Mode = 'SuggestedPrice'
+PriceDefault = '20 gwei'
+PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether'
+PriceMin = '1 gwei'
+LimitDefault = 500000
+LimitMax = 500000
+LimitMultiplier = '1'
+LimitTransfer = 21000
+EstimateLimit = false
+BumpMin = '10 gwei'
+BumpPercent = 20
+BumpThreshold = 0
+EIP1559DynamicFees = false
+FeeCapDefault = '100 gwei'
+TipCapDefault = '1 wei'
+TipCapMin = '1 wei'
+
+[GasEstimator.BlockHistory]
+BatchSize = 25
+BlockHistorySize = 8
+CheckInclusionBlocks = 12
+CheckInclusionPercentile = 90
+TransactionPercentile = 60
+
+[GasEstimator.FeeHistory]
+CacheTimeout = '10s'
+
+[HeadTracker]
+HistoryDepth = 100
+MaxBufferSize = 3
+SamplingInterval = '1s'
+MaxAllowedFinalityDepth = 10000
+FinalityTagBypass = true
+
+[NodePool]
+PollFailureThreshold = 5
+PollInterval = '10s'
+SelectionMode = 'HighestHead'
+SyncThreshold = 10
+LeaseDuration = '0s'
+NodeIsSyncingEnabled = false
+FinalizedBlockPollInterval = '5s'
+EnforceRepeatableRead = false
+DeathDeclarationDelay = '10s'
+
+[OCR]
+ContractConfirmations = 4
+ContractTransmitterTransmitTimeout = '10s'
+DatabaseTimeout = '10s'
+DeltaCOverride = '168h0m0s'
+DeltaCJitterOverride = '1h0m0s'
+ObservationGracePeriod = '1s'
+
+[OCR2]
+[OCR2.Automation]
+GasLimit = 5400000
+
+[Workflow]
+GasLimitDefault = 400000
+```
+
+
+
zkSync Sepolia (300)
```toml