diff --git a/aptos-move/framework/aptos-framework/doc/aptos_account.md b/aptos-move/framework/aptos-framework/doc/aptos_account.md index 4777da7049787..83ec7f5c3fa10 100644 --- a/aptos-move/framework/aptos-framework/doc/aptos_account.md +++ b/aptos-move/framework/aptos-framework/doc/aptos_account.md @@ -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::raw_withdraw(sender_store, amount)); } @@ -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); }; } diff --git a/aptos-move/framework/aptos-framework/doc/coin.md b/aptos-move/framework/aptos-framework/doc/coin.md index 273f2a2f3e1f0..45f4e16441d7e 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 b3b76f108128c..4ba5882b3a7e5 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::raw_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 17ee3056667da..ddd0a024c1fad 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) + raw_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) + raw_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 `raw_deposit_internal` -
public(friend) fun deposit_internal(store_addr: address, fa: fungible_asset::FungibleAsset)
+
fun raw_deposit_internal(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 raw_deposit_internal(
+    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 });
+    raw_deposit_internal(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 });
+    raw_deposit_internal(store_addr, fa);
+}
+
+ + + + + + + +## Function `raw_withdraw` + +Extract amount of the fungible asset from store emitting event. + + +
public(friend) fun raw_withdraw(store_addr: address, amount: u64): fungible_asset::FungibleAsset
+
+ + + +
+Implementation + + +
public(friend) fun raw_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 28b1374e4f850..a3e8609af7fae 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/sources/aptos_account.move b/aptos-move/framework/aptos-framework/sources/aptos_account.move index d18abf2125186..78f2dd7d4ce38 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::raw_withdraw(sender_store, amount)); } /// Is balance from APT Primary FungibleStore at least the given amount @@ -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/coin.move b/aptos-move/framework/aptos-framework/sources/coin.move index f1d9a81962785..6c8b9cdadf254 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 5a70aff95d2c1..56c10061f1a65 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::raw_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 50a77348c630c..1b80191918b50 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) + raw_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) + raw_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 raw_deposit_internal( + 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 }); + raw_deposit_internal(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 }); + raw_deposit_internal(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 raw_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 9e39b97fa2854..d9f27c0ecf26c 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.