diff --git a/aptos-move/framework/aptos-framework/doc/aptos_account.md b/aptos-move/framework/aptos-framework/doc/aptos_account.md index 4777da7049787e..1da8a517b74be0 100644 --- a/aptos-move/framework/aptos-framework/doc/aptos_account.md +++ b/aptos-move/framework/aptos-framework/doc/aptos_account.md @@ -25,7 +25,7 @@ - [Function `register_apt`](#0x1_aptos_account_register_apt) - [Function `fungible_transfer_only`](#0x1_aptos_account_fungible_transfer_only) - [Function `is_fungible_balance_at_least`](#0x1_aptos_account_is_fungible_balance_at_least) -- [Function `burn_from_fungible_store`](#0x1_aptos_account_burn_from_fungible_store) +- [Function `burn_from_fungible_store_for_gas`](#0x1_aptos_account_burn_from_fungible_store_for_gas) - [Function `ensure_primary_fungible_store_exists`](#0x1_aptos_account_ensure_primary_fungible_store_exists) - [Function `primary_fungible_store_address`](#0x1_aptos_account_primary_fungible_store_address) - [Specification](#@Specification_1) @@ -47,7 +47,7 @@ - [Function `register_apt`](#@Specification_1_register_apt) - [Function `fungible_transfer_only`](#@Specification_1_fungible_transfer_only) - [Function `is_fungible_balance_at_least`](#@Specification_1_is_fungible_balance_at_least) - - [Function `burn_from_fungible_store`](#@Specification_1_burn_from_fungible_store) + - [Function `burn_from_fungible_store_for_gas`](#@Specification_1_burn_from_fungible_store_for_gas)
use 0x1::account;
@@ -707,7 +707,7 @@ to transfer APT) - if we want to allow APT PFS without account itself
     // as APT cannot be frozen or have dispatch, and PFS cannot be transfered
     // (PFS could potentially be burned. regular transfer would permanently unburn the store.
     // Ignoring the check here has the equivalent of unburning, transfers, and then burning again)
-    fungible_asset::deposit_internal(recipient_store, fungible_asset::withdraw_internal(sender_store, amount));
+    fungible_asset::raw_deposit(recipient_store, fungible_asset::unchecked_withdraw(sender_store, amount));
 }
 
@@ -741,14 +741,14 @@ Is balance from APT Primary FungibleStore at least the given amount - + -## Function `burn_from_fungible_store` +## Function `burn_from_fungible_store_for_gas` -Burn from APT Primary FungibleStore +Burn gas from APT Primary FungibleStore -
public(friend) fun burn_from_fungible_store(ref: &fungible_asset::BurnRef, account: address, amount: u64)
+
public(friend) fun burn_from_fungible_store_for_gas(ref: &fungible_asset::BurnRef, account: address, amount: u64)
 
