From 226dbb9578ab9719be334c7d4cc1a571f22c59f2 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 25 Feb 2020 20:47:40 +1300 Subject: [PATCH 1/3] Handle gas_price being zero separately --- frame/contracts/src/gas.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frame/contracts/src/gas.rs b/frame/contracts/src/gas.rs index c8572daaa43d4..8b4b96fbcc896 100644 --- a/frame/contracts/src/gas.rs +++ b/frame/contracts/src/gas.rs @@ -250,7 +250,11 @@ pub fn refund_unused_gas( pub fn approx_gas_for_balance(gas_price: Balance, balance: Balance) -> Gas where Balance: AtLeast32Bit { - (balance / gas_price).saturated_into::() + if gas_price.is_zero() { + Zero::zero() + } else { + (balance / gas_price).saturated_into::() + } } /// A simple utility macro that helps to match against a From b01e37e06b29bdb60f20c05124c5b3167c0ef1a2 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 25 Feb 2020 21:08:13 +1300 Subject: [PATCH 2/3] Bump spec_version --- bin/node/runtime/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 980f033024d6a..730a983a43818 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -81,8 +81,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to 0. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 225, - impl_version: 1, + spec_version: 226, + impl_version: 0, apis: RUNTIME_API_VERSIONS, }; From 94b7a68f2cf7ddc7b2ac6b733a1d3f93a741f623 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 26 Feb 2020 09:02:11 +1300 Subject: [PATCH 3/3] Add a unit & integration tests for gas price = 0 --- frame/contracts/src/gas.rs | 20 +++++++++++++++++++- frame/contracts/src/tests.rs | 16 ++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/frame/contracts/src/gas.rs b/frame/contracts/src/gas.rs index 8b4b96fbcc896..362f15f3aae79 100644 --- a/frame/contracts/src/gas.rs +++ b/frame/contracts/src/gas.rs @@ -298,7 +298,7 @@ macro_rules! match_tokens { #[cfg(test)] mod tests { use super::{GasMeter, Token}; - use crate::tests::Test; + use crate::{tests::Test, gas::approx_gas_for_balance}; /// A trivial token that charges the specified number of gas units. #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -386,4 +386,22 @@ mod tests { let mut gas_meter = GasMeter::::with_limit(25, 10); assert!(!gas_meter.charge(&(), SimpleToken(25)).is_out_of_gas()); } + + // A unit test for `fn approx_gas_for_balance()`, and makes + // sure setting gas_price 0 does not cause `div by zero` error. + #[test] + fn approx_gas_for_balance_works() { + let tests = vec![ + (approx_gas_for_balance(0_u64, 123), 0), + (approx_gas_for_balance(0_u64, 456), 0), + (approx_gas_for_balance(1_u64, 123), 123), + (approx_gas_for_balance(1_u64, 456), 456), + (approx_gas_for_balance(100_u64, 900), 9), + (approx_gas_for_balance(123_u64, 900), 7), + ]; + + for (lhs, rhs) in tests { + assert_eq!(lhs, rhs); + } + } } diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index e775998a3a553..51da3e8d1ff97 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -2079,6 +2079,22 @@ fn deploy_and_call_other_contract() { }); } +#[test] +fn deploy_works_without_gas_price() { + let (wasm, code_hash) = compile_module::(CODE_GET_RUNTIME_STORAGE).unwrap(); + ExtBuilder::default().existential_deposit(50).gas_price(0).build().execute_with(|| { + Balances::deposit_creating(&ALICE, 1_000_000); + assert_ok!(Contracts::put_code(Origin::signed(ALICE), 100_000, wasm)); + assert_ok!(Contracts::instantiate( + Origin::signed(ALICE), + 100, + 100_000, + code_hash.into(), + vec![], + )); + }); +} + const CODE_SELF_DESTRUCT: &str = r#" (module (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32)))