Skip to content
This repository has been archived by the owner on Jul 4, 2022. It is now read-only.

Uncouple emptying gas_meter from updating the gas spent for the block #68

Merged
merged 4 commits into from
Feb 26, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
11 changes: 2 additions & 9 deletions frame/contracts/src/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.

use crate::{GasSpent, Module, Trait, BalanceOf};
use crate::{Module, Trait, BalanceOf};
use sp_std::convert::TryFrom;
use sp_runtime::traits::{
CheckedMul, Zero, SaturatedConversion, AtLeast32Bit, UniqueSaturatedInto,
};
use frame_support::{
traits::{Currency, ExistenceRequirement, OnUnbalanced, WithdrawReason}, StorageValue,
dispatch::DispatchError,
traits::{Currency, ExistenceRequirement, OnUnbalanced, WithdrawReason}, dispatch::DispatchError,
};

#[cfg(test)]
Expand Down Expand Up @@ -257,14 +256,8 @@ pub fn refund_unused_gas<T: Trait>(
transactor: &T::AccountId,
gas_meter: GasMeter<T>,
) {
let gas_spent = gas_meter.spent();
let gas_left = gas_meter.gas_left();

// Increase total spent gas.
// This cannot overflow, since `gas_spent` is never greater than `block_gas_limit`, which
// also has Gas type.
GasSpent::mutate(|block_gas_spent| *block_gas_spent += gas_spent);

aliXsed marked this conversation as resolved.
Show resolved Hide resolved
// Refund gas left by the price it was bought at.
let refund = gas_meter.gas_price * gas_left.unique_saturated_into();
let _imbalance = T::Currency::deposit_creating(transactor, refund);
Expand Down
26 changes: 23 additions & 3 deletions frame/contracts/src/gas_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,24 @@ impl GasHandler<GasTest> for TestGasHandler {
}
}

pub struct NoChargeGasHandler;
impl GasHandler<GasTest> for NoChargeGasHandler {
fn fill_gas(
_transactor: &<GasTest as system::Trait>::AccountId,
gas_limit: Gas,
) -> Result<GasMeter<GasTest>, DispatchError> {
// fills the gas meter without charging the user
Ok(GasMeter::with_limit(gas_limit, 1))
}

fn empty_unused_gas(
transactor: &<GasTest as system::Trait>::AccountId,
gas_meter: GasMeter<GasTest>,
) {
// Do not charge the transactor. Give gas for free.
}
}

#[test]
// Tests that the user is not charged when filling up gas meters
fn customized_fill_gas_does_not_charge_the_user() {
Expand All @@ -273,9 +291,11 @@ fn customized_fill_gas_does_not_charge_the_user() {
// Create test account
Balances::deposit_creating(&ALICE, 1000);

// fill gas
let gas_meter_result = TestGasHandler::fill_gas(&ALICE, 500);
assert!(gas_meter_result.is_ok());
let gas_limit = 500;
let mut gas_meter = NoChargeGasHandler::fill_gas(&ALICE, gas_limit).unwrap();
// Charge as if the whole gas_limit is used
gas_meter.charge(&(), SimpleToken(gas_limit));
NoChargeGasHandler::empty_unused_gas(&ALICE, gas_meter);

// Check the user is not charged
assert_eq!(Balances::free_balance(&ALICE), 1000);
Expand Down
10 changes: 10 additions & 0 deletions frame/contracts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,11 @@ decl_module! {
if let Ok(code_hash) = result {
Self::deposit_event(RawEvent::CodeStored(code_hash));
}
// Increase total spent gas.
// This cannot overflow, since `gas_spent` is never greater than `block_gas_limit`, which
// also has Gas type.
GasSpent::mutate(|block_gas_spent| *block_gas_spent += gas_meter.spent());

T::GasHandler::empty_unused_gas(&origin, gas_meter);

result.map(|_| ()).map_err(Into::into)
Expand Down Expand Up @@ -752,6 +757,11 @@ impl<T: Trait> Module<T> {
DirectAccountDb.commit(ctx.overlay.into_change_set());
}

// Increase total spent gas.
// This cannot overflow, since `gas_spent` is never greater than `block_gas_limit`, which
// also has Gas type.
GasSpent::mutate(|block_gas_spent| *block_gas_spent += gas_meter.spent());

// Handle unused gas of the gas meter. Default behaviour is to refund cost of the unused gas.
//
// NOTE: This should go after the commit to the storage, since the storage changes
Expand Down