From 2f8920085ba1266dfa64dd3b703da0453db07922 Mon Sep 17 00:00:00 2001 From: Bryan Stitt Date: Thu, 19 Jan 2023 18:08:53 -0800 Subject: [PATCH] configurable gas buffer --- TODO.md | 1 + web3_proxy/src/app/mod.rs | 36 ++++++++++++----------- web3_proxy/src/bin/web3_proxy_cli/main.rs | 17 +++++++++-- web3_proxy/src/config.rs | 7 +++++ 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/TODO.md b/TODO.md index 693b2179..8574253a 100644 --- a/TODO.md +++ b/TODO.md @@ -308,6 +308,7 @@ These are not yet ordered. There might be duplicates. We might not actually need - [x] retry another server if we get a jsonrpc response error about rate limits - [x] major refactor to only use backup servers when absolutely necessary - [x] remove allowed lag +- [x] configurable gas buffer. default to the larger of 25k or 25% on polygon to work around erigon bug - [-] proxy mode for benchmarking all backends - [-] proxy mode for sending to multiple backends - [-] let users choose a % of reverts to log (or maybe x/second). someone like curve logging all reverts will be a BIG database very quickly diff --git a/web3_proxy/src/app/mod.rs b/web3_proxy/src/app/mod.rs index 81968a6b..2db6fe52 100644 --- a/web3_proxy/src/app/mod.rs +++ b/web3_proxy/src/app/mod.rs @@ -25,6 +25,7 @@ use entities::sea_orm_active_enums::LogLevel; use entities::user; use ethers::core::utils::keccak256; use ethers::prelude::{Address, Block, Bytes, Transaction, TxHash, H256, U64}; +use ethers::types::U256; use ethers::utils::rlp::{Decodable, Rlp}; use futures::future::join_all; use futures::stream::{FuturesUnordered, StreamExt}; @@ -1119,19 +1120,14 @@ impl Web3ProxyApp { // TODO: eth_sendPrivateTransaction (https://docs.flashbots.net/flashbots-auction/searchers/advanced/rpc-endpoint#eth_sendprivatetransaction) "eth_coinbase" => { // no need for serving coinbase - // we could return a per-user payment address here, but then we might leak that to dapps // no stats on this. its cheap json!(Address::zero()) } - /* - // erigon was giving bad estimates. but now it doesn't need it - // TODO: got reports of some gas estimate issue on polygon with their erc20s. maybe we do want it "eth_estimateGas" => { - // TODO: eth_estimateGas using anvil? - // TODO: modify the block requested? let mut response = self .balanced_rpcs - .try_send_best_upstream_server( + .try_proxy_connection( + proxy_mode, authorization, request, Some(&request_metadata), @@ -1139,11 +1135,9 @@ impl Web3ProxyApp { ) .await?; - let parsed_gas_estimate = if let Some(gas_estimate) = response.result.take() { - let parsed_gas_estimate: U256 = serde_json::from_str(gas_estimate.get()) - .context("gas estimate result is not an U256")?; - - parsed_gas_estimate + let mut gas_estimate: U256 = if let Some(gas_estimate) = response.result.take() { + serde_json::from_str(gas_estimate.get()) + .context("gas estimate result is not an U256")? } else { // i think this is always an error response let rpcs = request_metadata.backend_requests.lock().clone(); @@ -1151,13 +1145,21 @@ impl Web3ProxyApp { return Ok((response, rpcs)); }; - // increase by 1.01% - let parsed_gas_estimate = - parsed_gas_estimate * U256::from(101_010) / U256::from(100_000); + let gas_increase = + if let Some(gas_increase_percent) = self.config.gas_increase_percent { + let gas_increase = gas_estimate * gas_increase_percent / U256::from(100); - json!(parsed_gas_estimate) + let min_gas_increase = self.config.gas_increase_min.unwrap_or_default(); + + gas_increase.max(min_gas_increase) + } else { + self.config.gas_increase_min.unwrap_or_default() + }; + + gas_estimate += gas_increase; + + json!(gas_estimate) } - */ // TODO: eth_gasPrice that does awesome magic to predict the future "eth_hashrate" => { // no stats on this. its cheap diff --git a/web3_proxy/src/bin/web3_proxy_cli/main.rs b/web3_proxy/src/bin/web3_proxy_cli/main.rs index a99ea54d..e542fd32 100644 --- a/web3_proxy/src/bin/web3_proxy_cli/main.rs +++ b/web3_proxy/src/bin/web3_proxy_cli/main.rs @@ -16,6 +16,7 @@ mod user_import; use anyhow::Context; use argh::FromArgs; +use ethers::types::U256; use log::{info, warn}; use std::{ fs, @@ -127,7 +128,10 @@ fn main() -> anyhow::Result<()> { .context(format!("checking for config at {}", top_config_path))?; let top_config: String = fs::read_to_string(top_config_path)?; - let top_config: TopConfig = toml::from_str(&top_config)?; + let mut top_config: TopConfig = toml::from_str(&top_config)?; + + // TODO: this doesn't seem to do anything + proctitle::set_title(format!("web3_proxy-{}", top_config.app.chain_id)); if cli_config.db_url.is_none() { cli_config.db_url = top_config.app.db_url.clone(); @@ -137,8 +141,15 @@ fn main() -> anyhow::Result<()> { cli_config.sentry_url = Some(sentry_url); } - // TODO: this doesn't seem to do anything - proctitle::set_title(format!("web3_proxy-{}", top_config.app.chain_id)); + if top_config.app.chain_id == 137 { + if top_config.app.gas_increase_min.is_none() { + top_config.app.gas_increase_min = Some(U256::from(25_000)); + } + + if top_config.app.gas_increase_percent.is_none() { + top_config.app.gas_increase_percent = Some(U256::from(25)); + } + } Some(top_config) } else { diff --git a/web3_proxy/src/config.rs b/web3_proxy/src/config.rs index 397a9c60..67f48870 100644 --- a/web3_proxy/src/config.rs +++ b/web3_proxy/src/config.rs @@ -4,6 +4,7 @@ use crate::rpcs::request::OpenRequestHandleMetrics; use crate::{app::AnyhowJoinHandle, rpcs::blockchain::ArcBlock}; use argh::FromArgs; use ethers::prelude::TxHash; +use ethers::types::U256; use hashbrown::HashMap; use log::warn; use migration::sea_orm::DatabaseConnection; @@ -90,6 +91,12 @@ pub struct AppConfig { /// None = allow all requests pub default_user_max_requests_per_period: Option, + /// minimum amount to increase eth_estimateGas results + pub gas_increase_min: Option, + + /// percentage to increase eth_estimateGas results. 100 == 100% + pub gas_increase_percent: Option, + /// Restrict user registration. /// None = no code needed pub invite_code: Option,