Skip to content

Commit

Permalink
feat(Rundler): Handle standardized eth_sendRawTransactionConditional …
Browse files Browse the repository at this point in the history
…error codes (#931)
  • Loading branch information
niveda-krish authored Dec 11, 2024
1 parent 6b9a2ad commit e21dc0f
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 29 deletions.
3 changes: 2 additions & 1 deletion crates/builder/src/sender/bloxroute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ struct BloxrouteResponse {
impl From<jsonrpsee::core::ClientError> for TxSenderError {
fn from(value: jsonrpsee::core::ClientError) -> Self {
if let jsonrpsee::core::ClientError::Call(e) = &value {
if let Some(e) = super::parse_known_call_execution_failed(e.message()) {
if let Some(e) = super::parse_known_call_execution_failed(e.message(), e.code() as i64)
{
return e;
}
}
Expand Down
66 changes: 38 additions & 28 deletions crates/builder/src/sender/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ impl From<ProviderError> for TxSenderError {
ProviderError::RPC(e) => {
if let Some(e) = e.as_error_resp() {
// Client impls use different error codes, just match on the message
if let Some(e) = parse_known_call_execution_failed(&e.message) {
if let Some(e) = parse_known_call_execution_failed(&e.message, e.code) {
e
} else {
TxSenderError::Other(value.into())
Expand All @@ -257,33 +257,43 @@ impl From<ProviderError> for TxSenderError {
// Geth: https://github.com/ethereum/go-ethereum/blob/23800122b37695be50565f8221858a16ce1763db/core/txpool/errors.go#L31
// Reth: https://github.com/paradigmxyz/reth/blob/8e4a917ec1aa70b3779083454ff2d5ecf6b44168/crates/rpc/rpc-eth-types/src/error/mod.rs#L624
// Erigon: https://github.com/erigontech/erigon/blob/96fabf3fd1a4ddce26b845ffe2b6cfb50d5b4b2d/txnprovider/txpool/txpoolcfg/txpoolcfg.go#L124
fn parse_known_call_execution_failed(e: &str) -> Option<TxSenderError> {
fn parse_known_call_execution_failed(message: &str, code: i64) -> Option<TxSenderError> {
// Check error codes before checking the message
// The error code is -32003 or -32005 when condition is not met: https://eips.ethereum.org/EIPS/eip-7796
if code == -32003 || code == -32005 {
return Some(TxSenderError::ConditionNotMet);
}
// String match on the error message when an error code is not available
// DEVELOPER NOTE: ensure to put the most specific matches first
match &e.to_lowercase() {
// geth. Reth & erigon don't have similar
x if x.contains("future transaction tries to replace pending") => {
Some(TxSenderError::Rejected)
}
// geth & reth
x if x.contains("replacement transaction underpriced") => {
Some(TxSenderError::ReplacementUnderpriced)
}
// erigon
x if x.contains("could not replace existing tx") => {
Some(TxSenderError::ReplacementUnderpriced)
}
// geth, erigon, reth
x if x.contains("nonce too low") => Some(TxSenderError::NonceTooLow),
// Arbitrum conditional sender error message
x if x.contains("storage slot value condition not met") => {
Some(TxSenderError::ConditionNotMet)
}
// geth
x if x.contains("transaction underpriced") => Some(TxSenderError::Underpriced),
// reth
x if x.contains("txpool is full") => Some(TxSenderError::Underpriced),
// erigon
x if x.contains("underpriced") => Some(TxSenderError::Underpriced),
_ => None,
let lowercase_message = message.to_lowercase();
// geth. Reth & erigon don't have similar
if lowercase_message.contains("future transaction tries to replace pending") {
return Some(TxSenderError::Rejected);
}
// geth & reth
if lowercase_message.contains("replacement transaction underpriced") {
return Some(TxSenderError::ReplacementUnderpriced);
}
// erigon
if lowercase_message.contains("could not replace existing tx") {
return Some(TxSenderError::ReplacementUnderpriced);
}
// geth, erigon, reth
if lowercase_message.contains("nonce too low") {
return Some(TxSenderError::NonceTooLow);
}
// geth
if lowercase_message.contains("transaction underpriced") {
return Some(TxSenderError::Underpriced);
}
// reth
if lowercase_message.contains("txpool is full") {
return Some(TxSenderError::Underpriced);
}
// erigon
if lowercase_message.contains("underpriced") {
return Some(TxSenderError::Underpriced);
}
// No known error matched
None
}

0 comments on commit e21dc0f

Please sign in to comment.