[][src]Crate ethereumvm_network

Network-Agnostic EthereumVM Patches

This crate provides re-exports of the DynamicPatch API, and a set of precompiled contracts covering everything up to ETH Constantinople

There are two major approaches to the EVM configuration:

Examples for both approaches may be found below

Dynamic Patch API

DynamicPatch API is most useful for multi-network clients like multi-geth, where it's preferable to configure the EVM feature-wise, instead of fork-wise.

Example

use ethereumvm::{SeqTransactionVM, ValidTransaction, TransactionAction, HeaderParams};
use ethereumvm_network::{DynamicPatch, DynamicAccountPatch, PRECOMPILEDS};
use bigint::{Gas, U256, Address};
use std::rc::Rc;

fn main() {
  let transaction = ValidTransaction {
     caller: Some(Address::default()),
     gas_price: Gas::zero(),
     gas_limit: Gas::max_value(),
     action: TransactionAction::Create,
     value: U256::zero(),
     input: Rc::new(Vec::new()),
     nonce: U256::zero()
  };

  // Block Header
  let header = HeaderParams {
     beneficiary: Address::default(),
     timestamp: 0,
     number: U256::zero(),
     difficulty: U256::zero(),
     gas_limit: Gas::zero()
  };

  // Account Patch for ETC MainNet
  let account_patch = DynamicAccountPatch {
     initial_nonce: U256::zero(),
     initial_create_nonce: U256::zero(),
     empty_considered_exists: true,
     allow_partial_change: true
  };

  // Patch for Constantinople hardfork
  let patch = DynamicPatch {
     account_patch,
     code_deposit_limit: None,
     callstack_limit: 1024,
     gas_extcode: Gas::from(700_usize),
     gas_balance: Gas::from(400_usize),
     gas_sload: Gas::from(200_usize),
     gas_suicide: Gas::from(5000_usize),
     gas_suicide_new_account: Gas::from(25000_usize),
     gas_call: Gas::from(700_usize),
     gas_expbyte: Gas::from(50_usize),
     gas_transaction_create: Gas::from(32000_usize),
     force_code_deposit: false,
     has_delegate_call: true,
     has_static_call: true,
     has_revert: true,
     has_return_data: true,
     has_bitwise_shift: true,
     has_extcodehash: true,
     has_create2: true,
     has_reduced_sstore_gas_metering: true,
     err_on_call_with_more_gas: false,
     call_create_l64_after_gas: true,
     memory_limit: usize::max_value(),
     // Enable all eight precompiled contracts by their addresses
     enabled_precompileds: (0x1..=0x8).into_iter().map(Address::from).collect(),
     precompileds: &PRECOMPILEDS
  };

  SeqTransactionVM::new(
      &patch,
      transaction,
      header
  );
}

Patch API

If you need just a single network or even a single feature-set, use the Patch trait directly, that allows to create custom feature sets without DynamicPatch's tiny overhead.

Example

use ethereumvm::{SeqTransactionVM, ValidTransaction, TransactionAction, HeaderParams, Precompiled};
use ethereumvm_network::{AccountPatch, Patch, PRECOMPILEDS};
use bigint::{Gas, U256, Address};
use std::rc::Rc;

struct MainnetAccountPatch;
impl AccountPatch for MainnetAccountPatch {
   fn initial_nonce(&self) -> U256 { U256::zero() }
   fn initial_create_nonce(&self) -> U256 { U256::zero() }
   fn empty_considered_exists(&self) -> bool { true }
}

static MAINNET_ACCOUNT_PATCH: MainnetAccountPatch = MainnetAccountPatch;

struct ConstantinoplePatch;
impl Patch for ConstantinoplePatch {
   type Account = MainnetAccountPatch;
   fn account_patch(&self) -> &'static Self::Account { &MAINNET_ACCOUNT_PATCH }
   fn code_deposit_limit(&self) -> Option<usize> { None }
   fn callstack_limit(&self) -> usize { 1024 }
   fn gas_extcode(&self) -> Gas { Gas::from(700usize) }
   fn gas_balance(&self) -> Gas { Gas::from(400usize) }
   fn gas_sload(&self) -> Gas { Gas::from(200usize) }
   fn gas_suicide(&self) -> Gas { Gas::from(5000usize) }
   fn gas_suicide_new_account(&self) -> Gas { Gas::from(25000usize) }
   fn gas_call(&self) -> Gas { Gas::from(700usize) }
   fn gas_expbyte(&self) -> Gas { Gas::from(50usize) }
   fn gas_transaction_create(&self) -> Gas { Gas::from(32000usize) }
   fn force_code_deposit(&self) -> bool { false }
   fn has_delegate_call(&self) -> bool { true }
   fn has_static_call(&self) -> bool { true }
   fn has_revert(&self) -> bool { true }
   fn has_return_data(&self) -> bool { true }
   fn has_bitwise_shift(&self) -> bool { true }
   fn has_create2(&self) -> bool { true }
   fn has_extcodehash(&self) -> bool { true }
   fn has_reduced_sstore_gas_metering(&self) -> bool { true }
   fn err_on_call_with_more_gas(&self) -> bool { false }
   fn call_create_l64_after_gas(&self) -> bool { true }
   fn memory_limit(&self) -> usize { usize::max_value() }
   fn is_precompiled_contract_enabled(&self, address: &Address) -> bool {
       match address.low_u64() {
           0x1 | 0x2 | 0x3 | 0x4 | 0x5 | 0x6 | 0x7 | 0x8 => true,
           _ => false,
       }
   }
   fn precompileds(&self) -> &'static [(Address, Option<&'static [u8]>, &'static Precompiled)] {
       &PRECOMPILEDS
   }
}


fn main() {
  let transaction = ValidTransaction {
     caller: Some(Address::default()),
     gas_price: Gas::zero(),
     gas_limit: Gas::max_value(),
     action: TransactionAction::Create,
     value: U256::zero(),
     input: Rc::new(Vec::new()),
     nonce: U256::zero()
  };

  // Block Header
  let header = HeaderParams {
     beneficiary: Address::default(),
     timestamp: 0,
     number: U256::zero(),
     difficulty: U256::zero(),
     gas_limit: Gas::zero()
  };

  let patch = ConstantinoplePatch;

  SeqTransactionVM::new(
      &patch,
      transaction,
      header
  );
}

Structs

DynamicAccountPatch

AccountPatch that can be configured in client code runtime

DynamicPatch

Patch that can be configured in client code runtime

Statics

PRECOMPILEDS

Traits

AccountPatch

Account patch for account related variables. Account patch is always static, as it's usually stays constant for any given network.

Patch

Represents different block range context.