From 25fcfef796a085b3486091e8cf0834a6458c581e Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Fri, 10 Feb 2023 14:06:51 +0100 Subject: [PATCH] feat(anvil): add --disable-block-gas-limit (#4324) * feat(anvil): add --disable-block-gas-limit * extend backwards compat serialize --- anvil/src/cmd.rs | 21 +++++++++++++++++++++ anvil/src/config.rs | 13 +++++++++++++ anvil/tests/it/transaction.rs | 20 ++++++++++++++++++++ evm/Cargo.toml | 3 ++- evm/src/executor/fork/cache.rs | 7 +++++++ 5 files changed, 63 insertions(+), 1 deletion(-) diff --git a/anvil/src/cmd.rs b/anvil/src/cmd.rs index e8effa1fcde7..8fd06835ee37 100644 --- a/anvil/src/cmd.rs +++ b/anvil/src/cmd.rs @@ -208,6 +208,7 @@ impl NodeArgs { NodeConfig::default() .with_gas_limit(self.evm_opts.gas_limit) + .disable_block_gas_limit(self.evm_opts.disable_block_gas_limit) .with_gas_price(self.evm_opts.gas_price) .with_hardfork(self.hardfork) .with_blocktime(self.block_time.map(Duration::from_secs)) @@ -427,6 +428,16 @@ pub struct AnvilEvmArgs { #[clap(long, value_name = "GAS_LIMIT", help_heading = "Environment config")] pub gas_limit: Option, + /// Disable the `call.gas_limit <= block.gas_limit` constraint. + #[clap( + long, + value_name = "DISABLE_GAS_LIMIT", + help_heading = "Environment config", + alias = "disable-gas-limit", + conflicts_with = "gas_limit" + )] + pub disable_block_gas_limit: bool, + /// EIP-170: Contract code size limit in bytes. Useful to increase this because of tests. By /// default, it is 0x6000 (~25kb). #[clap(long, value_name = "CODE_SIZE", help_heading = "Environment config")] @@ -654,4 +665,14 @@ mod tests { let args: NodeArgs = NodeArgs::parse_from(["anvil", "--prune-history", "100"]); assert_eq!(args.prune_history, Some(Some(100))); } + + #[test] + fn can_parse_disable_block_gas_limit() { + let args: NodeArgs = NodeArgs::parse_from(["anvil", "--disable-block-gas-limit"]); + assert!(args.evm_opts.disable_block_gas_limit); + + let args = + NodeArgs::try_parse_from(["anvil", "--disable-block-gas-limit", "--gas-limit", "100"]); + assert!(args.is_err()); + } } diff --git a/anvil/src/config.rs b/anvil/src/config.rs index 9b3dcb925460..5e1e106e6911 100644 --- a/anvil/src/config.rs +++ b/anvil/src/config.rs @@ -84,6 +84,8 @@ pub struct NodeConfig { pub chain_id: Option, /// Default gas limit for all txs pub gas_limit: U256, + /// If set to `true`, disables the block gas limit + pub disable_block_gas_limit: bool, /// Default gas price for all txs pub gas_price: Option, /// Default base fee @@ -339,6 +341,7 @@ impl Default for NodeConfig { Self { chain_id: None, gas_limit: U256::from(30_000_000), + disable_block_gas_limit: false, gas_price: None, hardfork: None, signer_accounts: genesis_accounts.clone(), @@ -446,6 +449,15 @@ impl NodeConfig { self } + /// Disable block gas limit check + /// + /// If set to `true` block gas limit will not be enforced + #[must_use] + pub fn disable_block_gas_limit(mut self, disable_block_gas_limit: bool) -> Self { + self.disable_block_gas_limit = disable_block_gas_limit; + self + } + /// Sets the gas price #[must_use] pub fn with_gas_price>(mut self, gas_price: Option) -> Self { @@ -747,6 +759,7 @@ impl NodeConfig { // If EIP-3607 is enabled it can cause issues during fuzz/invariant tests if the // caller is a contract. So we disable the check by default. disable_eip3607: true, + disable_block_gas_limit: self.disable_block_gas_limit, ..Default::default() }, block: BlockEnv { diff --git a/anvil/tests/it/transaction.rs b/anvil/tests/it/transaction.rs index c2d7e6633a22..de1df21c3380 100644 --- a/anvil/tests/it/transaction.rs +++ b/anvil/tests/it/transaction.rs @@ -965,3 +965,23 @@ async fn test_reject_gas_too_low() { let err = resp.unwrap_err().to_string(); assert!(err.contains("intrinsic gas too low")); } + +// +#[tokio::test(flavor = "multi_thread")] +async fn can_call_with_high_gas_limit() { + let (_api, handle) = + spawn(NodeConfig::test().with_gas_limit(Some(U256::from(100_000_000)))).await; + let provider = handle.http_provider(); + + let wallet = handle.dev_wallets().next().unwrap(); + let client = Arc::new(SignerMiddleware::new(provider, wallet)); + + let greeter_contract = Greeter::deploy(Arc::clone(&client), "Hello World!".to_string()) + .unwrap() + .send() + .await + .unwrap(); + + let greeting = greeter_contract.greet().gas(60_000_000u64).call().await.unwrap(); + assert_eq!("Hello World!", greeting); +} diff --git a/evm/Cargo.toml b/evm/Cargo.toml index a2f8f5c948d6..eed26ce068f8 100644 --- a/evm/Cargo.toml +++ b/evm/Cargo.toml @@ -43,7 +43,8 @@ revm = { version = "2.3", default-features = false, features = [ "k256", "with-serde", "memory_limit", - "optional_eip3607" + "optional_eip3607", + "optional_block_gas_limit" ] } # Fuzzer diff --git a/evm/src/executor/fork/cache.rs b/evm/src/executor/fork/cache.rs index b3d4123b2683..d6c8b23a2c9a 100644 --- a/evm/src/executor/fork/cache.rs +++ b/evm/src/executor/fork/cache.rs @@ -168,6 +168,13 @@ impl<'de> Deserialize<'de> for BlockchainDbMeta { if !obj.contains_key(key) { obj.insert(key.to_string(), true.into()); } + // additional field `disable_block_gas_limit` enabled by the + // `optional_block_gas_limit` feature + let key = "disable_block_gas_limit"; + if !obj.contains_key(key) { + // keep default value + obj.insert(key.to_string(), false.into()); + } } let cfg_env: revm::CfgEnv =