diff --git a/aptos-move/framework/aptos-framework/doc/coin.md b/aptos-move/framework/aptos-framework/doc/coin.md index 5ff8a32e7e2b0..cd129502aab9e 100644 --- a/aptos-move/framework/aptos-framework/doc/coin.md +++ b/aptos-move/framework/aptos-framework/doc/coin.md @@ -74,10 +74,11 @@ This module provides the foundation for typesafe Coins. - [Function `coin_supply`](#0x1_coin_coin_supply) - [Function `burn`](#0x1_coin_burn) - [Function `burn_from`](#0x1_coin_burn_from) +- [Function `burn_from_for_gas`](#0x1_coin_burn_from_for_gas) - [Function `deposit`](#0x1_coin_deposit) - [Function `deposit_with_signer`](#0x1_coin_deposit_with_signer) - [Function `can_receive_paired_fungible_asset`](#0x1_coin_can_receive_paired_fungible_asset) -- [Function `force_deposit`](#0x1_coin_force_deposit) +- [Function `deposit_for_gas_fee`](#0x1_coin_deposit_for_gas_fee) - [Function `destroy_zero`](#0x1_coin_destroy_zero) - [Function `extract`](#0x1_coin_extract) - [Function `extract_all`](#0x1_coin_extract_all) @@ -119,7 +120,7 @@ This module provides the foundation for typesafe Coins. - [Function `burn`](#@Specification_1_burn) - [Function `burn_from`](#@Specification_1_burn_from) - [Function `deposit`](#@Specification_1_deposit) - - [Function `force_deposit`](#@Specification_1_force_deposit) + - [Function `deposit_for_gas_fee`](#@Specification_1_deposit_for_gas_fee) - [Function `destroy_zero`](#@Specification_1_destroy_zero) - [Function `extract`](#@Specification_1_extract) - [Function `extract_all`](#@Specification_1_extract_all) @@ -2672,6 +2673,54 @@ Note: This bypasses CoinStore::frozen -- coins within a frozen CoinStore can be + + + + +## Function `burn_from_for_gas` + + + +
public(friend) fun burn_from_for_gas<CoinType>(account_addr: address, amount: u64, burn_cap: &coin::BurnCapability<CoinType>)
+
+ + + +
+Implementation + + +
public(friend) fun burn_from_for_gas<CoinType>(
+    account_addr: address,
+    amount: u64,
+    burn_cap: &BurnCapability<CoinType>,
+) acquires CoinInfo, CoinStore, CoinConversionMap, PairedFungibleAssetRefs {
+    // Skip burning if amount is zero. This shouldn't error out as it's called as part of transaction fee burning.
+    if (amount == 0) {
+        return
+    };
+
+    let (coin_amount_to_burn, fa_amount_to_burn) = calculate_amount_to_withdraw<CoinType>(
+        account_addr,
+        amount
+    );
+    if (coin_amount_to_burn > 0) {
+        let coin_store = borrow_global_mut<CoinStore<CoinType>>(account_addr);
+        let coin_to_burn = extract(&mut coin_store.coin, coin_amount_to_burn);
+        burn(coin_to_burn, burn_cap);
+    };
+    if (fa_amount_to_burn > 0) {
+        fungible_asset::address_burn_from_for_gas(
+            borrow_paired_burn_ref(burn_cap),
+            primary_fungible_store::primary_store_address(account_addr, option::destroy_some(paired_metadata<CoinType>())),
+            fa_amount_to_burn
+        );
+    };
+}
+
+ + +
@@ -2797,15 +2846,15 @@ Deposit the coin balance into the recipient's account and emit an event. - + -## Function `force_deposit` +## Function `deposit_for_gas_fee` Deposit the coin balance into the recipient's account without checking if the account is frozen. This is for internal use only and doesn't emit an DepositEvent. -
public(friend) fun force_deposit<CoinType>(account_addr: address, coin: coin::Coin<CoinType>)
+
public(friend) fun deposit_for_gas_fee<CoinType>(account_addr: address, coin: coin::Coin<CoinType>)
 
@@ -2814,7 +2863,7 @@ This is for internal use only and doesn't emit an DepositEvent. Implementation -
public(friend) fun force_deposit<CoinType>(
+
public(friend) fun deposit_for_gas_fee<CoinType>(
     account_addr: address,
     coin: Coin<CoinType>
 ) acquires CoinStore, CoinConversionMap, CoinInfo {
@@ -4191,12 +4240,12 @@ Get address by reflection.
 
 
 
-
+
 
-### Function `force_deposit`
+### Function `deposit_for_gas_fee`
 
 
-
public(friend) fun force_deposit<CoinType>(account_addr: address, coin: coin::Coin<CoinType>)
+
public(friend) fun deposit_for_gas_fee<CoinType>(account_addr: address, coin: coin::Coin<CoinType>)
 
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 fdc63ca6edf5a..0975d0cc739f3 100644 --- a/aptos-move/framework/aptos-framework/doc/primary_fungible_store.md +++ b/aptos-move/framework/aptos-framework/doc/primary_fungible_store.md @@ -36,7 +36,6 @@ fungible asset to it. This emits an deposit event. - [Function `withdraw`](#0x1_primary_fungible_store_withdraw) - [Function `deposit`](#0x1_primary_fungible_store_deposit) - [Function `deposit_with_signer`](#0x1_primary_fungible_store_deposit_with_signer) -- [Function `force_deposit`](#0x1_primary_fungible_store_force_deposit) - [Function `transfer`](#0x1_primary_fungible_store_transfer) - [Function `transfer_assert_minimum_deposit`](#0x1_primary_fungible_store_transfer_assert_minimum_deposit) - [Function `mint`](#0x1_primary_fungible_store_mint) @@ -615,33 +614,6 @@ the same amount of fund in the future. - - - - -## Function `force_deposit` - -Deposit fungible asset fa to the given account's primary store. - - -
public(friend) fun force_deposit(owner: address, fa: fungible_asset::FungibleAsset)
-
- - - -
-Implementation - - -
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::unchecked_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 80cd7e93360be..2c774797fda2c 100644 --- a/aptos-move/framework/aptos-framework/doc/transaction_fee.md +++ b/aptos-move/framework/aptos-framework/doc/transaction_fee.md @@ -317,7 +317,7 @@ Burn transaction fees in epilogue. 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>( + coin::burn_from_for_gas<AptosCoin>( account, fee, burn_cap, @@ -350,7 +350,7 @@ Mint refund in epilogue.
public(friend) fun mint_and_refund(account: address, refund: u64) acquires AptosCoinMintCapability {
     let mint_cap = &borrow_global<AptosCoinMintCapability>(@aptos_framework).mint_cap;
     let refund_coin = coin::mint(refund, mint_cap);
-    coin::force_deposit(account, refund_coin);
+    coin::deposit_for_gas_fee(account, refund_coin);
 }
 
diff --git a/aptos-move/framework/aptos-framework/sources/coin.move b/aptos-move/framework/aptos-framework/sources/coin.move index 159ae64b7207d..ef2c1137dc1eb 100644 --- a/aptos-move/framework/aptos-framework/sources/coin.move +++ b/aptos-move/framework/aptos-framework/sources/coin.move @@ -823,6 +823,34 @@ module aptos_framework::coin { }; } + public(friend) fun burn_from_for_gas( + account_addr: address, + amount: u64, + burn_cap: &BurnCapability, + ) acquires CoinInfo, CoinStore, CoinConversionMap, PairedFungibleAssetRefs { + // Skip burning if amount is zero. This shouldn't error out as it's called as part of transaction fee burning. + if (amount == 0) { + return + }; + + let (coin_amount_to_burn, fa_amount_to_burn) = calculate_amount_to_withdraw( + account_addr, + amount + ); + if (coin_amount_to_burn > 0) { + let coin_store = borrow_global_mut>(account_addr); + let coin_to_burn = extract(&mut coin_store.coin, coin_amount_to_burn); + burn(coin_to_burn, burn_cap); + }; + if (fa_amount_to_burn > 0) { + fungible_asset::address_burn_from_for_gas( + borrow_paired_burn_ref(burn_cap), + primary_fungible_store::primary_store_address(account_addr, option::destroy_some(paired_metadata())), + fa_amount_to_burn + ); + }; + } + /// Deposit the coin balance into the recipient's account and emit an event. public fun deposit( account_addr: address, @@ -888,7 +916,7 @@ module aptos_framework::coin { /// Deposit the coin balance into the recipient's account without checking if the account is frozen. /// This is for internal use only and doesn't emit an DepositEvent. - public(friend) fun force_deposit( + public(friend) fun deposit_for_gas_fee( account_addr: address, coin: Coin ) acquires CoinStore, CoinConversionMap, CoinInfo { @@ -1977,7 +2005,7 @@ module aptos_framework::coin { account: &signer, aaron: &signer, bob: &signer - ) acquires CoinConversionMap, CoinInfo, CoinStore { + ) acquires CoinConversionMap, CoinInfo, CoinStore, PairedFungibleAssetRefs { let account_addr = signer::address_of(account); let aaron_addr = signer::address_of(aaron); let bob_addr = signer::address_of(bob); @@ -1985,17 +2013,35 @@ module aptos_framework::coin { account::create_account_for_test(aaron_addr); account::create_account_for_test(bob_addr); let (burn_cap, freeze_cap, mint_cap) = initialize_and_register_fake_money(account, 1, true); + + assert!(event::emitted_events().length() == 0, 10); + assert!(event::emitted_events().length() == 0, 10); + maybe_convert_to_fungible_store(aaron_addr); + + assert!(event::emitted_events().length() == 0, 10); deposit(aaron_addr, mint(1, &mint_cap)); + assert!(event::emitted_events().length() == 1, 10); + + deposit_for_gas_fee(account_addr, mint(100, &mint_cap)); + assert!(event::emitted_events().length() == 1, 10); - force_deposit(account_addr, mint(100, &mint_cap)); - force_deposit(aaron_addr, mint(50, &mint_cap)); + deposit_for_gas_fee(aaron_addr, mint(50, &mint_cap)); + assert!(event::emitted_events().length() == 1, 10); assert!( primary_fungible_store::balance(aaron_addr, option::extract(&mut paired_metadata())) == 51, 0 ); assert!(coin_balance(account_addr) == 100, 0); - force_deposit(bob_addr, mint(1, &mint_cap)); + deposit_for_gas_fee(bob_addr, mint(1, &mint_cap)); + assert!(event::emitted_events().length() == 1, 10); + + assert!(event::emitted_events().length() == 0, 10); + burn_from_for_gas(aaron_addr, 1, &burn_cap); + assert!(event::emitted_events().length() == 0, 10); + burn_from(aaron_addr, 1, &burn_cap); + assert!(event::emitted_events().length() == 1, 10); + move_to(account, FakeMoneyCapabilities { burn_cap, freeze_cap, diff --git a/aptos-move/framework/aptos-framework/sources/coin.spec.move b/aptos-move/framework/aptos-framework/sources/coin.spec.move index 0ccf01d2dd194..ae2dc1f35d225 100644 --- a/aptos-move/framework/aptos-framework/sources/coin.spec.move +++ b/aptos-move/framework/aptos-framework/sources/coin.spec.move @@ -325,7 +325,7 @@ spec aptos_framework::coin { aborts_if coin_store.frozen; } - spec force_deposit(account_addr: address, coin: Coin) { + spec deposit_for_gas_fee(account_addr: address, coin: Coin) { // TODO(fa_migration) pragma verify = false; modifies global>(account_addr); 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 2fc6ae2b27d7b..2327e50ddfbf1 100644 --- a/aptos-move/framework/aptos-framework/sources/primary_fungible_store.move +++ b/aptos-move/framework/aptos-framework/sources/primary_fungible_store.move @@ -216,13 +216,6 @@ module aptos_framework::primary_fungible_store { dispatchable_fungible_asset::deposit(store, fa); } - /// 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::unchecked_deposit(object::object_address(&store), fa); - } - /// Transfer `amount` of fungible asset from sender's primary store to receiver's primary store. public entry fun transfer( sender: &signer, diff --git a/aptos-move/framework/aptos-framework/sources/transaction_fee.move b/aptos-move/framework/aptos-framework/sources/transaction_fee.move index a00823de05003..8f71490025af4 100644 --- a/aptos-move/framework/aptos-framework/sources/transaction_fee.move +++ b/aptos-move/framework/aptos-framework/sources/transaction_fee.move @@ -88,7 +88,7 @@ module aptos_framework::transaction_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( + coin::burn_from_for_gas( account, fee, burn_cap, @@ -101,7 +101,7 @@ module aptos_framework::transaction_fee { public(friend) fun mint_and_refund(account: address, refund: u64) acquires AptosCoinMintCapability { let mint_cap = &borrow_global(@aptos_framework).mint_cap; let refund_coin = coin::mint(refund, mint_cap); - coin::force_deposit(account, refund_coin); + coin::deposit_for_gas_fee(account, refund_coin); } /// Only called during genesis.