@@ -757,7 +757,7 @@ Burn from APT Primary FungibleStore Implementation -
public(friend) fun burn_from_fungible_store(
+
public(friend) fun burn_from_fungible_store_for_gas(
     ref: &BurnRef,
     account: address,
     amount: u64,
@@ -765,7 +765,7 @@ Burn from APT Primary FungibleStore
     // Skip burning if amount is zero. This shouldn't error out as it's called as part of transaction fee burning.
     if (amount != 0) {
         let store_addr = primary_fungible_store_address(account);
-        fungible_asset::address_burn_from(ref, store_addr, amount);
+        fungible_asset::address_burn_from_for_gas(ref, store_addr, amount);
     };
 }
 
@@ -1294,12 +1294,12 @@ Check if the AptosCoin under the address existed. - + -### Function `burn_from_fungible_store` +### Function `burn_from_fungible_store_for_gas` -
public(friend) fun burn_from_fungible_store(ref: &fungible_asset::BurnRef, account: address, amount: u64)
+
public(friend) fun burn_from_fungible_store_for_gas(ref: &fungible_asset::BurnRef, account: address, amount: u64)
 
diff --git a/aptos-move/framework/aptos-framework/doc/coin.md b/aptos-move/framework/aptos-framework/doc/coin.md index 273f2a2f3e1f02..45f4e16441d7e7 100644 --- a/aptos-move/framework/aptos-framework/doc/coin.md +++ b/aptos-move/framework/aptos-framework/doc/coin.md @@ -2538,9 +2538,12 @@ Note: This bypasses CoinStore::frozen -- coins within a frozen CoinStore can be burn(coin_to_burn, burn_cap); }; if (fa_amount_to_burn > 0) { - fungible_asset::burn_from( + fungible_asset::address_burn_from_for_gas( borrow_paired_burn_ref(burn_cap), - primary_fungible_store::primary_store(account_addr, option::destroy_some(paired_metadata<CoinType>())), + primary_fungible_store::primary_store_address( + account_addr, + option::destroy_some(paired_metadata<CoinType>()) + ), fa_amount_to_burn ); }; @@ -2670,7 +2673,7 @@ This is for internal use only and doesn't emit an DepositEvent. let fa = coin_to_fungible_asset(coin); let metadata = fungible_asset::asset_metadata(&fa); let store = primary_fungible_store::primary_store(account_addr, metadata); - fungible_asset::deposit_internal(object::object_address(&store), fa); + fungible_asset::deposit_to_for_gas(object::object_address(&store), fa); } else { abort error::not_found(ECOIN_STORE_NOT_PUBLISHED) } diff --git a/aptos-move/framework/aptos-framework/doc/dispatchable_fungible_asset.md b/aptos-move/framework/aptos-framework/doc/dispatchable_fungible_asset.md index b3b76f108128ca..773d868ee0ec16 100644 --- a/aptos-move/framework/aptos-framework/doc/dispatchable_fungible_asset.md +++ b/aptos-move/framework/aptos-framework/doc/dispatchable_fungible_asset.md @@ -239,7 +239,7 @@ The semantics of deposit will be governed by the function specified in DispatchF assert!(amount <= start_balance - end_balance, error::aborted(EAMOUNT_MISMATCH)); fa } else { - fungible_asset::withdraw_internal(object::object_address(&store), amount) + fungible_asset::unchecked_withdraw(object::object_address(&store), amount) } }
@@ -283,7 +283,7 @@ The semantics of deposit will be governed by the function specified in DispatchF func ) } else { - fungible_asset::deposit_internal(object::object_address(&store), fa) + fungible_asset::raw_deposit(object::object_address(&store), fa) } }
diff --git a/aptos-move/framework/aptos-framework/doc/fungible_asset.md b/aptos-move/framework/aptos-framework/doc/fungible_asset.md index 17ee3056667dad..c5a8c0f1aee541 100644 --- a/aptos-move/framework/aptos-framework/doc/fungible_asset.md +++ b/aptos-move/framework/aptos-framework/doc/fungible_asset.md @@ -23,6 +23,8 @@ metadata object can be any object that equipped with + +## Struct `GasBurnt` + + + +
#[event]
+struct GasBurnt has drop, store
+
+ + + +
+Fields + + +
+
+store: address +
+
+ +
+
+amount: u64 +
+
+ +
+
+ + +
+ + + +## Struct `GasRefunded` + + + +
#[event]
+struct GasRefunded has drop, store
+
+ + + +
+Fields + + +
+
+store: address +
+
+ +
+
+amount: u64 +
+
+ +
+
+ +
@@ -2675,7 +2748,7 @@ Withdraw amount of the fungible asset from store by th amount: u64, ): FungibleAsset acquires FungibleStore, DispatchFunctionStore, ConcurrentFungibleBalance { withdraw_sanity_check(owner, store, true); - withdraw_internal(object::object_address(&store), amount) + unchecked_withdraw(object::object_address(&store), amount) }
@@ -2769,7 +2842,7 @@ Deposit amount of the fungible asset to store.
public fun deposit<T: key>(store: Object<T>, fa: FungibleAsset) acquires FungibleStore, DispatchFunctionStore, ConcurrentFungibleBalance {
     deposit_sanity_check(store, true);
-    deposit_internal(object::object_address(&store), fa);
+    raw_deposit(object::object_address(&store), fa);
 }
 
@@ -2854,7 +2927,7 @@ Mint the specified amount of the fungible asset to a destination st
public fun mint_to<T: key>(ref: &MintRef, store: Object<T>, amount: u64)
 acquires FungibleStore, Supply, ConcurrentSupply, DispatchFunctionStore, ConcurrentFungibleBalance {
     deposit_sanity_check(store, false);
-    deposit_internal(object::object_address(&store), mint(ref, amount));
+    raw_deposit(object::object_address(&store), mint(ref, amount));
 }
 
