Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/standard/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,16 @@ impl Config {
}
}

/// Floor gas paid for zero data in a transaction.
pub fn gas_floor_transaction_zero_data(&self) -> u64 {
10
}

/// Floor gas paid for non-zero data in a transaction.
pub fn gas_floor_transaction_non_zero_data(&self) -> u64 {
40
}

/// Gas paid per address in transaction access list (see EIP-2930).
pub fn gas_access_list_address(&self) -> u64 {
if self.eip2930_access_list { 2400 } else { 0 }
Expand Down
49 changes: 38 additions & 11 deletions src/standard/gasometer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub struct GasometerState {
gas_limit: u64,
memory_gas: u64,
used_gas: u64,
floor_gas: u64,
refunded_gas: i64,
/// Whether the gasometer is in static context.
pub is_static: bool,
Expand Down Expand Up @@ -78,6 +79,13 @@ impl GasometerState {
Ok(())
}

/// Record used and floor costs of a transaction.
pub fn records_transaction_cost(&mut self, cost: TransactionGas) -> Result<(), ExitError> {
self.record_gas64(cost.used)?;
self.floor_gas = cost.floor;
Ok(())
}

/// Set memory gas usage.
pub fn set_memory_gas(&mut self, memory_cost: u64) -> Result<(), ExitError> {
let all_gas_cost = self.used_gas.checked_add(memory_cost);
Expand All @@ -99,6 +107,7 @@ impl GasometerState {
gas_limit,
memory_gas: 0,
used_gas: 0,
floor_gas: 0,
refunded_gas: 0,
is_static,
}
Expand All @@ -118,9 +127,9 @@ impl GasometerState {
};

let mut s = Self::new(gas_limit, false);
let transaction_cost = TransactionCost::call(data, access_list).cost(config);
let cost = TransactionCost::call(data, access_list).cost(config);

s.record_gas64(transaction_cost)?;
s.records_transaction_cost(cost)?;
Ok(s)
}

Expand All @@ -138,9 +147,9 @@ impl GasometerState {
};

let mut s = Self::new(gas_limit, false);
let transaction_cost = TransactionCost::create(code, access_list).cost(config);
let cost = TransactionCost::create(code, access_list).cost(config);

s.record_gas64(transaction_cost)?;
s.records_transaction_cost(cost)?;
Ok(s)
}

Expand Down Expand Up @@ -202,6 +211,11 @@ impl GasometerState {
MergeStrategy::Discard => {}
}
}

/// Apply the floor gas cost for calldata as defined in EIP-7623
pub fn apply_transaction_floor_cost(&mut self) {
self.used_gas = max(self.used_gas, self.floor_gas);
}
}

/// The eval function of the entire gasometer.
Expand Down Expand Up @@ -940,6 +954,11 @@ enum TransactionCost {
},
}

pub struct TransactionGas {
used: u64,
floor: u64,
}

impl TransactionCost {
pub fn call(data: &[u8], access_list: &[(H160, Vec<H256>)]) -> TransactionCost {
let zero_data_len = data.iter().filter(|v| **v == 0).count();
Expand Down Expand Up @@ -969,22 +988,25 @@ impl TransactionCost {
}
}

pub fn cost(&self, config: &Config) -> u64 {
pub fn cost(&self, config: &Config) -> TransactionGas {
match self {
TransactionCost::Call {
zero_data_len,
non_zero_data_len,
access_list_address_len,
access_list_storage_len,
} => {
#[deny(clippy::let_and_return)]
let cost = config.gas_transaction_call()
let used = config.gas_transaction_call()
+ *zero_data_len as u64 * config.gas_transaction_zero_data()
+ *non_zero_data_len as u64 * config.gas_transaction_non_zero_data()
+ *access_list_address_len as u64 * config.gas_access_list_address()
+ *access_list_storage_len as u64 * config.gas_access_list_storage_key();

cost
let floor = config.gas_transaction_call()
+ *zero_data_len as u64 * config.gas_floor_transaction_zero_data()
+ *non_zero_data_len as u64 * config.gas_floor_transaction_non_zero_data();

TransactionGas { used, floor }
}
TransactionCost::Create {
zero_data_len,
Expand All @@ -993,16 +1015,21 @@ impl TransactionCost {
access_list_storage_len,
initcode_cost,
} => {
let mut cost = config.gas_transaction_create()
let mut used = config.gas_transaction_create()
+ *zero_data_len as u64 * config.gas_transaction_zero_data()
+ *non_zero_data_len as u64 * config.gas_transaction_non_zero_data()
+ *access_list_address_len as u64 * config.gas_access_list_address()
+ *access_list_storage_len as u64 * config.gas_access_list_storage_key();

if config.max_initcode_size().is_some() {
cost += initcode_cost;
used += initcode_cost;
}

cost
let floor = config.gas_transaction_call()
+ *zero_data_len as u64 * config.gas_floor_transaction_zero_data()
+ *non_zero_data_len as u64 * config.gas_floor_transaction_non_zero_data();

TransactionGas { used, floor }
}
}
}
Expand Down