diff --git a/.changelog/unreleased/improvements/3391-parameterize-gas-scale.md b/.changelog/unreleased/improvements/3391-parameterize-gas-scale.md
new file mode 100644
index 00000000000..2729821cb79
--- /dev/null
+++ b/.changelog/unreleased/improvements/3391-parameterize-gas-scale.md
@@ -0,0 +1,3 @@
+- Include the gas scale as a protocol parameter that is
+ mutable via governance rather than as a hard-coded constant.
+ ([\#3391](https://github.com/anoma/namada/pull/3391))
\ No newline at end of file
diff --git a/crates/apps_lib/src/config/genesis.rs b/crates/apps_lib/src/config/genesis.rs
index d6e5d970468..f3445ff496b 100644
--- a/crates/apps_lib/src/config/genesis.rs
+++ b/crates/apps_lib/src/config/genesis.rs
@@ -315,6 +315,8 @@ pub struct Parameters {
pub max_signatures_per_transaction: u8,
/// Fee unshielding gas limit
pub fee_unshielding_gas_limit: u64,
+ /// Gas scale
+ pub gas_scale: u64,
/// Map of the cost per gas unit for every token allowed for fee payment
pub minimum_gas_price: BTreeMap
,
}
diff --git a/crates/apps_lib/src/config/genesis/chain.rs b/crates/apps_lib/src/config/genesis/chain.rs
index 690d67909f0..eb01309a1d2 100644
--- a/crates/apps_lib/src/config/genesis/chain.rs
+++ b/crates/apps_lib/src/config/genesis/chain.rs
@@ -305,6 +305,7 @@ impl Finalized {
masp_epoch_multiplier,
max_signatures_per_transaction,
fee_unshielding_gas_limit,
+ gas_scale,
max_block_gas,
minimum_gas_price,
max_tx_bytes,
@@ -351,6 +352,7 @@ impl Finalized {
max_proposal_bytes,
max_signatures_per_transaction,
fee_unshielding_gas_limit,
+ gas_scale,
max_block_gas,
minimum_gas_price: minimum_gas_price
.iter()
diff --git a/crates/apps_lib/src/config/genesis/templates.rs b/crates/apps_lib/src/config/genesis/templates.rs
index db5ac13772e..c9c0d5133b4 100644
--- a/crates/apps_lib/src/config/genesis/templates.rs
+++ b/crates/apps_lib/src/config/genesis/templates.rs
@@ -301,6 +301,8 @@ pub struct ChainParams {
pub max_block_gas: u64,
/// Fee unshielding gas limit
pub fee_unshielding_gas_limit: u64,
+ /// Gas scale
+ pub gas_scale: u64,
/// Map of the cost per gas unit for every token allowed for fee payment
pub minimum_gas_price: T::GasMinimums,
}
@@ -325,6 +327,7 @@ impl ChainParams {
max_signatures_per_transaction,
max_block_gas,
fee_unshielding_gas_limit,
+ gas_scale,
minimum_gas_price,
} = self;
let mut min_gas_prices = BTreeMap::default();
@@ -371,6 +374,7 @@ impl ChainParams {
max_signatures_per_transaction,
max_block_gas,
fee_unshielding_gas_limit,
+ gas_scale,
minimum_gas_price: min_gas_prices,
})
}
diff --git a/crates/core/src/parameters.rs b/crates/core/src/parameters.rs
index aaf2c294f81..d7bd2b26a48 100644
--- a/crates/core/src/parameters.rs
+++ b/crates/core/src/parameters.rs
@@ -53,6 +53,8 @@ pub struct Parameters {
pub max_signatures_per_transaction: u8,
/// Fee unshielding gas limit
pub fee_unshielding_gas_limit: u64,
+ /// Gas scale
+ pub gas_scale: u64,
/// Map of the cost per gas unit for every token allowed for fee payment
pub minimum_gas_price: BTreeMap,
/// Enable the native token transfer if it is true
diff --git a/crates/gas/src/lib.rs b/crates/gas/src/lib.rs
index 89e24209ffc..dc9c4c0a201 100644
--- a/crates/gas/src/lib.rs
+++ b/crates/gas/src/lib.rs
@@ -113,9 +113,6 @@ pub const MASP_PARALLEL_GAS_DIVIDER: u64 = PARALLEL_GAS_DIVIDER / 2;
/// Gas module result for functions that may fail
pub type Result = std::result::Result;
-/// Decimal scale of Gas units
-const SCALE: u64 = 100_000_000;
-
/// Representation of gas in sub-units. This effectively decouples gas metering
/// from fee payment, allowing higher resolution when accounting for gas while,
/// at the same time, providing a contained gas value when paying fees.
@@ -155,9 +152,17 @@ impl Gas {
/// Converts the sub gas units to whole ones. If the sub units are not a
/// multiple of the `SCALE` than ceil the quotient
- fn get_whole_gas_units(&self) -> u64 {
- let quotient = self.sub / SCALE;
- if self.sub % SCALE == 0 {
+ pub fn get_whole_gas_units(&self, scale: u64) -> u64 {
+ let quotient = self
+ .sub
+ .checked_div(scale)
+ .expect("Gas quotient should not overflow on checked division");
+ if self
+ .sub
+ .checked_rem(scale)
+ .expect("Gas quotient remainder should not overflow")
+ == 0
+ {
quotient
} else {
quotient
@@ -167,8 +172,8 @@ impl Gas {
}
/// Generates a `Gas` instance from a whole amount
- pub fn from_whole_units(whole: u64) -> Option {
- let sub = whole.checked_mul(SCALE)?;
+ pub fn from_whole_units(whole: u64, scale: u64) -> Option {
+ let sub = whole.checked_mul(scale)?;
Some(Self { sub })
}
}
@@ -187,8 +192,9 @@ impl From for u64 {
impl Display for Gas {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- // Display the gas in whole amounts
- write!(f, "{}", self.get_whole_gas_units())
+ // Need to do this now that the gas scale is a parameter. Should
+ // manually scale gas first before calling this
+ write!(f, "{}", self.sub)
}
}
@@ -197,8 +203,7 @@ impl FromStr for Gas {
fn from_str(s: &str) -> std::result::Result {
let raw: u64 = s.parse().map_err(GasParseError::Parse)?;
- let gas = Gas::from_whole_units(raw).ok_or(GasParseError::Overflow)?;
- Ok(gas)
+ Ok(Self { sub: raw })
}
}
diff --git a/crates/namada/src/ledger/mod.rs b/crates/namada/src/ledger/mod.rs
index 2f952e4f992..f36406453de 100644
--- a/crates/namada/src/ledger/mod.rs
+++ b/crates/namada/src/ledger/mod.rs
@@ -23,7 +23,6 @@ pub use {
mod dry_run_tx {
use std::cell::RefCell;
- use namada_gas::Gas;
use namada_sdk::queries::{EncodedResponseQuery, RequestCtx, RequestQuery};
use namada_state::{DBIter, ResultExt, StorageHasher, DB};
use namada_tx::data::{GasLimit, TxResult};
@@ -54,11 +53,15 @@ mod dry_run_tx {
let tx = Tx::try_from(&request.data[..]).into_storage_result()?;
tx.validate_tx().into_storage_result()?;
+ let gas_scale = namada_parameters::get_gas_scale(ctx.state)?;
+
// Wrapper dry run to allow estimating the gas cost of a transaction
let (mut tx_result, tx_gas_meter) = match tx.header().tx_type {
TxType::Wrapper(wrapper) => {
- let gas_limit =
- Gas::try_from(wrapper.gas_limit).into_storage_result()?;
+ let gas_limit = wrapper
+ .gas_limit
+ .as_scaled_gas(gas_scale)
+ .into_storage_result()?;
let tx_gas_meter = RefCell::new(TxGasMeter::new(gas_limit));
let tx_result = protocol::apply_wrapper_tx(
&tx,
@@ -79,7 +82,8 @@ mod dry_run_tx {
// the gas limit
let max_block_gas =
namada_parameters::get_max_block_gas(ctx.state)?;
- let gas_limit = Gas::try_from(GasLimit::from(max_block_gas))
+ let gas_limit = GasLimit::from(max_block_gas)
+ .as_scaled_gas(gas_scale)
.into_storage_result()?;
(TxResult::default(), TxGasMeter::new(gas_limit))
}
@@ -187,6 +191,12 @@ mod test {
.expect(
"Max block gas parameter must be initialized in storage",
);
+ // Initialize mock gas scale
+ let gas_scale_key = namada_parameters::storage::get_gas_scale_key();
+ state
+ .db_write(&gas_scale_key, 100_000_000_u64.serialize_to_vec())
+ .expect("Gas scale parameter must be initialized in storage");
+
let event_log = EventLog::default();
let (vp_wasm_cache, vp_cache_dir) =
wasm::compilation_cache::common::testing::cache();
diff --git a/crates/namada/src/ledger/protocol/mod.rs b/crates/namada/src/ledger/protocol/mod.rs
index b19098e18d7..2bb8ecb4d26 100644
--- a/crates/namada/src/ledger/protocol/mod.rs
+++ b/crates/namada/src/ledger/protocol/mod.rs
@@ -261,6 +261,7 @@ where
tx_wasm_cache,
},
)?;
+
Ok(TxResult {
gas_used: tx_gas_meter.borrow().get_tx_consumed_gas(),
batch_results: BatchResults(
diff --git a/crates/node/src/shell/finalize_block.rs b/crates/node/src/shell/finalize_block.rs
index 7adbcd17ba5..844d3dec715 100644
--- a/crates/node/src/shell/finalize_block.rs
+++ b/crates/node/src/shell/finalize_block.rs
@@ -29,6 +29,7 @@ use namada::tx::event::{Batch, Code};
use namada::tx::new_tx_event;
use namada::vote_ext::ethereum_events::MultiSignedEthEvent;
use namada::vote_ext::ethereum_tx_data_variants;
+use parameters::get_gas_scale;
use super::*;
use crate::facade::tendermint::abci::types::VoteInfo;
@@ -385,9 +386,17 @@ where
.unwrap_or(""),
msg,
);
+ let gas_scale = get_gas_scale(&self.state)
+ .expect("Failed to get gas scale from parameters");
+ let scaled_gas = Gas::from(
+ tx_data
+ .tx_gas_meter
+ .get_tx_consumed_gas()
+ .get_whole_gas_units(gas_scale),
+ );
tx_logs
.tx_event
- .extend(GasUsed(tx_data.tx_gas_meter.get_tx_consumed_gas()))
+ .extend(GasUsed(scaled_gas))
.extend(Info(msg.to_string()))
.extend(Code(ResultCode::InvalidTx));
// Make sure to clean the write logs for the next transaction
@@ -410,9 +419,18 @@ where
msg
);
+ let gas_scale = get_gas_scale(&self.state)
+ .expect("Failed to get gas scale from parameters");
+ let scaled_gas = Gas::from(
+ tx_data
+ .tx_gas_meter
+ .get_tx_consumed_gas()
+ .get_whole_gas_units(gas_scale),
+ );
+
tx_logs
.tx_event
- .extend(GasUsed(tx_data.tx_gas_meter.get_tx_consumed_gas()))
+ .extend(GasUsed(scaled_gas))
.extend(Info(msg.to_string()))
.extend(Code(ResultCode::WasmRuntimeError));
@@ -487,9 +505,18 @@ where
self.commit_batch_hash(tx_data.replay_protection_hashes);
}
+ let gas_scale = get_gas_scale(&self.state)
+ .expect("Failed to get gas scale from parameters");
+ let scaled_gas = Gas::from(
+ tx_data
+ .tx_gas_meter
+ .get_tx_consumed_gas()
+ .get_whole_gas_units(gas_scale),
+ );
+
tx_logs
.tx_event
- .extend(GasUsed(extended_tx_result.tx_result.gas_used))
+ .extend(GasUsed(scaled_gas))
.extend(Info("Check batch for result.".to_string()))
.extend(Batch(&extended_tx_result.tx_result.to_result_string()));
}
@@ -669,22 +696,25 @@ where
TxType::Wrapper(wrapper) => {
stats.increment_wrapper_txs();
- let gas_limit = match Gas::try_from(wrapper.gas_limit) {
- Ok(value) => value,
- Err(_) => {
- response.events.emit(
- new_tx_event(&tx, height.0)
- .with(Code(ResultCode::InvalidTx))
- .with(Info(
- "The wrapper gas limit overflowed gas \
- representation"
- .to_owned(),
- ))
- .with(GasUsed(0.into())),
- );
- continue;
- }
- };
+ let gas_scale = get_gas_scale(&self.state)
+ .expect("Failed to get gas scale from parameters");
+ let gas_limit =
+ match wrapper.gas_limit.as_scaled_gas(gas_scale) {
+ Ok(value) => value,
+ Err(_) => {
+ response.events.emit(
+ new_tx_event(&tx, height.0)
+ .with(Code(ResultCode::InvalidTx))
+ .with(Info(
+ "The wrapper gas limit overflowed \
+ gas representation"
+ .to_owned(),
+ ))
+ .with(GasUsed(0.into())),
+ );
+ continue;
+ }
+ };
let tx_gas_meter = TxGasMeter::new(gas_limit);
for cmt in tx.commitments() {
if let Some(code_sec) = tx
diff --git a/crates/node/src/shell/mod.rs b/crates/node/src/shell/mod.rs
index 2ace0f620a7..4caf8a169ee 100644
--- a/crates/node/src/shell/mod.rs
+++ b/crates/node/src/shell/mod.rs
@@ -48,7 +48,7 @@ use namada::ledger::pos::namada_proof_of_stake::types::{
};
use namada::ledger::protocol::ShellParams;
use namada::ledger::{parameters, protocol};
-use namada::parameters::validate_tx_bytes;
+use namada::parameters::{get_gas_scale, validate_tx_bytes};
use namada::proof_of_stake::storage::read_pos_params;
use namada::state::tx_queue::ExpiredTx;
use namada::state::{
@@ -1067,9 +1067,22 @@ where
}
},
TxType::Wrapper(wrapper) => {
+ // Get the gas scale first
+ let gas_scale = match get_gas_scale(&self.state) {
+ Ok(scale) => scale,
+ Err(_) => {
+ response.code = ResultCode::InvalidTx.into();
+ response.log = "The gas scale could not be found in \
+ the parameters storage"
+ .to_string();
+ return response;
+ }
+ };
+
// Validate wrapper first
// Tx gas limit
- let gas_limit = match Gas::try_from(wrapper.gas_limit) {
+ let gas_limit = match wrapper.gas_limit.as_scaled_gas(gas_scale)
+ {
Ok(value) => value,
Err(_) => {
response.code = ResultCode::InvalidTx.into();
@@ -1091,6 +1104,7 @@ where
// Max block gas
let block_gas_limit: Gas = Gas::from_whole_units(
namada::parameters::get_max_block_gas(&self.state).unwrap(),
+ gas_scale,
)
.expect("Gas limit from parameter must not overflow");
if gas_meter.tx_gas_limit > block_gas_limit {
diff --git a/crates/node/src/shell/prepare_proposal.rs b/crates/node/src/shell/prepare_proposal.rs
index 6cc2f22392e..aa6fe39b5f5 100644
--- a/crates/node/src/shell/prepare_proposal.rs
+++ b/crates/node/src/shell/prepare_proposal.rs
@@ -4,9 +4,10 @@ use std::cell::RefCell;
use namada::core::address::Address;
use namada::core::key::tm_raw_hash_to_string;
-use namada::gas::{Gas, TxGasMeter};
+use namada::gas::TxGasMeter;
use namada::hash::Hash;
use namada::ledger::protocol::{self, ShellParams};
+use namada::parameters::get_gas_scale;
use namada::proof_of_stake::storage::find_validator_by_raw_hash;
use namada::state::{DBIter, StorageHasher, TempWlState, DB};
use namada::token::{Amount, DenominatedAmount};
@@ -288,7 +289,9 @@ where
tx.validate_tx().map_err(|_| ())?;
if let TxType::Wrapper(wrapper) = tx.header().tx_type {
// Check tx gas limit for tx size
- let gas_limit = Gas::try_from(wrapper.gas_limit).map_err(|_| ())?;
+ let gas_scale = get_gas_scale(temp_state).map_err(|_| ())?;
+ let gas_limit =
+ wrapper.gas_limit.as_scaled_gas(gas_scale).map_err(|_| ())?;
let mut tx_gas_meter = TxGasMeter::new(gas_limit);
tx_gas_meter.add_wrapper_gas(tx_bytes).map_err(|_| ())?;
diff --git a/crates/node/src/shell/process_proposal.rs b/crates/node/src/shell/process_proposal.rs
index f226097c116..7554be9e50f 100644
--- a/crates/node/src/shell/process_proposal.rs
+++ b/crates/node/src/shell/process_proposal.rs
@@ -410,7 +410,17 @@ where
let allocated_gas =
metadata.user_gas.try_dump(u64::from(wrapper.gas_limit));
- let gas_limit = match Gas::try_from(wrapper.gas_limit) {
+ let gas_scale = match get_gas_scale(temp_state) {
+ Ok(scale) => scale,
+ Err(_) => {
+ return TxResult {
+ code: ResultCode::TxGasLimit.into(),
+ info: "Failed to get gas scale".to_owned(),
+ };
+ }
+ };
+ let gas_limit = match wrapper.gas_limit.as_scaled_gas(gas_scale)
+ {
Ok(value) => value,
Err(_) => {
return TxResult {
diff --git a/crates/node/src/storage/mod.rs b/crates/node/src/storage/mod.rs
index 49d37c81a82..96bc5e716be 100644
--- a/crates/node/src/storage/mod.rs
+++ b/crates/node/src/storage/mod.rs
@@ -176,6 +176,7 @@ mod tests {
masp_epoch_multiplier: 2,
max_signatures_per_transaction: 10,
fee_unshielding_gas_limit: 0,
+ gas_scale: 100_000_000,
minimum_gas_price: Default::default(),
is_native_token_transferable: true,
};
diff --git a/crates/parameters/src/lib.rs b/crates/parameters/src/lib.rs
index b8dbe12a883..affaded892f 100644
--- a/crates/parameters/src/lib.rs
+++ b/crates/parameters/src/lib.rs
@@ -28,7 +28,7 @@ use namada_core::storage::Key;
use namada_core::time::DurationSecs;
use namada_core::token;
use namada_storage::{ResultExt, StorageRead, StorageWrite};
-pub use storage::get_max_block_gas;
+pub use storage::{get_gas_scale, get_max_block_gas};
use thiserror::Error;
pub use wasm_allowlist::{is_tx_allowed, is_vp_allowed};
@@ -78,6 +78,7 @@ where
max_signatures_per_transaction,
minimum_gas_price,
fee_unshielding_gas_limit,
+ gas_scale,
is_native_token_transferable,
} = parameters;
@@ -102,6 +103,10 @@ where
storage::get_fee_unshielding_gas_limit_key();
storage.write(&fee_unshielding_gas_limit_key, fee_unshielding_gas_limit)?;
+ // write the gas scale
+ let gas_scale_key = storage::get_gas_scale_key();
+ storage.write(&gas_scale_key, gas_scale)?;
+
// write vp allowlist parameter
let vp_allowlist_key = storage::get_vp_allowlist_storage_key();
let vp_allowlist = vp_allowlist
@@ -379,6 +384,13 @@ where
.ok_or(ReadError::ParametersMissing)
.into_storage_result()?;
+ // read gas scale
+ let gas_scale_key = storage::get_gas_scale_key();
+ let value = storage.read(&gas_scale_key)?;
+ let gas_scale: u64 = value
+ .ok_or(ReadError::ParametersMissing)
+ .into_storage_result()?;
+
// read epochs per year
let epochs_per_year_key = storage::get_epochs_per_year_key();
let value = storage.read(&epochs_per_year_key)?;
@@ -433,6 +445,7 @@ where
max_signatures_per_transaction,
minimum_gas_price,
fee_unshielding_gas_limit,
+ gas_scale,
is_native_token_transferable,
})
}
@@ -478,6 +491,7 @@ where
masp_epoch_multiplier: 2,
max_signatures_per_transaction: 10,
fee_unshielding_gas_limit: 0,
+ gas_scale: 100_000_000,
minimum_gas_price: Default::default(),
is_native_token_transferable: true,
};
diff --git a/crates/parameters/src/storage.rs b/crates/parameters/src/storage.rs
index 27204f95680..7b3d847138f 100644
--- a/crates/parameters/src/storage.rs
+++ b/crates/parameters/src/storage.rs
@@ -39,6 +39,7 @@ struct Keys {
max_block_gas: &'static str,
minimum_gas_price: &'static str,
fee_unshielding_gas_limit: &'static str,
+ gas_scale: &'static str,
max_signatures_per_transaction: &'static str,
native_token_transferable: &'static str,
}
@@ -121,6 +122,11 @@ pub fn get_fee_unshielding_gas_limit_key() -> Key {
get_fee_unshielding_gas_limit_key_at_addr(ADDRESS)
}
+/// Storage key used for the gas scale
+pub fn get_gas_scale_key() -> Key {
+ get_gas_scale_key_at_addr(ADDRESS)
+}
+
/// Storage key used for max_epected_time_per_block parameter.
pub fn get_max_expected_time_per_block_key() -> Key {
get_max_expected_time_per_block_key_at_addr(ADDRESS)
@@ -178,6 +184,18 @@ pub fn get_max_block_gas(
)
}
+/// Helper function to retrieve the `gas_scale` protocol parameter from
+/// storage
+pub fn get_gas_scale(
+ storage: &impl StorageRead,
+) -> std::result::Result {
+ storage.read(&get_gas_scale_key())?.ok_or(
+ namada_storage::Error::SimpleMessage(
+ "Missing gas_scale parameter from storage",
+ ),
+ )
+}
+
/// Storage key used for the flag to enable the native token transfer
pub fn get_native_token_transferable_key() -> Key {
get_native_token_transferable_key_at_addr(ADDRESS)
diff --git a/crates/proof_of_stake/src/lib.rs b/crates/proof_of_stake/src/lib.rs
index 19b003541f4..1326bcd7abf 100644
--- a/crates/proof_of_stake/src/lib.rs
+++ b/crates/proof_of_stake/src/lib.rs
@@ -2727,6 +2727,7 @@ pub mod test_utils {
masp_epoch_multiplier: 2,
max_signatures_per_transaction: 15,
fee_unshielding_gas_limit: 10000,
+ gas_scale: 100_000_000,
minimum_gas_price: BTreeMap::new(),
is_native_token_transferable: true,
};
diff --git a/crates/sdk/src/rpc.rs b/crates/sdk/src/rpc.rs
index 52f079c5add..6f07a373c3c 100644
--- a/crates/sdk/src/rpc.rs
+++ b/crates/sdk/src/rpc.rs
@@ -540,6 +540,7 @@ pub async fn dry_run_tx(
)?
.data;
let result_str = format!("Transaction consumed {} gas", result.gas_used);
+
let mut cmt_result_str = String::new();
for (cmt_hash, cmt_result) in &result.batch_results.0 {
match cmt_result {
diff --git a/crates/sdk/src/tx.rs b/crates/sdk/src/tx.rs
index b9daabeca20..bd17b498ef7 100644
--- a/crates/sdk/src/tx.rs
+++ b/crates/sdk/src/tx.rs
@@ -405,9 +405,11 @@ pub fn display_batch_resp(context: &impl Namada, resp: &TxResponse) {
InnerTxResult::Success(_) => {
display_line!(
context.io(),
- "Transaction {} was successfully applied at height {}.",
+ "Transaction {} was successfully applied at height {}, \
+ consuming {} gas units.",
cmt_hash,
resp.height,
+ resp.gas_used
);
}
InnerTxResult::VpsRejected(inner) => {
diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs
index f62ab1c862f..38695ce723c 100644
--- a/crates/state/src/lib.rs
+++ b/crates/state/src/lib.rs
@@ -761,6 +761,7 @@ mod tests {
masp_epoch_multiplier: 2,
max_signatures_per_transaction: 15,
fee_unshielding_gas_limit: 20_000,
+ gas_scale: 100_000_000,
minimum_gas_price: BTreeMap::default(),
is_native_token_transferable: true,
};
diff --git a/crates/tests/src/e2e/ibc_tests.rs b/crates/tests/src/e2e/ibc_tests.rs
index c1781b62955..3aadda71643 100644
--- a/crates/tests/src/e2e/ibc_tests.rs
+++ b/crates/tests/src/e2e/ibc_tests.rs
@@ -2196,13 +2196,13 @@ fn transfer_from_gaia(
fn check_tx_height(test: &Test, client: &mut NamadaCmd) -> Result {
let (_unread, matched) = client.exp_regex(r"height .*")?;
- // Expecting e.g. "height 1337."
+ // Expecting e.g. "height 1337, consuming x gas units."
let height_str = matched
.trim()
.split_once(' ')
.unwrap()
.1
- .split_once('.')
+ .split_once(',')
.unwrap()
.0;
let height: u32 = height_str.parse().unwrap();
diff --git a/crates/tx/src/data/mod.rs b/crates/tx/src/data/mod.rs
index 20c4019fc20..5984dafdc94 100644
--- a/crates/tx/src/data/mod.rs
+++ b/crates/tx/src/data/mod.rs
@@ -411,7 +411,7 @@ pub struct VpsResult {
impl fmt::Display for TxResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
- write!(f, "Transaction is valid. Gas used: {}", self.gas_used,)
+ write!(f, "Transaction is valid. Gas used: {}", self.gas_used)
} else {
write!(f, "{}", serde_json::to_string(self).unwrap())
}
diff --git a/crates/tx/src/data/wrapper.rs b/crates/tx/src/data/wrapper.rs
index 23bd4c53f15..3a2f1ebcc77 100644
--- a/crates/tx/src/data/wrapper.rs
+++ b/crates/tx/src/data/wrapper.rs
@@ -111,13 +111,10 @@ impl From for Amount {
}
}
-impl TryFrom for Gas {
- type Error = std::io::Error;
-
- /// Derive a Gas instance with a sub amount which is exactly a whole
- /// amount since the limit represents gas in whole units
- fn try_from(value: GasLimit) -> Result {
- Self::from_whole_units(u64::from(value)).ok_or_else(|| {
+impl GasLimit {
+ /// Convert the gas limit into scaled gas
+ pub fn as_scaled_gas(&self, scale: u64) -> Result {
+ Gas::from_whole_units(u64::from(*self), scale).ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"gas overflow",
diff --git a/genesis/localnet/parameters.toml b/genesis/localnet/parameters.toml
index bef2c1ae2d9..b2c8a1b9d7d 100644
--- a/genesis/localnet/parameters.toml
+++ b/genesis/localnet/parameters.toml
@@ -26,6 +26,8 @@ max_signatures_per_transaction = 15
max_block_gas = 20000000
# Fee unshielding gas limit
fee_unshielding_gas_limit = 20000
+# Gas scale
+gas_scale = 100_000_000
# Map of the cost per gas unit for every token allowed for fee payment
[parameters.minimum_gas_price]
diff --git a/genesis/starter/parameters.toml b/genesis/starter/parameters.toml
index dfb01522d6d..2fc30e455bf 100644
--- a/genesis/starter/parameters.toml
+++ b/genesis/starter/parameters.toml
@@ -26,6 +26,8 @@ max_signatures_per_transaction = 15
max_block_gas = 20000000
# Fee unshielding gas limit
fee_unshielding_gas_limit = 20000
+# Gas scale
+gas_scale = 100_000_000
# Map of the cost per gas unit for every token allowed for fee payment
[parameters.minimum_gas_price]