From d044474a45d4a136de544f607479c3afd9cab2f8 Mon Sep 17 00:00:00 2001 From: shekohex Date: Wed, 5 Apr 2023 21:28:01 +0200 Subject: [PATCH] feat: Improve the `GasOracle` usage (#414) --- Cargo.lock | 152 +++++++++++++---------- Cargo.toml | 3 +- crates/relayer-config/src/lib.rs | 6 + crates/relayer-context/src/lib.rs | 55 +++++--- crates/relayer-utils/src/lib.rs | 2 + crates/tx-relay/src/evm/fees.rs | 64 +++++----- services/light-client-relayer/Cargo.toml | 2 +- 7 files changed, 164 insertions(+), 120 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 75d6933cb..68bff999e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1115,9 +1115,9 @@ dependencies = [ [[package]] name = "coins-bip39" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb68f3b6c3fee83828ecd8d463f360a397c32aaeb35bd931c01e5ddf5631c69" +checksum = "ad2a68a46b9d8cc90484f0689adc0e4c890eb215bf698ae52e5235bb88f40be7" dependencies = [ "bitvec 0.17.4", "coins-bip32", @@ -1591,9 +1591,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc906908ea6458456e5eaa160a9c08543ec3d1e6f71e2235cedd660cb65f9df0" +checksum = "19c5cb402c5c958281c7c0702edea7b780d03b86b606497ca3a10fcd3fc393ac" dependencies = [ "const-oid", "zeroize", @@ -1654,6 +1654,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.4", + "const-oid", "crypto-common", "subtle", ] @@ -1754,14 +1755,15 @@ dependencies = [ [[package]] name = "ecdsa" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644d3b8674a5fc5b929ae435bca85c2323d85ccb013a5509c2ac9ee11a6284ba" +checksum = "a64d2e9c561b39b2de83c0387baffecfbc62ad116c4fc8f4e5b040b8e0737d7c" dependencies = [ - "der 0.7.1", - "elliptic-curve 0.13.2", + "der 0.7.2", + "digest 0.10.6", + "elliptic-curve 0.13.3", "rfc6979 0.4.0", - "signature 2.0.0", + "signature 2.1.0", ] [[package]] @@ -1828,9 +1830,9 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea5a92946e8614bb585254898bb7dd1ddad241ace60c52149e3765e34cc039d" +checksum = "22cdacd4d6ed3f9b98680b679c0e52a823b8a2c7a97358d508fe247f2180c282" dependencies = [ "base16ct 0.2.0", "crypto-bigint 0.5.1", @@ -1838,7 +1840,7 @@ dependencies = [ "ff 0.13.0", "generic-array 0.14.7", "group 0.13.0", - "pkcs8 0.10.1", + "pkcs8 0.10.2", "rand_core 0.6.4", "sec1 0.7.1", "subtle", @@ -1987,7 +1989,7 @@ dependencies = [ "tokio 1.27.0", "toml 0.5.11", "tree_hash 0.4.1 (git+https://github.com/webb-tools/pallet-eth2-light-client)", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.21", "webb-proposals", "webb-relayer-types 0.1.0 (git+https://github.com/webb-tools/relayer.git)", "webb-relayer-utils 0.1.0 (git+https://github.com/webb-tools/relayer.git)", @@ -2134,7 +2136,7 @@ dependencies = [ "tree_hash 0.4.1 (git+https://github.com/webb-tools/pallet-eth2-light-client)", "types", "warp", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.21", "webb-proposals", "webb-relayer-utils 0.1.0 (git+https://github.com/webb-tools/relayer.git)", ] @@ -2268,7 +2270,7 @@ dependencies = [ [[package]] name = "ethers" version = "2.0.2" -source = "git+https://github.com/gakonst/ethers-rs#d80e82a561ff714d1fa10c05786bb6fe124edbf0" +source = "git+https://github.com/gakonst/ethers-rs#1dd35458695e2b967d4c2ff278cc8d0eaadcc9fb" dependencies = [ "ethers-addressbook 2.0.2 (git+https://github.com/gakonst/ethers-rs)", "ethers-contract 2.0.2 (git+https://github.com/gakonst/ethers-rs)", @@ -2295,7 +2297,7 @@ dependencies = [ [[package]] name = "ethers-addressbook" version = "2.0.2" -source = "git+https://github.com/gakonst/ethers-rs#d80e82a561ff714d1fa10c05786bb6fe124edbf0" +source = "git+https://github.com/gakonst/ethers-rs#1dd35458695e2b967d4c2ff278cc8d0eaadcc9fb" dependencies = [ "ethers-core 2.0.2 (git+https://github.com/gakonst/ethers-rs)", "once_cell", @@ -2325,7 +2327,7 @@ dependencies = [ [[package]] name = "ethers-contract" version = "2.0.2" -source = "git+https://github.com/gakonst/ethers-rs#d80e82a561ff714d1fa10c05786bb6fe124edbf0" +source = "git+https://github.com/gakonst/ethers-rs#1dd35458695e2b967d4c2ff278cc8d0eaadcc9fb" dependencies = [ "ethers-contract-abigen 2.0.2 (git+https://github.com/gakonst/ethers-rs)", "ethers-contract-derive 2.0.2 (git+https://github.com/gakonst/ethers-rs)", @@ -2370,7 +2372,7 @@ dependencies = [ [[package]] name = "ethers-contract-abigen" version = "2.0.2" -source = "git+https://github.com/gakonst/ethers-rs#d80e82a561ff714d1fa10c05786bb6fe124edbf0" +source = "git+https://github.com/gakonst/ethers-rs#1dd35458695e2b967d4c2ff278cc8d0eaadcc9fb" dependencies = [ "Inflector", "dunce", @@ -2410,7 +2412,7 @@ dependencies = [ [[package]] name = "ethers-contract-derive" version = "2.0.2" -source = "git+https://github.com/gakonst/ethers-rs#d80e82a561ff714d1fa10c05786bb6fe124edbf0" +source = "git+https://github.com/gakonst/ethers-rs#1dd35458695e2b967d4c2ff278cc8d0eaadcc9fb" dependencies = [ "ethers-contract-abigen 2.0.2 (git+https://github.com/gakonst/ethers-rs)", "ethers-core 2.0.2 (git+https://github.com/gakonst/ethers-rs)", @@ -2431,7 +2433,7 @@ dependencies = [ "cargo_metadata", "chrono", "convert_case 0.6.0", - "elliptic-curve 0.13.2", + "elliptic-curve 0.13.3", "ethabi", "generic-array 0.14.7", "getrandom 0.2.8", @@ -2456,14 +2458,14 @@ dependencies = [ [[package]] name = "ethers-core" version = "2.0.2" -source = "git+https://github.com/gakonst/ethers-rs#d80e82a561ff714d1fa10c05786bb6fe124edbf0" +source = "git+https://github.com/gakonst/ethers-rs#1dd35458695e2b967d4c2ff278cc8d0eaadcc9fb" dependencies = [ "arrayvec 0.7.2", "bytes 1.4.0", "cargo_metadata", "chrono", "convert_case 0.6.0", - "elliptic-curve 0.13.2", + "elliptic-curve 0.13.3", "ethabi", "generic-array 0.14.7", "getrandom 0.2.8", @@ -2505,7 +2507,7 @@ dependencies = [ [[package]] name = "ethers-etherscan" version = "2.0.2" -source = "git+https://github.com/gakonst/ethers-rs#d80e82a561ff714d1fa10c05786bb6fe124edbf0" +source = "git+https://github.com/gakonst/ethers-rs#1dd35458695e2b967d4c2ff278cc8d0eaadcc9fb" dependencies = [ "ethers-core 2.0.2 (git+https://github.com/gakonst/ethers-rs)", "ethers-solc 2.0.2 (git+https://github.com/gakonst/ethers-rs)", @@ -2548,7 +2550,7 @@ dependencies = [ [[package]] name = "ethers-middleware" version = "2.0.2" -source = "git+https://github.com/gakonst/ethers-rs#d80e82a561ff714d1fa10c05786bb6fe124edbf0" +source = "git+https://github.com/gakonst/ethers-rs#1dd35458695e2b967d4c2ff278cc8d0eaadcc9fb" dependencies = [ "async-trait", "auto_impl", @@ -2610,7 +2612,7 @@ dependencies = [ [[package]] name = "ethers-providers" version = "2.0.2" -source = "git+https://github.com/gakonst/ethers-rs#d80e82a561ff714d1fa10c05786bb6fe124edbf0" +source = "git+https://github.com/gakonst/ethers-rs#1dd35458695e2b967d4c2ff278cc8d0eaadcc9fb" dependencies = [ "async-trait", "auto_impl", @@ -2651,7 +2653,7 @@ dependencies = [ "async-trait", "coins-bip32", "coins-bip39", - "elliptic-curve 0.13.2", + "elliptic-curve 0.13.3", "eth-keystore", "ethers-core 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex", @@ -2664,12 +2666,12 @@ dependencies = [ [[package]] name = "ethers-signers" version = "2.0.2" -source = "git+https://github.com/gakonst/ethers-rs#d80e82a561ff714d1fa10c05786bb6fe124edbf0" +source = "git+https://github.com/gakonst/ethers-rs#1dd35458695e2b967d4c2ff278cc8d0eaadcc9fb" dependencies = [ "async-trait", "coins-bip32", "coins-bip39", - "elliptic-curve 0.13.2", + "elliptic-curve 0.13.3", "eth-keystore", "ethers-core 2.0.2 (git+https://github.com/gakonst/ethers-rs)", "hex", @@ -2713,7 +2715,7 @@ dependencies = [ [[package]] name = "ethers-solc" version = "2.0.2" -source = "git+https://github.com/gakonst/ethers-rs#d80e82a561ff714d1fa10c05786bb6fe124edbf0" +source = "git+https://github.com/gakonst/ethers-rs#1dd35458695e2b967d4c2ff278cc8d0eaadcc9fb" dependencies = [ "cfg-if 1.0.0", "dunce", @@ -3665,13 +3667,13 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" dependencies = [ "hermit-abi 0.3.1", "libc", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -3839,11 +3841,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "955890845095ccf31ef83ad41a05aabb4d8cc23dc3cac5a9f5c89cf26dd0da75" dependencies = [ "cfg-if 1.0.0", - "ecdsa 0.16.2", - "elliptic-curve 0.13.2", + "ecdsa 0.16.3", + "elliptic-curve 0.13.3", "once_cell", "sha2 0.10.6", - "signature 2.0.0", + "signature 2.1.0", ] [[package]] @@ -4876,12 +4878,12 @@ dependencies = [ [[package]] name = "pkcs8" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d2820d87d2b008616e5c27212dd9e0e694fb4c6b522de06094106813328cb49" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.1", - "spki 0.7.0", + "der 0.7.2", + "spki 0.7.1", ] [[package]] @@ -5712,9 +5714,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48518a2b5775ba8ca5b46596aae011caa431e6ce7e4a67ead66d92f08884220e" dependencies = [ "base16ct 0.2.0", - "der 0.7.1", + "der 0.7.2", "generic-array 0.14.7", - "pkcs8 0.10.1", + "pkcs8 0.10.2", "subtle", "zeroize", ] @@ -6035,9 +6037,9 @@ dependencies = [ [[package]] name = "signature" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fe458c98333f9c8152221191a77e2a44e8325d0193484af2e9421a53019e57d" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" dependencies = [ "digest 0.10.6", "rand_core 0.6.4", @@ -6494,12 +6496,12 @@ dependencies = [ [[package]] name = "spki" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0445c905640145c7ea8c1993555957f65e7c46d0535b91ba501bc9bfc85522f" +checksum = "37a5be806ab6f127c3da44b7378837ebf01dadca8510a0e572460216b228bd0e" dependencies = [ "base64ct", - "der 0.7.1", + "der 0.7.2", ] [[package]] @@ -7940,15 +7942,18 @@ dependencies = [ [[package]] name = "webb" -version = "0.5.21" -source = "git+https://github.com/webb-tools/webb-rs#1ed2db6eaf930f94774af0293ac751707af825b0" +version = "0.5.22" +source = "git+https://github.com/webb-tools/webb-rs#ce757c52c404c4ebe1499712429ca858bff200f0" dependencies = [ "async-trait", "ethers 2.0.2 (git+https://github.com/gakonst/ethers-rs)", "hex", + "parity-scale-codec", "rand 0.8.5", + "scale-info", "serde", "serde_json", + "subxt", "tempfile", "thiserror", ] @@ -7968,7 +7973,7 @@ dependencies = [ "tempfile", "tokio 1.27.0", "tracing", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-relayer", "webb-relayer-config", "webb-relayer-context", @@ -7989,7 +7994,7 @@ dependencies = [ "sp-core", "tokio 1.27.0", "typed-builder 0.12.0", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-proposals", "webb-relayer-config", "webb-relayer-utils 0.1.0", @@ -8007,7 +8012,7 @@ dependencies = [ "tokio 1.27.0", "tracing", "tracing-test", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-proposals", "webb-relayer-config", "webb-relayer-context", @@ -8026,7 +8031,7 @@ dependencies = [ "sled", "tokio 1.27.0", "tracing", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-event-watcher-traits", "webb-proposals", "webb-relayer-config", @@ -8053,7 +8058,7 @@ dependencies = [ "sled", "tokio 1.27.0", "tracing", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-bridge-registry-backends", "webb-event-watcher-traits", "webb-proposal-signing-backends", @@ -8075,7 +8080,7 @@ dependencies = [ "sp-core", "tokio 1.27.0", "tracing", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-event-watcher-traits", "webb-proposal-signing-backends", "webb-proposals", @@ -8108,7 +8113,7 @@ dependencies = [ "thiserror", "tokio 1.27.0", "tracing", - "webb 0.5.21 (git+https://github.com/webb-tools/webb-rs)", + "webb 0.5.22", "webb-proposal-signing-backends", "webb-proposals", "webb-relayer", @@ -8136,7 +8141,7 @@ dependencies = [ "serde", "tokio 1.27.0", "typed-builder 0.12.0", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-relayer-store", "webb-relayer-utils 0.1.0", ] @@ -8155,7 +8160,7 @@ dependencies = [ "tokio 1.27.0", "tracing", "typed-builder 0.12.0", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-proposals", "webb-relayer-store", "webb-relayer-types 0.1.0", @@ -8198,7 +8203,7 @@ dependencies = [ "tower-http", "tracing", "url", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-bridge-registry-backends", "webb-event-watcher-traits", "webb-ew-dkg", @@ -8234,7 +8239,7 @@ dependencies = [ "tracing", "tracing-subscriber 0.3.16", "url", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-proposals", "webb-relayer-store", "webb-relayer-types 0.1.0", @@ -8248,7 +8253,7 @@ dependencies = [ "native-tls", "sp-core", "tokio 1.27.0", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-price-oracle-backends", "webb-relayer-config", "webb-relayer-store", @@ -8262,7 +8267,7 @@ dependencies = [ "native-tls", "serde", "tokio 1.27.0", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-relayer-tx-relay-utils", ] @@ -8281,7 +8286,7 @@ dependencies = [ "tokio 1.27.0", "tokio-stream", "tracing", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-proposals", "webb-relayer-config", "webb-relayer-context", @@ -8303,7 +8308,7 @@ dependencies = [ "sled", "tempfile", "tracing", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-proposals", "webb-relayer-utils 0.1.0", ] @@ -8322,7 +8327,7 @@ dependencies = [ "sp-runtime", "tokio 1.27.0", "tracing", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-relayer-context", "webb-relayer-store", "webb-relayer-types 0.1.0", @@ -8341,7 +8346,7 @@ dependencies = [ "serde", "tokio 1.27.0", "tracing", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-price-oracle-backends", "webb-proposals", "webb-relayer-config", @@ -8369,7 +8374,7 @@ dependencies = [ "tiny-bip39", "tracing", "url", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", ] [[package]] @@ -8384,7 +8389,7 @@ dependencies = [ "tiny-bip39", "tracing", "url", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.21", ] [[package]] @@ -8408,7 +8413,7 @@ dependencies = [ "sled", "thiserror", "url", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.22", "webb-proposals", ] @@ -8433,7 +8438,7 @@ dependencies = [ "sled", "thiserror", "url", - "webb 0.5.21 (registry+https://github.com/rust-lang/crates.io-index)", + "webb 0.5.21", "webb-proposals", ] @@ -8543,6 +8548,15 @@ dependencies = [ "windows-targets 0.42.2", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + [[package]] name = "windows-targets" version = "0.42.2" diff --git a/Cargo.toml b/Cargo.toml index d2f4fa448..363d25909 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,8 @@ tokio = { version = "^1", features = ["full"] } config = { version = "0.13", default-features = false, features = ["toml", "json"] } serde_json = { version = "^1", default-features = false } paw = { version = "^1.0" } -webb = { version = "0.5.21", default-features = false } +# webb = { version = "0.5.21", default-features = false } +webb = { version = "0.5.22", git = "https://github.com/webb-tools/webb-rs", default-features = false } sp-core = { version = "16.0.0", default-features = false } sp-runtime = { version = "18.0.0", default-features = false } # Used by ethers (but we need it to be vendored with the lib). diff --git a/crates/relayer-config/src/lib.rs b/crates/relayer-config/src/lib.rs index db5c5cbb4..7ac04e371 100644 --- a/crates/relayer-config/src/lib.rs +++ b/crates/relayer-config/src/lib.rs @@ -175,6 +175,12 @@ pub struct EtherscanApiConfig { /// A wrapper type around the `String` to allow reading it from the env. #[serde(skip_serializing)] pub api_key: EtherscanApiKey, + /// An optional URL to use for the Etherscan API instead of the default. + /// + /// This is useful for testing against a local Etherscan API. + /// Or in case of testnets, the Etherscan GasOracle API is not available. + /// So we can use the mainnet API URL to get the gas price. + pub api_url: Option, } /// TxQueueConfig is the configuration for the TxQueue. diff --git a/crates/relayer-context/src/lib.rs b/crates/relayer-context/src/lib.rs index 6fd92d2e9..71d9f2d0b 100644 --- a/crates/relayer-context/src/lib.rs +++ b/crates/relayer-context/src/lib.rs @@ -22,6 +22,7 @@ use std::{collections::HashMap, convert::TryFrom}; use tokio::sync::{broadcast, Mutex}; +use webb::evm::ethers; #[cfg(feature = "evm")] use webb::evm::ethers::core::k256::SecretKey; #[cfg(feature = "evm")] @@ -29,6 +30,10 @@ use webb::evm::ethers::prelude::*; #[cfg(feature = "substrate")] use sp_core::sr25519::Pair as Sr25519Pair; +use webb::evm::ethers::middleware::gas_oracle::{ + Cache as CachedGasOracle, Etherscan as EtherscanGasOracle, + Median as GasOracleMedian, ProviderOracle, +}; #[cfg(feature = "substrate")] use webb::substrate::subxt; @@ -58,7 +63,7 @@ pub struct RelayerContext { /// Price backend for fetching prices. price_oracle: Arc, /// Hashmap of - etherscan_clients: HashMap, + etherscan_clients: HashMap, } impl RelayerContext { @@ -92,9 +97,16 @@ impl RelayerContext { .build(); let price_oracle = Arc::new(price_oracle); let mut etherscan_clients: HashMap = HashMap::new(); - for (chain, etherscan_config) in config.evm_etherscan.iter() { - let client = - Client::new(*chain, etherscan_config.api_key.to_string())?; + for (chain, etherscan_config) in &config.evm_etherscan { + let client_builder = ethers::etherscan::Client::builder() + .chain(*chain)? + .with_api_key(etherscan_config.api_key.as_str()); + // if the api url is set, override the default + let client = if let Some(ref api_url) = etherscan_config.api_url { + client_builder.with_api_url(api_url.as_str())?.build()? + } else { + client_builder.build()? + }; etherscan_clients.insert(etherscan_config.chain_id, client); } Ok(Self { @@ -214,18 +226,33 @@ impl RelayerContext { self.price_oracle.clone() } - /// Returns API client for https://etherscan.io/ - pub fn etherscan_client( + /// Returns a gas oracle for the given chain. + pub async fn gas_oracle( &self, chain_id: u32, - ) -> webb_relayer_utils::Result<&Client> { - let client = - self.etherscan_clients.get(&chain_id).ok_or_else(|| { - webb_relayer_utils::Error::EtherscanConfigNotFound { - chain_id: chain_id.to_string(), - } - })?; - Ok(client) + ) -> webb_relayer_utils::Result { + let chain_provider = self.evm_provider(&chain_id.to_string()).await?; + let provider_gas_oracle = ProviderOracle::new(chain_provider); + let mut gas_oracle = GasOracleMedian::new(); + // Give only 10% of the weight to the provider gas oracle + // since it is not very accurate. + gas_oracle.add_weighted(0.1, provider_gas_oracle); + // Check if we have etherscan client for this chain + if let Some(etherscan_client) = self.etherscan_clients.get(&chain_id) { + let etherscan_gas_oracle = + EtherscanGasOracle::new(etherscan_client.clone()); + let cached = CachedGasOracle::new( + // Cache for 5 minutes to avoid hitting etherscan rate limit + Duration::from_secs(5 * 60), + etherscan_gas_oracle, + ); + // Etherscan gas oracle is more accurate than the provider gas oracle + // so give it the remaining 90% of the weight. + gas_oracle.add_weighted(0.9, cached); + } + // TODO: Add more gas oracles + + Ok(gas_oracle) } } diff --git a/crates/relayer-utils/src/lib.rs b/crates/relayer-utils/src/lib.rs index d852c53f5..51439b752 100644 --- a/crates/relayer-utils/src/lib.rs +++ b/crates/relayer-utils/src/lib.rs @@ -105,6 +105,8 @@ pub enum Error { /// Etherscan API error #[error(transparent)] Etherscan(#[from] ethers::etherscan::errors::EtherscanError), + #[error(transparent)] + GasOracle(#[from] ethers::middleware::gas_oracle::GasOracleError), /// Ether wallet errors. #[error(transparent)] EtherWalletError(#[from] ethers::signers::WalletError), diff --git a/crates/tx-relay/src/evm/fees.rs b/crates/tx-relay/src/evm/fees.rs index 7a6e386ba..86a3665a0 100644 --- a/crates/tx-relay/src/evm/fees.rs +++ b/crates/tx-relay/src/evm/fees.rs @@ -9,6 +9,7 @@ use std::sync::{Arc, Mutex}; use webb::evm::contract::protocol_solidity::{ FungibleTokenWrapperContract, OpenVAnchorContract, }; +use webb::evm::ethers::middleware::gas_oracle::GasOracle; use webb::evm::ethers::prelude::U256; use webb::evm::ethers::types::Address; use webb::evm::ethers::utils::{format_units, parse_units}; @@ -77,33 +78,27 @@ pub async fn get_fee_info( lock.get(&(vanchor, chain_id)).cloned() }; - match fee_info_cached { - // There is a cached fee info, use it - Some(mut fee_info) => { - // Need to recalculate estimated fee with the gas amount that was passed in. We use - // cached exchange rate so that this matches calculation on the client. - fee_info.estimated_fee = calculate_transaction_fee( - fee_info.gas_price, - gas_amount, - fee_info.native_token_price, - fee_info.wrapped_token_price, - fee_info.wrapped_token_decimals, - ) - .await?; - Ok(fee_info) - } - // No cached fee info, generate new one - None => { - let fee_info = - generate_fee_info(chain_id, vanchor, gas_amount, ctx).await?; + if let Some(mut fee_info) = fee_info_cached { + // Need to recalculate estimated fee with the gas amount that was passed in. We use + // cached exchange rate so that this matches calculation on the client. + fee_info.estimated_fee = calculate_transaction_fee( + fee_info.gas_price, + gas_amount, + fee_info.native_token_price, + fee_info.wrapped_token_price, + fee_info.wrapped_token_decimals, + )?; + Ok(fee_info) + } else { + let fee_info = + generate_fee_info(chain_id, vanchor, gas_amount, ctx).await?; - // Insert newly generated fee info into cache. - FEE_INFO_CACHED - .lock() - .expect("lock fee info cache mutex") - .insert((vanchor, chain_id), fee_info.clone()); - Ok(fee_info) - } + // Insert newly generated fee info into cache. + FEE_INFO_CACHED + .lock() + .expect("lock fee info cache mutex") + .insert((vanchor, chain_id), fee_info.clone()); + Ok(fee_info) } } @@ -134,6 +129,7 @@ async fn generate_fee_info( }) } }; + let wrapped_token_price = match prices.get(&wrapped_token) { Some(price) => *price, None => { @@ -143,13 +139,12 @@ async fn generate_fee_info( } }; - // Fetch native gas price estimate from etherscan.io, using "average" value - let gas_oracle = ctx - .etherscan_client(chain_id.underlying_chain_id())? - .gas_oracle() + // Fetch native gas price estimate from gas oracle, using "average" value + let gas_price = ctx + .gas_oracle(chain_id.underlying_chain_id()) + .await? + .fetch() .await?; - let gas_price_gwei = U256::from(gas_oracle.propose_gas_price); - let gas_price = parse_units(gas_price_gwei, "gwei")?.into(); let estimated_fee = calculate_transaction_fee( gas_price, @@ -157,8 +152,7 @@ async fn generate_fee_info( native_token_price, wrapped_token_price, wrapped_token_decimals, - ) - .await?; + )?; // Calculate the exchange rate from wrapped token to native token which is used for the refund. let refund_exchange_rate = parse_units( @@ -190,7 +184,7 @@ async fn generate_fee_info( /// fee in `wrappedToken` wei. This fee includes a profit for the relay of `TRANSACTION_PROFIT_USD`. /// /// The algorithm is explained at https://www.notion.so/hicommonwealth/Private-Tx-Relay-Support-v1-f5522b04d6a349aab1bbdb0dd83a7fb4#6bb2b4920e3f42d69988688c6fa54e6e -async fn calculate_transaction_fee( +fn calculate_transaction_fee( gas_price: U256, gas_amount: U256, native_token_price: f64, diff --git a/services/light-client-relayer/Cargo.toml b/services/light-client-relayer/Cargo.toml index b1dc685a8..7dd900f7e 100644 --- a/services/light-client-relayer/Cargo.toml +++ b/services/light-client-relayer/Cargo.toml @@ -39,7 +39,7 @@ backoff = { version = "0.4.0", features = ["tokio"] } tokio = { version = "^1", features = ["full"] } serde_json = { version = "^1", default-features = false } paw = { version = "^1.0", optional = true } -webb = { git = "https://github.com/webb-tools/webb-rs" , default-features = false, features = ["evm-runtime"] } +webb = { workspace = true, default-features = false, features = ["evm-runtime"] } webb-proposals = { version = "0.5.4", default-features = false, features = ["scale", "evm", "substrate"] } # Used by ethers (but we need it to be vendored with the lib). native-tls = { version = "^0.2", features = ["vendored"], optional = true }