2021-10-16 15:47:17 +00:00
|
|
|
use async_trait::async_trait;
|
2022-06-01 15:22:39 +00:00
|
|
|
use ethers_core::{types::*, utils::Anvil};
|
2023-03-01 00:26:27 +00:00
|
|
|
use ethers_etherscan::Client;
|
2020-09-24 21:33:09 +00:00
|
|
|
use ethers_middleware::gas_oracle::{
|
2022-12-18 11:45:47 +00:00
|
|
|
BlockNative, Etherchain, Etherscan, GasCategory, GasNow, GasOracle, GasOracleError,
|
|
|
|
GasOracleMiddleware, Polygon, ProviderOracle, Result,
|
2020-09-24 21:33:09 +00:00
|
|
|
};
|
|
|
|
use ethers_providers::{Http, Middleware, Provider};
|
2021-10-16 15:47:17 +00:00
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct FakeGasOracle {
|
|
|
|
gas_price: U256,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
|
|
|
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
|
|
|
impl GasOracle for FakeGasOracle {
|
2022-12-18 11:45:47 +00:00
|
|
|
async fn fetch(&self) -> Result<U256> {
|
2021-10-16 15:47:17 +00:00
|
|
|
Ok(self.gas_price)
|
|
|
|
}
|
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
async fn estimate_eip1559_fees(&self) -> Result<(U256, U256)> {
|
2021-10-16 15:47:17 +00:00
|
|
|
Err(GasOracleError::Eip1559EstimationNotSupported)
|
|
|
|
}
|
|
|
|
}
|
2020-09-24 21:33:09 +00:00
|
|
|
|
|
|
|
#[tokio::test]
|
2022-12-18 11:45:47 +00:00
|
|
|
async fn provider_using_gas_oracle() {
|
2022-06-01 15:22:39 +00:00
|
|
|
let anvil = Anvil::new().spawn();
|
2020-09-24 21:33:09 +00:00
|
|
|
|
2022-06-01 15:22:39 +00:00
|
|
|
let from = anvil.addresses()[0];
|
2020-09-24 21:33:09 +00:00
|
|
|
|
|
|
|
// connect to the network
|
2022-06-01 15:22:39 +00:00
|
|
|
let provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
|
2020-09-24 21:33:09 +00:00
|
|
|
|
|
|
|
// assign a gas oracle to use
|
2022-12-18 11:45:47 +00:00
|
|
|
let expected_gas_price = U256::from(1234567890_u64);
|
|
|
|
let gas_oracle = FakeGasOracle { gas_price: expected_gas_price };
|
|
|
|
let gas_price = gas_oracle.fetch().await.unwrap();
|
|
|
|
assert_eq!(gas_price, expected_gas_price);
|
2020-09-24 21:33:09 +00:00
|
|
|
|
|
|
|
let provider = GasOracleMiddleware::new(provider, gas_oracle);
|
|
|
|
|
|
|
|
// broadcast a transaction
|
2021-10-29 12:29:35 +00:00
|
|
|
let tx = TransactionRequest::new().from(from).to(Address::zero()).value(10000);
|
2020-09-24 21:33:09 +00:00
|
|
|
let tx_hash = provider.send_transaction(tx, None).await.unwrap();
|
|
|
|
|
2020-12-17 11:26:01 +00:00
|
|
|
let tx = provider.get_transaction(*tx_hash).await.unwrap().unwrap();
|
2021-08-12 16:01:52 +00:00
|
|
|
assert_eq!(tx.gas_price, Some(expected_gas_price));
|
2020-09-24 21:33:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test]
|
2022-12-18 11:45:47 +00:00
|
|
|
async fn provider_oracle() {
|
|
|
|
// spawn anvil and connect to it
|
|
|
|
let anvil = Anvil::new().spawn();
|
|
|
|
let provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
|
|
|
|
|
|
|
|
// assert that provider.get_gas_price() and oracle.fetch() return the same value
|
|
|
|
let expected_gas_price = provider.get_gas_price().await.unwrap();
|
|
|
|
let provider_oracle = ProviderOracle::new(provider);
|
|
|
|
let gas = provider_oracle.fetch().await.unwrap();
|
|
|
|
assert_eq!(gas, expected_gas_price);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
async fn blocknative() {
|
|
|
|
let gas_now_oracle = BlockNative::default();
|
|
|
|
let gas_price = gas_now_oracle.fetch().await.unwrap();
|
|
|
|
assert!(gas_price > U256::zero());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[ignore = "ETHGasStation is shutting down: https://twitter.com/ETHGasStation/status/1597341610777317376"]
|
|
|
|
#[allow(deprecated)]
|
2020-09-24 21:33:09 +00:00
|
|
|
async fn eth_gas_station() {
|
2022-12-18 11:45:47 +00:00
|
|
|
let eth_gas_station_oracle = ethers_middleware::gas_oracle::EthGasStation::default();
|
|
|
|
let gas_price = eth_gas_station_oracle.fetch().await.unwrap();
|
|
|
|
assert!(gas_price > U256::zero());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
#[ignore = "Etherchain / beaconcha.in's `gasPriceOracle` API currently returns 404: https://www.etherchain.org/api/gasPriceOracle"]
|
|
|
|
async fn etherchain() {
|
|
|
|
let etherchain_oracle = Etherchain::default();
|
|
|
|
let gas_price = etherchain_oracle.fetch().await.unwrap();
|
|
|
|
assert!(gas_price > U256::zero());
|
2020-09-24 21:33:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
async fn etherscan() {
|
2023-03-01 00:26:27 +00:00
|
|
|
let chain = Chain::Mainnet;
|
|
|
|
let etherscan_client = Client::new_from_opt_env(chain).unwrap();
|
2020-09-24 21:33:09 +00:00
|
|
|
|
|
|
|
// initialize and fetch gas estimates from Etherscan
|
|
|
|
// since etherscan does not support `fastest` category, we expect an error
|
2021-11-27 07:54:20 +00:00
|
|
|
let etherscan_oracle = Etherscan::new(etherscan_client.clone()).category(GasCategory::Fastest);
|
2022-12-18 11:45:47 +00:00
|
|
|
let error = etherscan_oracle.fetch().await.unwrap_err();
|
|
|
|
assert!(matches!(error, GasOracleError::GasCategoryNotSupported));
|
2020-09-24 21:33:09 +00:00
|
|
|
|
|
|
|
// but fetching the `standard` gas price should work fine
|
2021-11-27 07:54:20 +00:00
|
|
|
let etherscan_oracle = Etherscan::new(etherscan_client).category(GasCategory::SafeLow);
|
2020-09-24 21:33:09 +00:00
|
|
|
|
2022-12-18 11:45:47 +00:00
|
|
|
let gas_price = etherscan_oracle.fetch().await.unwrap();
|
|
|
|
assert!(gas_price > U256::zero());
|
2020-09-24 21:33:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test]
|
2022-12-18 11:45:47 +00:00
|
|
|
async fn gas_now() {
|
|
|
|
let gas_now_oracle = GasNow::default();
|
|
|
|
let gas_price = gas_now_oracle.fetch().await.unwrap();
|
|
|
|
assert!(gas_price > U256::zero());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
async fn polygon() {
|
|
|
|
let polygon_oracle = Polygon::default();
|
|
|
|
let gas_price = polygon_oracle.fetch().await.unwrap();
|
|
|
|
assert!(gas_price > U256::zero());
|
2020-09-24 21:33:09 +00:00
|
|
|
}
|