Skip to content
Snippets Groups Projects
lib.rs 38 KiB
Newer Older
				pays_fee: Pays::Yes,
			assert_eq!(Module::<Runtime>::compute_fee(0, &dispatch_info, 0), 100);
			// Tip + base fee works
			assert_eq!(Module::<Runtime>::compute_fee(0, &dispatch_info, 69), 169);
			// Len (byte fee) + base fee works
			assert_eq!(Module::<Runtime>::compute_fee(42, &dispatch_info, 0), 520);
			// Weight fee + base fee works
			let dispatch_info = DispatchInfo {
				weight: 1000,
				class: DispatchClass::Operational,
				pays_fee: Pays::Yes,
			assert_eq!(Module::<Runtime>::compute_fee(0, &dispatch_info, 0), 1100);
		});
	}

	#[test]
	fn compute_fee_works_with_multiplier() {
		ExtBuilder::default()
			.byte_fee(10)
			.balance_factor(0)
			.build()
			.execute_with(||
			// Add a next fee multiplier. Fees will be x3/2.
			NextFeeMultiplier::put(Multiplier::saturating_from_rational(3, 2));
			// Base fee is unaffected by multiplier
			let dispatch_info = DispatchInfo {
				weight: 0,
				class: DispatchClass::Operational,
				pays_fee: Pays::Yes,
			assert_eq!(Module::<Runtime>::compute_fee(0, &dispatch_info, 0), 100);

			// Everything works together :)
			let dispatch_info = DispatchInfo {
				weight: 123,
				class: DispatchClass::Operational,
				pays_fee: Pays::Yes,
			};
			// 123 weight, 456 length, 100 base
			assert_eq!(
				Module::<Runtime>::compute_fee(456, &dispatch_info, 789),
				100 + (3 * 123 / 2) + 4560 + 789,
			);
	#[test]
	fn compute_fee_works_with_negative_multiplier() {
		ExtBuilder::default()
			.base_weight(100)
			.byte_fee(10)
			.balance_factor(0)
			.build()
			.execute_with(||
		{
			// Add a next fee multiplier. All fees will be x1/2.
			NextFeeMultiplier::put(Multiplier::saturating_from_rational(1, 2));

			// Base fee is unaffected by multiplier.
			let dispatch_info = DispatchInfo {
				weight: 0,
				class: DispatchClass::Operational,
				pays_fee: Pays::Yes,
			};
			assert_eq!(Module::<Runtime>::compute_fee(0, &dispatch_info, 0), 100);

			// Everything works together.
			let dispatch_info = DispatchInfo {
				weight: 123,
				class: DispatchClass::Operational,
				pays_fee: Pays::Yes,
			};
			// 123 weight, 456 length, 100 base
			assert_eq!(
				Module::<Runtime>::compute_fee(456, &dispatch_info, 789),
				100 + (123 / 2) + 4560 + 789,
			);
	#[test]
	fn compute_fee_does_not_overflow() {
		ExtBuilder::default()
			.byte_fee(10)
			.balance_factor(0)
			.build()
			.execute_with(||
		{
			// Overflow is handled
			let dispatch_info = DispatchInfo {
				weight: Weight::max_value(),
				class: DispatchClass::Operational,
				pays_fee: Pays::Yes,
			};
			assert_eq!(
				Module::<Runtime>::compute_fee(
					<u32>::max_value(),
					&dispatch_info,
					<u64>::max_value()
				),
				<u64>::max_value()
			);
		});
	}

	#[test]
	fn refund_does_not_recreate_account() {
		ExtBuilder::default()
			.balance_factor(10)
			.build()
			.execute_with(||
		{
			// So events are emitted
			System::set_block_number(10);
			let len = 10;
			let pre = ChargeTransactionPayment::<Runtime>::from(5 /* tipped */)
				.pre_dispatch(&2, CALL, &info_from_weight(100), len)
				.unwrap();
			assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5);

			// kill the account between pre and post dispatch
			assert!(Balances::transfer(Some(2).into(), 3, Balances::free_balance(2)).is_ok());
			assert_eq!(Balances::free_balance(2), 0);

			assert!(
				ChargeTransactionPayment::<Runtime>
					::post_dispatch(pre, &info_from_weight(100), &post_info_from_weight(50), len, &Ok(()))
					.is_ok()
			);
			assert_eq!(Balances::free_balance(2), 0);
			// Transfer Event
			assert!(System::events().iter().any(|event| {
				event.event == Event::pallet_balances(pallet_balances::RawEvent::Transfer(2, 3, 80))
			}));
			// Killed Event
			assert!(System::events().iter().any(|event| {
				event.event == Event::system(system::RawEvent::KilledAccount(2))
			}));
		});
	}

	#[test]
	fn actual_weight_higher_than_max_refunds_nothing() {
		ExtBuilder::default()
			.balance_factor(10)
			.build()
			.execute_with(||
		{
			let len = 10;
			let pre = ChargeTransactionPayment::<Runtime>::from(5 /* tipped */)
				.pre_dispatch(&2, CALL, &info_from_weight(100), len)
				.unwrap();
			assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5);

			assert!(
				ChargeTransactionPayment::<Runtime>
					::post_dispatch(pre, &info_from_weight(100), &post_info_from_weight(101), len, &Ok(()))
					.is_ok()
			);
			assert_eq!(Balances::free_balance(2), 200 - 5 - 10 - 100 - 5);
		});
	}

	#[test]
	fn zero_transfer_on_free_transaction() {
		ExtBuilder::default()
			.balance_factor(10)
			.base_weight(5)
			.build()
			.execute_with(||
		{
			// So events are emitted
			System::set_block_number(10);
			let len = 10;
			let dispatch_info = DispatchInfo {
				weight: 100,
				pays_fee: Pays::No,
				class: DispatchClass::Normal,
			};
			let user = 69;
			let pre = ChargeTransactionPayment::<Runtime>::from(0)
				.pre_dispatch(&user, CALL, &dispatch_info, len)
				.unwrap();
			assert_eq!(Balances::total_balance(&user), 0);
			assert!(
				ChargeTransactionPayment::<Runtime>
					::post_dispatch(pre, &dispatch_info, &default_post_info(), len, &Ok(()))
					.is_ok()
			);
			assert_eq!(Balances::total_balance(&user), 0);
			// No events for such a scenario
			assert_eq!(System::events().len(), 0);
		});
	}

	#[test]
	fn refund_consistent_with_actual_weight() {
		ExtBuilder::default()
			.balance_factor(10)
			.base_weight(7)
			.build()
			.execute_with(||
		{
			let info = info_from_weight(100);
			let post_info = post_info_from_weight(33);
			let prev_balance = Balances::free_balance(2);
			let len = 10;
			let tip = 5;

			NextFeeMultiplier::put(Multiplier::saturating_from_rational(5, 4));

			let pre = ChargeTransactionPayment::<Runtime>::from(tip)
				.pre_dispatch(&2, CALL, &info, len)
				.unwrap();

			ChargeTransactionPayment::<Runtime>
				::post_dispatch(pre, &info, &post_info, len, &Ok(()))
				.unwrap();

			let refund_based_fee = prev_balance - Balances::free_balance(2);
			let actual_fee = Module::<Runtime>
				::compute_actual_fee(len as u32, &info, &post_info, tip);

			// 33 weight, 10 length, 7 base, 5 tip
			assert_eq!(actual_fee, 7 + 10 + (33 * 5 / 4) + 5);
			assert_eq!(refund_based_fee, actual_fee);
		});
	}

	#[test]
	fn post_info_can_change_pays_fee() {
		ExtBuilder::default()
			.balance_factor(10)
			.base_weight(7)
			.build()
			.execute_with(||
		{
			let info = info_from_weight(100);
			let post_info = post_info_from_pays(Pays::No);
			let prev_balance = Balances::free_balance(2);
			let len = 10;
			let tip = 5;

			NextFeeMultiplier::put(Multiplier::saturating_from_rational(5, 4));

			let pre = ChargeTransactionPayment::<Runtime>::from(tip)
				.pre_dispatch(&2, CALL, &info, len)
				.unwrap();

			ChargeTransactionPayment::<Runtime>
				::post_dispatch(pre, &info, &post_info, len, &Ok(()))
				.unwrap();

			let refund_based_fee = prev_balance - Balances::free_balance(2);
			let actual_fee = Module::<Runtime>
				::compute_actual_fee(len as u32, &info, &post_info, tip);

			// Only 5 tip is paid
			assert_eq!(actual_fee, 5);
			assert_eq!(refund_based_fee, actual_fee);
		});
	}