@@ -3008,7 +3081,7 @@ Burn the amount of the fungible asset from the given store. amount: u64 ) acquires FungibleStore, Supply, ConcurrentSupply, ConcurrentFungibleBalance { // ref metadata match is checked in burn() call - burn(ref, withdraw_internal(object::object_address(&store), amount)); + burn(ref, raw_withdraw_internal(object::object_address(&store), amount)); } @@ -3016,13 +3089,13 @@ Burn the amount of the fungible asset from the given store. - + -## Function `address_burn_from` +## Function `address_burn_from_for_gas` -
public(friend) fun address_burn_from(ref: &fungible_asset::BurnRef, store_addr: address, amount: u64)
+
public(friend) fun address_burn_from_for_gas(ref: &fungible_asset::BurnRef, store_addr: address, amount: u64)
 
@@ -3031,13 +3104,14 @@ Burn the amount of the fungible asset from the given store. Implementation -
public(friend) fun address_burn_from(
+
public(friend) fun address_burn_from_for_gas(
     ref: &BurnRef,
     store_addr: address,
     amount: u64
 ) acquires FungibleStore, Supply, ConcurrentSupply, ConcurrentFungibleBalance {
     // ref metadata match is checked in burn() call
-    burn(ref, withdraw_internal(store_addr, amount));
+    burn(ref, raw_withdraw_internal(store_addr, amount));
+    event::emit(GasBurnt { store: store_addr, amount })
 }
 
@@ -3070,7 +3144,7 @@ Withdraw amount of the fungible asset from the store i ref.metadata == store_metadata(store), error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH), ); - withdraw_internal(object::object_address(&store), amount) + unchecked_withdraw(object::object_address(&store), amount) }
@@ -3103,7 +3177,7 @@ Deposit the fungible asset into the store ignoring frozenerror::invalid_argument(ETRANSFER_REF_AND_FUNGIBLE_ASSET_MISMATCH) ); - deposit_internal(object::object_address(&store), fa); + raw_deposit(object::object_address(&store), fa); }
@@ -3314,13 +3388,13 @@ Destroy an empty fungible asset. - + -## Function `deposit_internal` +## Function `unchecked_deposit_with_no_events` -
public(friend) fun deposit_internal(store_addr: address, fa: fungible_asset::FungibleAsset)
+
fun unchecked_deposit_with_no_events(store_addr: address, fa: fungible_asset::FungibleAsset)
 
@@ -3329,22 +3403,51 @@ Destroy an empty fungible asset. Implementation -
public(friend) fun deposit_internal(store_addr: address, fa: FungibleAsset) acquires FungibleStore, ConcurrentFungibleBalance {
+
inline fun unchecked_deposit_with_no_events(
+    store_addr: address,
+    fa: FungibleAsset
+) acquires FungibleStore, ConcurrentFungibleBalance {
     let FungibleAsset { metadata, amount } = fa;
     assert!(exists<FungibleStore>(store_addr), error::not_found(EFUNGIBLE_STORE_EXISTENCE));
     let store = borrow_global_mut<FungibleStore>(store_addr);
     assert!(metadata == store.metadata, error::invalid_argument(EFUNGIBLE_ASSET_AND_STORE_MISMATCH));
 
-    if (amount == 0) return;
+    if (amount != 0) {
+        if (store.balance == 0 && concurrent_fungible_balance_exists_inline(store_addr)) {
+            let balance_resource = borrow_global_mut<ConcurrentFungibleBalance>(store_addr);
+            aggregator_v2::add(&mut balance_resource.balance, amount);
+        } else {
+            store.balance = store.balance + amount;
+        };
+    }
+}
+
+ - if (store.balance == 0 && concurrent_fungible_balance_exists_inline(store_addr)) { - let balance_resource = borrow_global_mut<ConcurrentFungibleBalance>(store_addr); - aggregator_v2::add(&mut balance_resource.balance, amount); - } else { - store.balance = store.balance + amount; - }; - event::emit(Deposit { store: store_addr, amount }); + + + + +## Function `raw_deposit` + + + +
public(friend) fun raw_deposit(store_addr: address, fa: fungible_asset::FungibleAsset)
+
+ + + +
+Implementation + + +
public(friend) fun raw_deposit(
+    store_addr: address,
+    fa: FungibleAsset
+) acquires FungibleStore, ConcurrentFungibleBalance {
+    event::emit(Deposit { store: store_addr, amount: fa.amount });
+    unchecked_deposit_with_no_events(store_addr, fa);
 }
 
@@ -3352,14 +3455,13 @@ Destroy an empty fungible asset.
- + -## Function `withdraw_internal` +## Function `deposit_to_for_gas` -Extract amount of the fungible asset from store. -
public(friend) fun withdraw_internal(store_addr: address, amount: u64): fungible_asset::FungibleAsset
+
public(friend) fun deposit_to_for_gas(store_addr: address, fa: fungible_asset::FungibleAsset)
 
@@ -3368,7 +3470,67 @@ Extract amount of the fungible asset from store. Implementation -
public(friend) fun withdraw_internal(
+
public(friend) fun deposit_to_for_gas(
+    store_addr: address,
+    fa: FungibleAsset
+) acquires FungibleStore, ConcurrentFungibleBalance {
+    event::emit(GasRefunded { store: store_addr, amount: fa.amount });
+    unchecked_deposit_with_no_events(store_addr, fa);
+}
+
+ + + + + + + +## Function `unchecked_withdraw` + +Extract amount of the fungible asset from store emitting event. + + +
public(friend) fun unchecked_withdraw(store_addr: address, amount: u64): fungible_asset::FungibleAsset
+
+ + + +
+Implementation + + +
public(friend) fun unchecked_withdraw(
+    store_addr: address,
+    amount: u64
+): FungibleAsset acquires FungibleStore, ConcurrentFungibleBalance {
+    if (amount != 0) {
+        event::emit<Withdraw>(Withdraw { store: store_addr, amount });
+    };
+    raw_withdraw_internal(store_addr, amount)
+}
+
+ + + +
+ + + +## Function `raw_withdraw_internal` + +Extract amount of the fungible asset from store w/o emitting event. + + +
fun raw_withdraw_internal(store_addr: address, amount: u64): fungible_asset::FungibleAsset
+
+ + + +
+Implementation + + +
inline fun raw_withdraw_internal(
     store_addr: address,
     amount: u64,
 ): FungibleAsset acquires FungibleStore, ConcurrentFungibleBalance {
@@ -3387,8 +3549,6 @@ Extract amount of the fungible asset from store.
             assert!(store.balance >= amount, error::invalid_argument(EINSUFFICIENT_BALANCE));
             store.balance = store.balance - amount;
         };
-
-        event::emit<Withdraw>(Withdraw { store: store_addr, amount });
     };
     FungibleAsset { metadata, amount }
 }
diff --git a/aptos-move/framework/aptos-framework/doc/primary_fungible_store.md b/aptos-move/framework/aptos-framework/doc/primary_fungible_store.md
index 28b1374e4f850c..a3e8609af7faef 100644
--- a/aptos-move/framework/aptos-framework/doc/primary_fungible_store.md
+++ b/aptos-move/framework/aptos-framework/doc/primary_fungible_store.md
@@ -528,7 +528,7 @@ Deposit fungible asset fa to the given account's primary store.
 
public(friend) fun force_deposit(owner: address, fa: FungibleAsset) acquires DeriveRefPod {
     let metadata = fungible_asset::asset_metadata(&fa);
     let store = ensure_primary_store_exists(owner, metadata);
-    fungible_asset::deposit_internal(object::object_address(&store), fa);
+    fungible_asset::raw_deposit(object::object_address(&store), fa);
 }
 
diff --git a/aptos-move/framework/aptos-framework/doc/transaction_fee.md b/aptos-move/framework/aptos-framework/doc/transaction_fee.md index b672fe413d52e6..80cd7e93360bea 100644 --- a/aptos-move/framework/aptos-framework/doc/transaction_fee.md +++ b/aptos-move/framework/aptos-framework/doc/transaction_fee.md @@ -309,12 +309,12 @@ Burn transaction fees in epilogue.
public(friend) fun burn_fee(account: address, fee: u64) acquires AptosFABurnCapabilities, AptosCoinCapabilities {
     if (exists<AptosFABurnCapabilities>(@aptos_framework)) {
         let burn_ref = &borrow_global<AptosFABurnCapabilities>(@aptos_framework).burn_ref;
-        aptos_account::burn_from_fungible_store(burn_ref, account, fee);
+        aptos_account::burn_from_fungible_store_for_gas(burn_ref, account, fee);
     } else {
         let burn_cap = &borrow_global<AptosCoinCapabilities>(@aptos_framework).burn_cap;
         if (features::operations_default_to_fa_apt_store_enabled()) {
             let (burn_ref, burn_receipt) = coin::get_paired_burn_ref(burn_cap);
-            aptos_account::burn_from_fungible_store(&burn_ref, account, fee);
+            aptos_account::burn_from_fungible_store_for_gas(&burn_ref, account, fee);
             coin::return_paired_burn_ref(burn_ref, burn_receipt);
         } else {
             coin::burn_from<AptosCoin>(
diff --git a/aptos-move/framework/aptos-framework/sources/aptos_account.move b/aptos-move/framework/aptos-framework/sources/aptos_account.move
index d18abf21251866..6cfd96b43d43f0 100644
--- a/aptos-move/framework/aptos-framework/sources/aptos_account.move
+++ b/aptos-move/framework/aptos-framework/sources/aptos_account.move
@@ -247,7 +247,7 @@ module aptos_framework::aptos_account {
         // as APT cannot be frozen or have dispatch, and PFS cannot be transfered
         // (PFS could potentially be burned. regular transfer would permanently unburn the store.
         // Ignoring the check here has the equivalent of unburning, transfers, and then burning again)
-        fungible_asset::deposit_internal(recipient_store, fungible_asset::withdraw_internal(sender_store, amount));
+        fungible_asset::raw_deposit(recipient_store, fungible_asset::unchecked_withdraw(sender_store, amount));
     }
 
     /// Is balance from APT Primary FungibleStore at least the given amount
@@ -256,8 +256,8 @@ module aptos_framework::aptos_account {
         fungible_asset::is_address_balance_at_least(store_addr, amount)
     }
 
-    /// Burn from APT Primary FungibleStore
-    public(friend) fun burn_from_fungible_store(
+    /// Burn gas from APT Primary FungibleStore
+    public(friend) fun burn_from_fungible_store_for_gas(
         ref: &BurnRef,
         account: address,
         amount: u64,
@@ -265,7 +265,7 @@ module aptos_framework::aptos_account {
         // Skip burning if amount is zero. This shouldn't error out as it's called as part of transaction fee burning.
         if (amount != 0) {
             let store_addr = primary_fungible_store_address(account);
-            fungible_asset::address_burn_from(ref, store_addr, amount);
+            fungible_asset::address_burn_from_for_gas(ref, store_addr, amount);
         };
     }
 
diff --git a/aptos-move/framework/aptos-framework/sources/aptos_account.spec.move b/aptos-move/framework/aptos-framework/sources/aptos_account.spec.move
index 7c628496755127..163a62ea9ae2d9 100644
--- a/aptos-move/framework/aptos-framework/sources/aptos_account.spec.move
+++ b/aptos-move/framework/aptos-framework/sources/aptos_account.spec.move
@@ -282,7 +282,7 @@ spec aptos_framework::aptos_account {
         pragma verify = false;
     }
 
-    spec burn_from_fungible_store(
+    spec burn_from_fungible_store_for_gas(
         ref: &BurnRef,
         account: address,
         amount: u64,
diff --git a/aptos-move/framework/aptos-framework/sources/coin.move b/aptos-move/framework/aptos-framework/sources/coin.move
index f1d9a819627855..6c8b9cdadf2549 100644
--- a/aptos-move/framework/aptos-framework/sources/coin.move
+++ b/aptos-move/framework/aptos-framework/sources/coin.move
@@ -779,9 +779,12 @@ module aptos_framework::coin {
             burn(coin_to_burn, burn_cap);
         };
         if (fa_amount_to_burn > 0) {
-            fungible_asset::burn_from(
+            fungible_asset::address_burn_from_for_gas(
                 borrow_paired_burn_ref(burn_cap),
-                primary_fungible_store::primary_store(account_addr, option::destroy_some(paired_metadata())),
+                primary_fungible_store::primary_store_address(
+                    account_addr,
+                    option::destroy_some(paired_metadata())
+                ),
                 fa_amount_to_burn
             );
         };
@@ -851,7 +854,7 @@ module aptos_framework::coin {
                 let fa = coin_to_fungible_asset(coin);
                 let metadata = fungible_asset::asset_metadata(&fa);
                 let store = primary_fungible_store::primary_store(account_addr, metadata);
-                fungible_asset::deposit_internal(object::object_address(&store), fa);
+                fungible_asset::deposit_to_for_gas(object::object_address(&store), fa);
             } else {
                 abort error::not_found(ECOIN_STORE_NOT_PUBLISHED)
             }
diff --git a/aptos-move/framework/aptos-framework/sources/dispatchable_fungible_asset.move b/aptos-move/framework/aptos-framework/sources/dispatchable_fungible_asset.move
index 5a70aff95d2c11..18835a15b81eb5 100644
--- a/aptos-move/framework/aptos-framework/sources/dispatchable_fungible_asset.move
+++ b/aptos-move/framework/aptos-framework/sources/dispatchable_fungible_asset.move
@@ -96,7 +96,7 @@ module aptos_framework::dispatchable_fungible_asset {
             assert!(amount <= start_balance - end_balance, error::aborted(EAMOUNT_MISMATCH));
             fa
         } else {
-            fungible_asset::withdraw_internal(object::object_address(&store), amount)
+            fungible_asset::unchecked_withdraw(object::object_address(&store), amount)
         }
     }
 
@@ -120,7 +120,7 @@ module aptos_framework::dispatchable_fungible_asset {
                 func
             )
         } else {
-            fungible_asset::deposit_internal(object::object_address(&store), fa)
+            fungible_asset::raw_deposit(object::object_address(&store), fa)
         }
     }
 
diff --git a/aptos-move/framework/aptos-framework/sources/fungible_asset.move b/aptos-move/framework/aptos-framework/sources/fungible_asset.move
index 50a77348c630c8..cfa395d5347fa8 100644
--- a/aptos-move/framework/aptos-framework/sources/fungible_asset.move
+++ b/aptos-move/framework/aptos-framework/sources/fungible_asset.move
@@ -215,6 +215,18 @@ module aptos_framework::fungible_asset {
         frozen: bool,
     }
 
+    #[event]
+    struct GasBurnt has drop, store {
+        store: address,
+        amount: u64,
+    }
+
+    #[event]
+    struct GasRefunded has drop, store {
+        store: address,
+        amount: u64,
+    }
+
     inline fun default_to_concurrent_fungible_supply(): bool {
         features::concurrent_fungible_assets_enabled()
     }
@@ -785,7 +797,7 @@ module aptos_framework::fungible_asset {
         amount: u64,
     ): FungibleAsset acquires FungibleStore, DispatchFunctionStore, ConcurrentFungibleBalance {
         withdraw_sanity_check(owner, store, true);
-        withdraw_internal(object::object_address(&store), amount)
+        unchecked_withdraw(object::object_address(&store), amount)
     }
 
     /// Check the permission for withdraw operation.
@@ -819,7 +831,7 @@ module aptos_framework::fungible_asset {
     /// Deposit `amount` of the fungible asset to `store`.
     public fun deposit(store: Object, fa: FungibleAsset) acquires FungibleStore, DispatchFunctionStore, ConcurrentFungibleBalance {
         deposit_sanity_check(store, true);
-        deposit_internal(object::object_address(&store), fa);
+        raw_deposit(object::object_address(&store), fa);
     }
 
     /// Mint the specified `amount` of the fungible asset.
@@ -844,7 +856,7 @@ module aptos_framework::fungible_asset {
     public fun mint_to(ref: &MintRef, store: Object, amount: u64)
     acquires FungibleStore, Supply, ConcurrentSupply, DispatchFunctionStore, ConcurrentFungibleBalance {
         deposit_sanity_check(store, false);
-        deposit_internal(object::object_address(&store), mint(ref, amount));
+        raw_deposit(object::object_address(&store), mint(ref, amount));
     }
 
     /// Enable/disable a store's ability to do direct transfers of the fungible asset.
@@ -898,16 +910,17 @@ module aptos_framework::fungible_asset {
         amount: u64
     ) acquires FungibleStore, Supply, ConcurrentSupply, ConcurrentFungibleBalance {
         // ref metadata match is checked in burn() call
-        burn(ref, withdraw_internal(object::object_address(&store), amount));
+        burn(ref, raw_withdraw_internal(object::object_address(&store), amount));
     }
 
-    public(friend) fun address_burn_from(
+    public(friend) fun address_burn_from_for_gas(
         ref: &BurnRef,
         store_addr: address,
         amount: u64
     ) acquires FungibleStore, Supply, ConcurrentSupply, ConcurrentFungibleBalance {
         // ref metadata match is checked in burn() call
-        burn(ref, withdraw_internal(store_addr, amount));
+        burn(ref, raw_withdraw_internal(store_addr, amount));
+        event::emit(GasBurnt { store: store_addr, amount })
     }
 
     /// Withdraw `amount` of the fungible asset from the `store` ignoring `frozen`.
@@ -920,7 +933,7 @@ module aptos_framework::fungible_asset {
             ref.metadata == store_metadata(store),
             error::invalid_argument(ETRANSFER_REF_AND_STORE_MISMATCH),
         );
-        withdraw_internal(object::object_address(&store), amount)
+        unchecked_withdraw(object::object_address(&store), amount)
     }
 
     /// Deposit the fungible asset into the `store` ignoring `frozen`.
@@ -933,7 +946,7 @@ module aptos_framework::fungible_asset {
             ref.metadata == fa.metadata,
             error::invalid_argument(ETRANSFER_REF_AND_FUNGIBLE_ASSET_MISMATCH)
         );
-        deposit_internal(object::object_address(&store), fa);
+        raw_deposit(object::object_address(&store), fa);
     }
 
     /// Transfer `amount` of the fungible asset with `TransferRef` even it is frozen.
@@ -1019,26 +1032,54 @@ module aptos_framework::fungible_asset {
         assert!(amount == 0, error::invalid_argument(EAMOUNT_IS_NOT_ZERO));
     }
 
-    public(friend) fun deposit_internal(store_addr: address, fa: FungibleAsset) acquires FungibleStore, ConcurrentFungibleBalance {
+    inline fun unchecked_deposit_with_no_events(
+        store_addr: address,
+        fa: FungibleAsset
+    ) acquires FungibleStore, ConcurrentFungibleBalance {
         let FungibleAsset { metadata, amount } = fa;
         assert!(exists(store_addr), error::not_found(EFUNGIBLE_STORE_EXISTENCE));
         let store = borrow_global_mut(store_addr);
         assert!(metadata == store.metadata, error::invalid_argument(EFUNGIBLE_ASSET_AND_STORE_MISMATCH));
 
-        if (amount == 0) return;
+        if (amount != 0) {
+            if (store.balance == 0 && concurrent_fungible_balance_exists_inline(store_addr)) {
+                let balance_resource = borrow_global_mut(store_addr);
+                aggregator_v2::add(&mut balance_resource.balance, amount);
+            } else {
+                store.balance = store.balance + amount;
+            };
+        }
+    }
 
-        if (store.balance == 0 && concurrent_fungible_balance_exists_inline(store_addr)) {
-            let balance_resource = borrow_global_mut(store_addr);
-            aggregator_v2::add(&mut balance_resource.balance, amount);
-        } else {
-            store.balance = store.balance + amount;
-        };
+    public(friend) fun raw_deposit(
+        store_addr: address,
+        fa: FungibleAsset
+    ) acquires FungibleStore, ConcurrentFungibleBalance {
+        event::emit(Deposit { store: store_addr, amount: fa.amount });
+        unchecked_deposit_with_no_events(store_addr, fa);
+    }
 
-        event::emit(Deposit { store: store_addr, amount });
+    public(friend) fun deposit_to_for_gas(
+        store_addr: address,
+        fa: FungibleAsset
+    ) acquires FungibleStore, ConcurrentFungibleBalance {
+        event::emit(GasRefunded { store: store_addr, amount: fa.amount });
+        unchecked_deposit_with_no_events(store_addr, fa);
     }
 
-    /// Extract `amount` of the fungible asset from `store`.
-    public(friend) fun withdraw_internal(
+    /// Extract `amount` of the fungible asset from `store` emitting event.
+    public(friend) fun unchecked_withdraw(
+        store_addr: address,
+        amount: u64
+    ): FungibleAsset acquires FungibleStore, ConcurrentFungibleBalance {
+        if (amount != 0) {
+            event::emit(Withdraw { store: store_addr, amount });
+        };
+        raw_withdraw_internal(store_addr, amount)
+    }
+
+    /// Extract `amount` of the fungible asset from `store` w/o emitting event.
+    inline fun raw_withdraw_internal(
         store_addr: address,
         amount: u64,
     ): FungibleAsset acquires FungibleStore, ConcurrentFungibleBalance {
@@ -1057,8 +1098,6 @@ module aptos_framework::fungible_asset {
                 assert!(store.balance >= amount, error::invalid_argument(EINSUFFICIENT_BALANCE));
                 store.balance = store.balance - amount;
             };
-
-            event::emit(Withdraw { store: store_addr, amount });
         };
         FungibleAsset { metadata, amount }
     }
diff --git a/aptos-move/framework/aptos-framework/sources/primary_fungible_store.move b/aptos-move/framework/aptos-framework/sources/primary_fungible_store.move
index 9e39b97fa2854d..d9f27c0ecf26cb 100644
--- a/aptos-move/framework/aptos-framework/sources/primary_fungible_store.move
+++ b/aptos-move/framework/aptos-framework/sources/primary_fungible_store.move
@@ -172,7 +172,7 @@ module aptos_framework::primary_fungible_store {
     public(friend) fun force_deposit(owner: address, fa: FungibleAsset) acquires DeriveRefPod {
         let metadata = fungible_asset::asset_metadata(&fa);
         let store = ensure_primary_store_exists(owner, metadata);
-        fungible_asset::deposit_internal(object::object_address(&store), fa);
+        fungible_asset::raw_deposit(object::object_address(&store), fa);
     }
 
     /// Transfer `amount` of fungible asset from sender's primary store to receiver's primary store.
diff --git a/aptos-move/framework/aptos-framework/sources/transaction_fee.move b/aptos-move/framework/aptos-framework/sources/transaction_fee.move
index 48b1ed99d6f749..a00823de050031 100644
--- a/aptos-move/framework/aptos-framework/sources/transaction_fee.move
+++ b/aptos-move/framework/aptos-framework/sources/transaction_fee.move
@@ -80,12 +80,12 @@ module aptos_framework::transaction_fee {
     public(friend) fun burn_fee(account: address, fee: u64) acquires AptosFABurnCapabilities, AptosCoinCapabilities {
         if (exists(@aptos_framework)) {
             let burn_ref = &borrow_global(@aptos_framework).burn_ref;
-            aptos_account::burn_from_fungible_store(burn_ref, account, fee);
+            aptos_account::burn_from_fungible_store_for_gas(burn_ref, account, fee);
         } else {
             let burn_cap = &borrow_global(@aptos_framework).burn_cap;
             if (features::operations_default_to_fa_apt_store_enabled()) {
                 let (burn_ref, burn_receipt) = coin::get_paired_burn_ref(burn_cap);
-                aptos_account::burn_from_fungible_store(&burn_ref, account, fee);
+                aptos_account::burn_from_fungible_store_for_gas(&burn_ref, account, fee);
                 coin::return_paired_burn_ref(burn_ref, burn_receipt);
             } else {
                 coin::burn_from(
diff --git a/execution/executor-benchmark/src/native/native_vm.rs b/execution/executor-benchmark/src/native/native_vm.rs
index 0621aebfc86481..acdfd5f6f04b22 100644
--- a/execution/executor-benchmark/src/native/native_vm.rs
+++ b/execution/executor-benchmark/src/native/native_vm.rs
@@ -28,7 +28,7 @@ use aptos_types::{
     account_config::{
         primary_apt_store, AccountResource, CoinDeposit, CoinInfoResource, CoinRegister,
         CoinStoreResource, CoinWithdraw, ConcurrentSupplyResource, DepositFAEvent,
-        FungibleStoreResource, WithdrawFAEvent,
+        FungibleStoreResource, GasBurntEvent, WithdrawFAEvent,
     },
     block_executor::{
         config::{BlockExecutorConfig, BlockExecutorConfigFromOnchain, BlockExecutorLocalConfig},
@@ -644,7 +644,7 @@ impl NativeVMExecutorTask {
                         ));
                     }
                     events.push((
-                        WithdrawFAEvent {
+                        GasBurntEvent {
                             store: sender_store_address,
                             amount: gas,
                         }
diff --git a/execution/executor-benchmark/src/native/parallel_uncoordinated_block_executor.rs b/execution/executor-benchmark/src/native/parallel_uncoordinated_block_executor.rs
index 3b364c645424a2..20c3a6527a40b6 100644
--- a/execution/executor-benchmark/src/native/parallel_uncoordinated_block_executor.rs
+++ b/execution/executor-benchmark/src/native/parallel_uncoordinated_block_executor.rs
@@ -16,7 +16,7 @@ use aptos_types::{
     account_config::{
         primary_apt_store, AccountResource, CoinDeposit, CoinInfoResource, CoinRegister,
         CoinStoreResource, CoinWithdraw, ConcurrentSupplyResource, DepositFAEvent,
-        FungibleStoreResource, WithdrawFAEvent,
+        FungibleStoreResource, GasBurntEvent, WithdrawFAEvent,
     },
     block_executor::{
         config::BlockExecutorConfigFromOnchain,
@@ -557,7 +557,7 @@ impl CommonNativeRawTransactionExecutor for NativeRawTransactionExecutor {
         }
 
         output.events.push(
-            WithdrawFAEvent {
+            GasBurntEvent {
                 store: sender_store_address,
                 amount: gas,
             }
diff --git a/types/src/account_config/events/fungible_asset.rs b/types/src/account_config/events/fungible_asset.rs
index ed003be6d64829..31a238d8e62e89 100644
--- a/types/src/account_config/events/fungible_asset.rs
+++ b/types/src/account_config/events/fungible_asset.rs
@@ -21,6 +21,20 @@ impl MoveStructType for WithdrawFAEvent {
     const STRUCT_NAME: &'static IdentStr = ident_str!("Withdraw");
 }
 
+/// Struct that represents a GasBurnt event.
+#[derive(Debug, Serialize, Deserialize)]
+pub struct GasBurntEvent {
+    pub store: AccountAddress,
+    pub amount: u64,
+}
+
+impl MoveEventV2Type for GasBurntEvent {}
+
+impl MoveStructType for GasBurntEvent {
+    const MODULE_NAME: &'static IdentStr = ident_str!("fungible_asset");
+    const STRUCT_NAME: &'static IdentStr = ident_str!("GasBurnt");
+}
+
 /// Struct that represents a Deposit event.
 #[derive(Debug, Serialize, Deserialize)]
 pub struct DepositFAEvent {