From d0cd794cc5ec39a978a805e8451a8ae2bd374011 Mon Sep 17 00:00:00 2001 From: Anirudh Prasad Date: Tue, 2 Dec 2025 11:09:50 +0530 Subject: [PATCH 01/20] feat: add concurrent accounting to eliminate serilization bottleneck --- .../aptos-framework/doc/governed_gas_pool.md | 274 ++++++++++++++++-- .../sources/governed_gas_pool.move | 138 +++++++-- .../sources/governed_gas_pool.spec.move | 1 - .../framework/move-stdlib/doc/features.md | 61 ++++ .../move-stdlib/sources/configs/features.move | 12 + 5 files changed, 440 insertions(+), 46 deletions(-) diff --git a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md index 8514231f1c8..688a158c36d 100644 --- a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md +++ b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md @@ -8,6 +8,7 @@ - [Struct `WithdrawStakingRewardEvent`](#0x1_governed_gas_pool_WithdrawStakingRewardEvent) - [Resource `GovernedGasPool`](#0x1_governed_gas_pool_GovernedGasPool) - [Resource `GovernedGasPoolExtension`](#0x1_governed_gas_pool_GovernedGasPoolExtension) +- [Resource `GovernedGasPoolCounters`](#0x1_governed_gas_pool_GovernedGasPoolCounters) - [Constants](#@Constants_0) - [Function `primary_fungible_store_address`](#0x1_governed_gas_pool_primary_fungible_store_address) - [Function `create_resource_account_seed`](#0x1_governed_gas_pool_create_resource_account_seed) @@ -27,6 +28,10 @@ - [Function `get_balance`](#0x1_governed_gas_pool_get_balance) - [Function `withdraw_staking_reward`](#0x1_governed_gas_pool_withdraw_staking_reward) - [Function `register_coin`](#0x1_governed_gas_pool_register_coin) +- [Function `get_gas_fee_total`](#0x1_governed_gas_pool_get_gas_fee_total) +- [Function `get_treasury_total`](#0x1_governed_gas_pool_get_treasury_total) +- [Function `get_governance_funded_total`](#0x1_governed_gas_pool_get_governance_funded_total) +- [Function `get_reward_withdrawn_total`](#0x1_governed_gas_pool_get_reward_withdrawn_total) - [Specification](#@Specification_1) - [Function `initialize`](#@Specification_1_initialize) - [Function `fund`](#@Specification_1_fund) @@ -35,6 +40,7 @@
use 0x1::account;
+use 0x1::aggregator_v2;
 use 0x1::aptos_account;
 use 0x1::aptos_coin;
 use 0x1::coin;
@@ -139,6 +145,58 @@ Contains added variable needed for the GovernedGasPool staking reward update.
 
 
 
+
+
+
+
+## Resource `GovernedGasPoolCounters`
+
+Aggregator-backed counters for parallel gas pool accounting.
+
+
+
struct GovernedGasPoolCounters has key
+
+ + + +
+Fields + + +
+
+gas_fee_total: aggregator_v2::Aggregator<u64> +
+
+ +
+
+treasury_total: aggregator_v2::Aggregator<u64> +
+
+ +
+
+governance_funded_total: aggregator_v2::Aggregator<u64> +
+
+ +
+
+reward_withdrawn_total: aggregator_v2::Aggregator<u64> +
+
+ +
+
+withdraw_events: event::EventHandle<governed_gas_pool::WithdrawStakingRewardEvent> +
+
+ +
+
+ +
@@ -146,6 +204,16 @@ Contains added variable needed for the GovernedGasPool staking reward update. ## Constants + + +Insufficient balance in the pool. + + +
const EINSUFFICIENT_BALANCE: u64 = 1;
+
+ + + No longer supported. @@ -253,6 +321,15 @@ Initializes the governed gas pool around a resource account creation seed. deposited_treasury_counter: 0, withdraw_staking_reward_events: account::new_event_handle<WithdrawStakingRewardEvent>(aptos_framework), }); + }; + if (!exists<GovernedGasPoolCounters>(signer::address_of(aptos_framework))) { + move_to(aptos_framework, GovernedGasPoolCounters{ + gas_fee_total: aggregator_v2::create_unbounded_aggregator(), + treasury_total: aggregator_v2::create_unbounded_aggregator(), + governance_funded_total: aggregator_v2::create_unbounded_aggregator(), + reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(), + withdraw_events: account::new_event_handle<WithdrawStakingRewardEvent>(aptos_framework), + }); } } else { @@ -271,6 +348,14 @@ Initializes the governed gas pool around a resource account creation seed. deposited_treasury_counter: 0, withdraw_staking_reward_events: account::new_event_handle<WithdrawStakingRewardEvent>(aptos_framework), }); + + move_to(aptos_framework, GovernedGasPoolCounters{ + gas_fee_total: aggregator_v2::create_unbounded_aggregator(), + treasury_total: aggregator_v2::create_unbounded_aggregator(), + governance_funded_total: aggregator_v2::create_unbounded_aggregator(), + reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(), + withdraw_events: account::new_event_handle<WithdrawStakingRewardEvent>(aptos_framework), + }); } }
@@ -298,17 +383,32 @@ Initializes the governed gas pool extension alone.
public entry fun initialize_governed_gas_pool_extension(
     aptos_framework: &signer,
-) {
+) acquires GovernedGasPoolExtension {
     system_addresses::assert_aptos_framework(aptos_framework);
 
     // return if the governed gas extension has already been initialized
-    if (exists<GovernedGasPoolExtension>(signer::address_of(aptos_framework))) {
-    } else {
+    if (!exists<GovernedGasPoolExtension>(signer::address_of(aptos_framework))) {
+        move_to(aptos_framework, GovernedGasPoolExtension{
+            deposited_treasury_counter: 0,
+            withdraw_staking_reward_events: account::new_event_handle<WithdrawStakingRewardEvent>(aptos_framework),
+        });
+    };
 
-    move_to(aptos_framework, GovernedGasPoolExtension{
-        deposited_treasury_counter: 0,
-        withdraw_staking_reward_events: account::new_event_handle<WithdrawStakingRewardEvent>(aptos_framework),
-    });
+    // Create counters resource if missing (migration path)
+    if (!exists<GovernedGasPoolCounters>(signer::address_of(aptos_framework))) {
+        let legacy_treasury_total = if (exists<GovernedGasPoolExtension>(signer::address_of(aptos_framework))) {
+            borrow_global<GovernedGasPoolExtension>(@aptos_framework).deposited_treasury_counter
+        } else {
+            0
+        };
+
+        move_to(aptos_framework, GovernedGasPoolCounters{
+            gas_fee_total: aggregator_v2::create_unbounded_aggregator(),
+            treasury_total: aggregator_v2::create_unbounded_aggregator_with_value(legacy_treasury_total),
+            governance_funded_total: aggregator_v2::create_unbounded_aggregator(),
+            reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(),
+            withdraw_events: account::new_event_handle<WithdrawStakingRewardEvent>(aptos_framework),
+        });
     }
 }
 
@@ -443,13 +543,18 @@ Funds the destination account with a given amount of coin. Implementation -
public fun fund<CoinType>(aptos_framework: &signer, account: address, amount: u64) acquires GovernedGasPool {
+
public fun fund<CoinType>(aptos_framework: &signer, account: address, amount: u64) acquires GovernedGasPool, GovernedGasPoolCounters {
     // Check that the Aptos framework is the caller
     // This is what ensures that funding can only be done by the Aptos framework,
     // i.e., via a governance proposal.
     system_addresses::assert_aptos_framework(aptos_framework);
     let governed_gas_signer = &governed_gas_signer();
     coin::deposit(account, coin::withdraw<CoinType>(governed_gas_signer, amount));
+
+    if (features::governed_gas_pool_aggregators_enabled()) {
+        let counters = borrow_global_mut<GovernedGasPoolCounters>(@aptos_framework);
+        aggregator_v2::add(&mut counters.governance_funded_total, amount);
+    };
 }
 
@@ -599,12 +704,19 @@ Deposits gas fees into the governed gas pool. Implementation -
public(friend) fun deposit_gas_fee_v2(gas_payer: address, gas_fee: u64) acquires GovernedGasPool {
+
public(friend) fun deposit_gas_fee_v2(gas_payer: address, gas_fee: u64) acquires GovernedGasPool, GovernedGasPoolCounters {
+    if (gas_fee == 0) return;
+
     if (features::operations_default_to_fa_apt_store_enabled()) {
         deposit_from_fungible_store(gas_payer, gas_fee);
     } else {
         deposit_from<AptosCoin>(gas_payer, gas_fee);
     };
+
+    if (features::governed_gas_pool_aggregators_enabled()) {
+        let counters = borrow_global_mut<GovernedGasPoolCounters>(@aptos_framework);
+        aggregator_v2::add(&mut counters.gas_fee_total, gas_fee);
+    };
 }
 
@@ -630,12 +742,17 @@ Deposits from the treasury account. Treasury deposit are recorded. Implementation -
public entry fun deposit_treasury(treasury_account: &signer, amount: u64) acquires GovernedGasPool, GovernedGasPoolExtension {
+
public entry fun deposit_treasury(treasury_account: &signer, amount: u64) acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters {
     let treasury_account_address = signer::address_of(treasury_account);
     deposit_from<AptosCoin>(treasury_account_address, amount);
 
-    let ggp = borrow_global_mut<GovernedGasPoolExtension>(@aptos_framework);
-    ggp.deposited_treasury_counter = ggp.deposited_treasury_counter + amount;
+    if (features::governed_gas_pool_aggregators_enabled()) {
+        let counters = borrow_global_mut<GovernedGasPoolCounters>(@aptos_framework);
+        aggregator_v2::add(&mut counters.treasury_total, amount);
+    } else {
+        let ggp = borrow_global_mut<GovernedGasPoolExtension>(@aptos_framework);
+        ggp.deposited_treasury_counter = ggp.deposited_treasury_counter + amount;
+    };
 }
 
@@ -696,17 +813,24 @@ governed gas pool to authorize the withdrawal.
public(friend) fun withdraw_staking_reward<CoinType>(
     amount: u64
-): Coin<CoinType> acquires GovernedGasPool, GovernedGasPoolExtension {
+): Coin<CoinType> acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters {
     let balance = get_balance<CoinType>();
-    assert!(balance >= amount, 0); // insufficient balance
-    let ggpv2 = borrow_global_mut<GovernedGasPoolExtension>(@aptos_framework);
-
-    event::emit_event(
-        &mut ggpv2.withdraw_staking_reward_events,
-        WithdrawStakingRewardEvent {
-            amount,
-        },
-    );
+    assert!(balance >= amount, EINSUFFICIENT_BALANCE);
+
+    if (features::governed_gas_pool_aggregators_enabled()) {
+        let counters = borrow_global_mut<GovernedGasPoolCounters>(@aptos_framework);
+        aggregator_v2::add(&mut counters.reward_withdrawn_total, amount);
+        event::emit_event(
+            &mut counters.withdraw_events,
+            WithdrawStakingRewardEvent { amount },
+        );
+    } else {
+        let ggpv2 = borrow_global_mut<GovernedGasPoolExtension>(@aptos_framework);
+        event::emit_event(
+            &mut ggpv2.withdraw_staking_reward_events,
+            WithdrawStakingRewardEvent { amount },
+        );
+    };
 
     // Withdraw reward coin.
     coin::withdraw<CoinType>(&governed_gas_signer(), amount)
@@ -741,6 +865,110 @@ Register Aptos coin with Governed gas signer.
 
 
 
+
+
+
+
+## Function `get_gas_fee_total`
+
+Returns a snapshot of the total gas fees collected.
+
+
+
#[view]
+public fun get_gas_fee_total(): aggregator_v2::AggregatorSnapshot<u64>
+
+ + + +
+Implementation + + +
public fun get_gas_fee_total(): AggregatorSnapshot<u64> acquires GovernedGasPoolCounters {
+    aggregator_v2::snapshot(&borrow_global<GovernedGasPoolCounters>(@aptos_framework).gas_fee_total)
+}
+
+ + + +
+ + + +## Function `get_treasury_total` + +Returns a snapshot of the total treasury deposits. + + +
#[view]
+public fun get_treasury_total(): aggregator_v2::AggregatorSnapshot<u64>
+
+ + + +
+Implementation + + +
public fun get_treasury_total(): AggregatorSnapshot<u64> acquires GovernedGasPoolCounters {
+    aggregator_v2::snapshot(&borrow_global<GovernedGasPoolCounters>(@aptos_framework).treasury_total)
+}
+
+ + + +
+ + + +## Function `get_governance_funded_total` + +Returns a snapshot of the total governance-funded payouts. + + +
#[view]
+public fun get_governance_funded_total(): aggregator_v2::AggregatorSnapshot<u64>
+
+ + + +
+Implementation + + +
public fun get_governance_funded_total(): AggregatorSnapshot<u64> acquires GovernedGasPoolCounters {
+    aggregator_v2::snapshot(&borrow_global<GovernedGasPoolCounters>(@aptos_framework).governance_funded_total)
+}
+
+ + + +
+ + + +## Function `get_reward_withdrawn_total` + +Returns a snapshot of the total staking rewards withdrawn. + + +
#[view]
+public fun get_reward_withdrawn_total(): aggregator_v2::AggregatorSnapshot<u64>
+
+ + + +
+Implementation + + +
public fun get_reward_withdrawn_total(): AggregatorSnapshot<u64> acquires GovernedGasPoolCounters {
+    aggregator_v2::snapshot(&borrow_global<GovernedGasPoolCounters>(@aptos_framework).reward_withdrawn_total)
+}
+
+ + +
@@ -793,7 +1021,7 @@ Register Aptos coin with Governed gas signer. Abort if the governed gas pool has insufficient funds -
aborts_with coin::EINSUFFICIENT_BALANCE, error::invalid_argument(EINSUFFICIENT_BALANCE), 0x1, 0x5, 0x7;
+
aborts_with coin::EINSUFFICIENT_BALANCE, error::invalid_argument(EINSUFFICIENT_BALANCE), 0x1, 0x5, 0x7;
 
diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move index ce3d6a81f9f..182200f1325 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move @@ -14,6 +14,7 @@ module aptos_framework::governed_gas_pool { use std::features; use aptos_framework::signer; use aptos_framework::aptos_account::Self; + use aptos_framework::aggregator_v2::{Self, Aggregator, AggregatorSnapshot}; #[test_only] use aptos_framework::coin::{BurnCapability, MintCapability}; #[test_only] @@ -24,6 +25,8 @@ module aptos_framework::governed_gas_pool { friend aptos_framework::stake; friend aptos_framework::transaction_fee; + /// Insufficient balance in the pool. + const EINSUFFICIENT_BALANCE: u64 = 1; /// No longer supported. const ENO_LONGER_SUPPORTED: u64 = 4; @@ -47,6 +50,15 @@ module aptos_framework::governed_gas_pool { withdraw_staking_reward_events: EventHandle, } + /// Aggregator-backed counters for parallel gas pool accounting. + struct GovernedGasPoolCounters has key { + gas_fee_total: Aggregator, + treasury_total: Aggregator, + governance_funded_total: Aggregator, + reward_withdrawn_total: Aggregator, + withdraw_events: EventHandle, + } + /// Address of APT Primary Fungible Store inline fun primary_fungible_store_address(account: address): address { object::create_user_derived_object_address(account, @aptos_fungible_asset) @@ -80,6 +92,15 @@ module aptos_framework::governed_gas_pool { deposited_treasury_counter: 0, withdraw_staking_reward_events: account::new_event_handle(aptos_framework), }); + }; + if (!exists(signer::address_of(aptos_framework))) { + move_to(aptos_framework, GovernedGasPoolCounters{ + gas_fee_total: aggregator_v2::create_unbounded_aggregator(), + treasury_total: aggregator_v2::create_unbounded_aggregator(), + governance_funded_total: aggregator_v2::create_unbounded_aggregator(), + reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(), + withdraw_events: account::new_event_handle(aptos_framework), + }); } } else { @@ -98,6 +119,14 @@ module aptos_framework::governed_gas_pool { deposited_treasury_counter: 0, withdraw_staking_reward_events: account::new_event_handle(aptos_framework), }); + + move_to(aptos_framework, GovernedGasPoolCounters{ + gas_fee_total: aggregator_v2::create_unbounded_aggregator(), + treasury_total: aggregator_v2::create_unbounded_aggregator(), + governance_funded_total: aggregator_v2::create_unbounded_aggregator(), + reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(), + withdraw_events: account::new_event_handle(aptos_framework), + }); } } @@ -105,17 +134,32 @@ module aptos_framework::governed_gas_pool { /// @param aptos_framework The signer of the aptos_framework module. public entry fun initialize_governed_gas_pool_extension( aptos_framework: &signer, - ) { + ) acquires GovernedGasPoolExtension { system_addresses::assert_aptos_framework(aptos_framework); // return if the governed gas extension has already been initialized - if (exists(signer::address_of(aptos_framework))) { - } else { + if (!exists(signer::address_of(aptos_framework))) { + move_to(aptos_framework, GovernedGasPoolExtension{ + deposited_treasury_counter: 0, + withdraw_staking_reward_events: account::new_event_handle(aptos_framework), + }); + }; - move_to(aptos_framework, GovernedGasPoolExtension{ - deposited_treasury_counter: 0, - withdraw_staking_reward_events: account::new_event_handle(aptos_framework), - }); + // Create counters resource if missing (migration path) + if (!exists(signer::address_of(aptos_framework))) { + let legacy_treasury_total = if (exists(signer::address_of(aptos_framework))) { + borrow_global(@aptos_framework).deposited_treasury_counter + } else { + 0 + }; + + move_to(aptos_framework, GovernedGasPoolCounters{ + gas_fee_total: aggregator_v2::create_unbounded_aggregator(), + treasury_total: aggregator_v2::create_unbounded_aggregator_with_value(legacy_treasury_total), + governance_funded_total: aggregator_v2::create_unbounded_aggregator(), + reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(), + withdraw_events: account::new_event_handle(aptos_framework), + }); } } @@ -150,13 +194,18 @@ module aptos_framework::governed_gas_pool { /// Funds the destination account with a given amount of coin. /// @param account The account to be funded. /// @param amount The amount of coin to be funded. - public fun fund(aptos_framework: &signer, account: address, amount: u64) acquires GovernedGasPool { + public fun fund(aptos_framework: &signer, account: address, amount: u64) acquires GovernedGasPool, GovernedGasPoolCounters { // Check that the Aptos framework is the caller // This is what ensures that funding can only be done by the Aptos framework, // i.e., via a governance proposal. system_addresses::assert_aptos_framework(aptos_framework); let governed_gas_signer = &governed_gas_signer(); coin::deposit(account, coin::withdraw(governed_gas_signer, amount)); + + if (features::governed_gas_pool_aggregators_enabled()) { + let counters = borrow_global_mut(@aptos_framework); + aggregator_v2::add(&mut counters.governance_funded_total, amount); + }; } /// Deposits some coin into the governed gas pool. @@ -206,23 +255,35 @@ module aptos_framework::governed_gas_pool { /// Deposits gas fees into the governed gas pool. /// @param gas_payer The address of the account that paid the gas fees. /// @param gas_fee The amount of gas fees to be deposited. - public(friend) fun deposit_gas_fee_v2(gas_payer: address, gas_fee: u64) acquires GovernedGasPool { + public(friend) fun deposit_gas_fee_v2(gas_payer: address, gas_fee: u64) acquires GovernedGasPool, GovernedGasPoolCounters { + if (gas_fee == 0) return; + if (features::operations_default_to_fa_apt_store_enabled()) { deposit_from_fungible_store(gas_payer, gas_fee); } else { deposit_from(gas_payer, gas_fee); }; + + if (features::governed_gas_pool_aggregators_enabled()) { + let counters = borrow_global_mut(@aptos_framework); + aggregator_v2::add(&mut counters.gas_fee_total, gas_fee); + }; } /// Deposits from the treasury account. Treasury deposit are recorded. /// @param treasury_account The address of the account that paid the treasury. /// @param amount The amount of treasury to be deposited. - public entry fun deposit_treasury(treasury_account: &signer, amount: u64) acquires GovernedGasPool, GovernedGasPoolExtension { + public entry fun deposit_treasury(treasury_account: &signer, amount: u64) acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters { let treasury_account_address = signer::address_of(treasury_account); deposit_from(treasury_account_address, amount); - let ggp = borrow_global_mut(@aptos_framework); - ggp.deposited_treasury_counter = ggp.deposited_treasury_counter + amount; + if (features::governed_gas_pool_aggregators_enabled()) { + let counters = borrow_global_mut(@aptos_framework); + aggregator_v2::add(&mut counters.treasury_total, amount); + } else { + let ggp = borrow_global_mut(@aptos_framework); + ggp.deposited_treasury_counter = ggp.deposited_treasury_counter + amount; + }; } #[view] @@ -243,17 +304,24 @@ module aptos_framework::governed_gas_pool { /// @return A `Coin` resource containing the withdrawn amount. public(friend) fun withdraw_staking_reward( amount: u64 - ): Coin acquires GovernedGasPool, GovernedGasPoolExtension { + ): Coin acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters { let balance = get_balance(); - assert!(balance >= amount, 0); // insufficient balance - let ggpv2 = borrow_global_mut(@aptos_framework); - - event::emit_event( - &mut ggpv2.withdraw_staking_reward_events, - WithdrawStakingRewardEvent { - amount, - }, - ); + assert!(balance >= amount, EINSUFFICIENT_BALANCE); + + if (features::governed_gas_pool_aggregators_enabled()) { + let counters = borrow_global_mut(@aptos_framework); + aggregator_v2::add(&mut counters.reward_withdrawn_total, amount); + event::emit_event( + &mut counters.withdraw_events, + WithdrawStakingRewardEvent { amount }, + ); + } else { + let ggpv2 = borrow_global_mut(@aptos_framework); + event::emit_event( + &mut ggpv2.withdraw_staking_reward_events, + WithdrawStakingRewardEvent { amount }, + ); + }; // Withdraw reward coin. coin::withdraw(&governed_gas_signer(), amount) @@ -265,6 +333,32 @@ module aptos_framework::governed_gas_pool { coin::register(&s); } + // ========== View Functions for Aggregator Totals ========== + + #[view] + /// Returns a snapshot of the total gas fees collected. + public fun get_gas_fee_total(): AggregatorSnapshot acquires GovernedGasPoolCounters { + aggregator_v2::snapshot(&borrow_global(@aptos_framework).gas_fee_total) + } + + #[view] + /// Returns a snapshot of the total treasury deposits. + public fun get_treasury_total(): AggregatorSnapshot acquires GovernedGasPoolCounters { + aggregator_v2::snapshot(&borrow_global(@aptos_framework).treasury_total) + } + + #[view] + /// Returns a snapshot of the total governance-funded payouts. + public fun get_governance_funded_total(): AggregatorSnapshot acquires GovernedGasPoolCounters { + aggregator_v2::snapshot(&borrow_global(@aptos_framework).governance_funded_total) + } + + #[view] + /// Returns a snapshot of the total staking rewards withdrawn. + public fun get_reward_withdrawn_total(): AggregatorSnapshot acquires GovernedGasPoolCounters { + aggregator_v2::snapshot(&borrow_global(@aptos_framework).reward_withdrawn_total) + } + #[test_only] /// The AptosCoin mint capability struct AptosCoinMintCapability has key { diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move index decae85a9b8..f9b6dae99fa 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move @@ -1,5 +1,4 @@ spec aptos_framework::governed_gas_pool { - use aptos_framework::coin::EINSUFFICIENT_BALANCE; use aptos_framework::error; /// diff --git a/aptos-move/framework/move-stdlib/doc/features.md b/aptos-move/framework/move-stdlib/doc/features.md index 9facb18e9ab..c8b14d2fab1 100644 --- a/aptos-move/framework/move-stdlib/doc/features.md +++ b/aptos-move/framework/move-stdlib/doc/features.md @@ -168,6 +168,8 @@ return true. - [Function `is_distribute_transaction_fee_enabled`](#0x1_features_is_distribute_transaction_fee_enabled) - [Function `get_stake_reward_using_treasury_feature`](#0x1_features_get_stake_reward_using_treasury_feature) - [Function `stake_reward_using_treasury_enabled`](#0x1_features_stake_reward_using_treasury_enabled) +- [Function `get_governed_gas_pool_aggregators_feature`](#0x1_features_get_governed_gas_pool_aggregators_feature) +- [Function `governed_gas_pool_aggregators_enabled`](#0x1_features_governed_gas_pool_aggregators_enabled) - [Function `change_feature_flags`](#0x1_features_change_feature_flags) - [Function `change_feature_flags_internal`](#0x1_features_change_feature_flags_internal) - [Function `change_feature_flags_for_next_epoch`](#0x1_features_change_feature_flags_for_next_epoch) @@ -705,6 +707,19 @@ Lifetime: permanent + + +Whether the Governed Gas Pool uses Aggregator V2 for concurrent accounting. +Enables parallel tracking of gas fees, treasury deposits, governance payouts, and rewards. + +Lifetime: transient + + +
const GOVERNED_GAS_POOL_AGGREGATORS: u64 = 225;
+
+ + + Deprecated by aptos_framework::jwk_consensus_config::JWKConsensusConfig. @@ -4346,6 +4361,52 @@ Whether the Governed Gas Pool is enabled. + + + + +## Function `get_governed_gas_pool_aggregators_feature` + + + +
public fun get_governed_gas_pool_aggregators_feature(): u64
+
+ + + +
+Implementation + + +
public fun get_governed_gas_pool_aggregators_feature(): u64 { GOVERNED_GAS_POOL_AGGREGATORS }
+
+ + + +
+ + + +## Function `governed_gas_pool_aggregators_enabled` + + + +
public fun governed_gas_pool_aggregators_enabled(): bool
+
+ + + +
+Implementation + + +
public fun governed_gas_pool_aggregators_enabled(): bool acquires Features {
+    is_enabled(GOVERNED_GAS_POOL_AGGREGATORS)
+}
+
+ + +
diff --git a/aptos-move/framework/move-stdlib/sources/configs/features.move b/aptos-move/framework/move-stdlib/sources/configs/features.move index c5d7cc6b856..25a6334e56e 100644 --- a/aptos-move/framework/move-stdlib/sources/configs/features.move +++ b/aptos-move/framework/move-stdlib/sources/configs/features.move @@ -804,6 +804,18 @@ module std::features { is_enabled(STAKE_REWARD_USING_TREASURY) } + /// Whether the Governed Gas Pool uses Aggregator V2 for concurrent accounting. + /// Enables parallel tracking of gas fees, treasury deposits, governance payouts, and rewards. + /// + /// Lifetime: transient + const GOVERNED_GAS_POOL_AGGREGATORS: u64 = 225; + + public fun get_governed_gas_pool_aggregators_feature(): u64 { GOVERNED_GAS_POOL_AGGREGATORS } + + public fun governed_gas_pool_aggregators_enabled(): bool acquires Features { + is_enabled(GOVERNED_GAS_POOL_AGGREGATORS) + } + // ============================================================================================ // Feature Flag Implementation From 14365add104086ee7da125caaf09e6f0841497ad Mon Sep 17 00:00:00 2001 From: Anirudh Prasad Date: Mon, 8 Dec 2025 22:55:52 +0530 Subject: [PATCH 02/20] feat: add spec invariants and unit tests --- .../aptos-framework/doc/governed_gas_pool.md | 73 ++++++++ .../sources/governed_gas_pool.move | 165 +++++++++++++++++- .../sources/governed_gas_pool.spec.move | 35 ++++ 3 files changed, 272 insertions(+), 1 deletion(-) diff --git a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md index 688a158c36d..040514b0139 100644 --- a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md +++ b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md @@ -34,9 +34,13 @@ - [Function `get_reward_withdrawn_total`](#0x1_governed_gas_pool_get_reward_withdrawn_total) - [Specification](#@Specification_1) - [Function `initialize`](#@Specification_1_initialize) + - [Function `initialize_governed_gas_pool_extension`](#@Specification_1_initialize_governed_gas_pool_extension) - [Function `fund`](#@Specification_1_fund) - [Function `deposit`](#@Specification_1_deposit) - [Function `deposit_gas_fee`](#@Specification_1_deposit_gas_fee) + - [Function `deposit_gas_fee_v2`](#@Specification_1_deposit_gas_fee_v2) + - [Function `deposit_treasury`](#@Specification_1_deposit_treasury) + - [Function `withdraw_staking_reward`](#@Specification_1_withdraw_staking_reward)
use 0x1::account;
@@ -1001,6 +1005,23 @@ Returns a snapshot of the total staking rewards withdrawn.
 
 
 
+
+
+### Function `initialize_governed_gas_pool_extension`
+
+
+
public entry fun initialize_governed_gas_pool_extension(aptos_framework: &signer)
+
+ + +Spec for initialize_governed_gas_pool_extension + + +
pragma aborts_if_is_partial = true;
+
+ + + ### Function `fund` @@ -1051,4 +1072,56 @@ Abort if the governed gas pool has insufficient funds
+ + + + +### Function `deposit_gas_fee_v2` + + +
public(friend) fun deposit_gas_fee_v2(gas_payer: address, gas_fee: u64)
+
+ + +[high-level-req-5] Spec for deposit_gas_fee_v2 + + +
pragma aborts_if_is_partial = true;
+
+ + + + + +### Function `deposit_treasury` + + +
public entry fun deposit_treasury(treasury_account: &signer, amount: u64)
+
+ + +[high-level-req-5.1] Spec for deposit_treasury + + +
pragma aborts_if_is_partial = true;
+
+ + + + + +### Function `withdraw_staking_reward` + + +
public(friend) fun withdraw_staking_reward<CoinType>(amount: u64): coin::Coin<CoinType>
+
+ + +[high-level-req-5.3] Spec for withdraw_staking_reward + + +
pragma aborts_if_is_partial = true;
+
+ + [move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move index 182200f1325..d7f1d2966f4 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move @@ -559,7 +559,7 @@ module aptos_framework::governed_gas_pool { /// Add some treasury to the governed gas pool. /// /// @param aptos_framework is the signer of the aptos_framework module. - fun test_deposite_treasury_and_counter(aptos_framework: &signer, treasury: &signer) acquires GovernedGasPool, GovernedGasPoolExtension, AptosCoinMintCapability { + fun test_deposite_treasury_and_counter(aptos_framework: &signer, treasury: &signer) acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters, AptosCoinMintCapability { // initialize the modules initialize_for_test(aptos_framework); @@ -588,4 +588,167 @@ module aptos_framework::governed_gas_pool { coin::deposit(@0xdddd, withdraw); } + // ============ Aggregator V2 Tests ============ + + #[test_only] + /// Helper to enable the aggregator feature flag for testing + fun enable_aggregator_feature_for_test(aptos_framework: &signer) { + features::change_feature_flags_for_testing( + aptos_framework, + vector[features::get_governed_gas_pool_aggregators_feature()], + vector[] + ); + } + + #[test(aptos_framework = @aptos_framework, depositor = @0xdddd)] + /// Test gas fee tracking with aggregators enabled + fun test_gas_fee_tracking_with_aggregators( + aptos_framework: &signer, + depositor: &signer + ) acquires GovernedGasPool, GovernedGasPoolCounters, AptosCoinMintCapability { + initialize_for_test(aptos_framework); + enable_aggregator_feature_for_test(aptos_framework); + + aptos_account::create_account(signer::address_of(depositor)); + mint_for_test(signer::address_of(depositor), 10000); + + deposit_gas_fee_v2(signer::address_of(depositor), 100); + deposit_gas_fee_v2(signer::address_of(depositor), 200); + deposit_gas_fee_v2(signer::address_of(depositor), 300); + + let gas_total = aggregator_v2::read_snapshot(&get_gas_fee_total()); + assert!(gas_total == 600, 1); + + deposit_gas_fee_v2(signer::address_of(depositor), 0); + let gas_total_after = aggregator_v2::read_snapshot(&get_gas_fee_total()); + assert!(gas_total_after == 600, 2); + } + + #[test(aptos_framework = @aptos_framework, treasury = @0xdddd)] + /// Test treasury tracking with aggregators enabled + fun test_treasury_tracking_with_aggregators( + aptos_framework: &signer, + treasury: &signer + ) acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters, AptosCoinMintCapability { + initialize_for_test(aptos_framework); + enable_aggregator_feature_for_test(aptos_framework); + + aptos_account::create_account(signer::address_of(treasury)); + mint_for_test(signer::address_of(treasury), 10000); + + deposit_treasury(treasury, 500); + deposit_treasury(treasury, 300); + + let treasury_total = aggregator_v2::read_snapshot(&get_treasury_total()); + assert!(treasury_total == 800, 1); + } + + #[test(aptos_framework = @aptos_framework, depositor = @0xdddd, beneficiary = @0xbbbb)] + /// Test governance funding tracking with aggregators enabled + fun test_governance_funding_tracking_with_aggregators( + aptos_framework: &signer, + depositor: &signer, + beneficiary: &signer + ) acquires GovernedGasPool, GovernedGasPoolCounters, AptosCoinMintCapability { + initialize_for_test(aptos_framework); + enable_aggregator_feature_for_test(aptos_framework); + + aptos_account::create_account(signer::address_of(depositor)); + aptos_account::create_account(signer::address_of(beneficiary)); + aptos_account::register_apt(beneficiary); + + mint_for_test(signer::address_of(depositor), 10000); + deposit_gas_fee_v2(signer::address_of(depositor), 5000); + + fund(aptos_framework, signer::address_of(beneficiary), 200); + fund(aptos_framework, signer::address_of(beneficiary), 100); + + let governance_total = aggregator_v2::read_snapshot(&get_governance_funded_total()); + assert!(governance_total == 300, 1); + } + + #[test(aptos_framework = @aptos_framework, treasury = @0xdddd)] + /// Test reward withdrawal tracking with aggregators enabled + fun test_reward_withdrawal_tracking_with_aggregators( + aptos_framework: &signer, + treasury: &signer + ) acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters, AptosCoinMintCapability { + initialize_for_test(aptos_framework); + enable_aggregator_feature_for_test(aptos_framework); + + aptos_account::create_account(signer::address_of(treasury)); + mint_for_test(signer::address_of(treasury), 10000); + deposit_treasury(treasury, 5000); + + let reward1 = withdraw_staking_reward(100); + let reward2 = withdraw_staking_reward(150); + + let reward_total = aggregator_v2::read_snapshot(&get_reward_withdrawn_total()); + assert!(reward_total == 250, 1); + + coin::deposit(signer::address_of(treasury), reward1); + coin::deposit(signer::address_of(treasury), reward2); + } + + #[test(aptos_framework = @aptos_framework, treasury = @0xdddd, beneficiary = @0xbbbb)] + /// Comprehensive test: verify accounting invariant (inflows >= outflows) + fun test_accounting_invariant_with_aggregators( + aptos_framework: &signer, + treasury: &signer, + beneficiary: &signer + ) acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters, AptosCoinMintCapability { + initialize_for_test(aptos_framework); + enable_aggregator_feature_for_test(aptos_framework); + + aptos_account::create_account(signer::address_of(treasury)); + aptos_account::create_account(signer::address_of(beneficiary)); + aptos_account::register_apt(beneficiary); + mint_for_test(signer::address_of(treasury), 100000); + + // INFLOWS + deposit_gas_fee_v2(signer::address_of(treasury), 1000); + deposit_gas_fee_v2(signer::address_of(treasury), 2000); + deposit_treasury(treasury, 5000); + + // OUTFLOWS + fund(aptos_framework, signer::address_of(beneficiary), 500); + let reward = withdraw_staking_reward(300); + coin::deposit(signer::address_of(beneficiary), reward); + + let gas_total = aggregator_v2::read_snapshot(&get_gas_fee_total()); + let treasury_total = aggregator_v2::read_snapshot(&get_treasury_total()); + let governance_total = aggregator_v2::read_snapshot(&get_governance_funded_total()); + let reward_total = aggregator_v2::read_snapshot(&get_reward_withdrawn_total()); + + assert!(gas_total == 3000, 1); + assert!(treasury_total == 5000, 2); + assert!(governance_total == 500, 3); + assert!(reward_total == 300, 4); + + let total_inflows = gas_total + treasury_total; + let total_outflows = governance_total + reward_total; + assert!(total_outflows <= total_inflows, 5); + + let expected_balance = total_inflows - total_outflows; + assert!(get_balance() == expected_balance, 6); + } + + #[test(aptos_framework = @aptos_framework)] + /// Test that counters resource is created during initialization + fun test_counters_resource_created(aptos_framework: &signer) acquires GovernedGasPoolCounters { + initialize_for_test(aptos_framework); + + assert!(exists(@aptos_framework), 1); + + let gas_total = aggregator_v2::read_snapshot(&get_gas_fee_total()); + let treasury_total = aggregator_v2::read_snapshot(&get_treasury_total()); + let governance_total = aggregator_v2::read_snapshot(&get_governance_funded_total()); + let reward_total = aggregator_v2::read_snapshot(&get_reward_withdrawn_total()); + + assert!(gas_total == 0, 2); + assert!(treasury_total == 0, 3); + assert!(governance_total == 0, 4); + assert!(reward_total == 0, 5); + } + } diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move index f9b6dae99fa..c77b195ef5e 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move @@ -26,6 +26,21 @@ spec aptos_framework::governed_gas_pool { /// Implementation: The fund function verifies the signer is the aptos_framework address. /// Enforcement: Formally verified via [high-level-req-4](fund). /// + /// No.: 5 + /// Requirement: Aggregator-backed counters must track all inflows and outflows when the feature is enabled. + /// Criticality: High + /// Implementation: When governed_gas_pool_aggregators_enabled(), gas fees, treasury deposits, + /// governance payouts, and staking rewards are tracked in GovernedGasPoolCounters aggregators. + /// Enforcement: Formally verified via [high-level-req-5](deposit_gas_fee_v2), [high-level-req-5.1](deposit_treasury), + /// [high-level-req-5.2](fund), [high-level-req-5.3](withdraw_staking_reward). + /// + /// No.: 6 + /// Requirement: Total outflows must not exceed total inflows (accounting invariant). + /// Criticality: Critical + /// Implementation: reward_withdrawn_total + governance_funded_total <= gas_fee_total + treasury_total. + /// Note: This invariant is only meaningful for post-migration transactions as historical data is not tracked. + /// Enforcement: Documented invariant; runtime balance checks prevent overdraw. + /// spec module { /// [high-level-req-1] @@ -75,4 +90,24 @@ spec aptos_framework::governed_gas_pool { // ensures gas_payer_balance == old(gas_payer_balance) - gas_fee; */ } + + /// [high-level-req-5] Spec for deposit_gas_fee_v2 + spec deposit_gas_fee_v2(gas_payer: address, gas_fee: u64) { + pragma aborts_if_is_partial = true; + } + + /// [high-level-req-5.1] Spec for deposit_treasury + spec deposit_treasury(treasury_account: &signer, amount: u64) { + pragma aborts_if_is_partial = true; + } + + /// [high-level-req-5.3] Spec for withdraw_staking_reward + spec withdraw_staking_reward(amount: u64): Coin { + pragma aborts_if_is_partial = true; + } + + /// Spec for initialize_governed_gas_pool_extension + spec initialize_governed_gas_pool_extension(aptos_framework: &signer) { + pragma aborts_if_is_partial = true; + } } From 9e25411b71713988df37b87fc393a39da9d1c81d Mon Sep 17 00:00:00 2001 From: Anirudh Prasad Date: Mon, 8 Dec 2025 23:08:06 +0530 Subject: [PATCH 03/20] feat: add feature flag --- .../aptos-framework/doc/fungible_asset.md | 35 +--- .../aptos-framework/doc/governed_gas_pool.md | 55 +++-- .../aptos-framework/doc/ordered_map.md | 10 - .../framework/aptos-framework/doc/stake.md | 188 +++++------------- .../aptos-framework/doc/staking_config.md | 3 +- .../aptos-framework/doc/staking_contract.md | 4 - types/src/on_chain_config/aptos_features.rs | 2 + 7 files changed, 82 insertions(+), 215 deletions(-) diff --git a/aptos-move/framework/aptos-framework/doc/fungible_asset.md b/aptos-move/framework/aptos-framework/doc/fungible_asset.md index 583099be5c6..f43390ecf8d 100644 --- a/aptos-move/framework/aptos-framework/doc/fungible_asset.md +++ b/aptos-move/framework/aptos-framework/doc/fungible_asset.md @@ -68,7 +68,6 @@ metadata object can be any object that equipped with - -## Function `is_asset_type_dispatchable` - -Return whether a fungible asset type has any dispatch or derived-supply hooks registered. - - -
#[view]
-public fun is_asset_type_dispatchable(metadata: object::Object<fungible_asset::Metadata>): bool
-
- - - -
-Implementation - - -
public fun is_asset_type_dispatchable(metadata: Object<Metadata>): bool {
-    let metadata_addr = object::object_address(&metadata);
-    exists<DispatchFunctionStore>(metadata_addr) || exists<DeriveSupply>(metadata_addr)
-}
-
- - -
@@ -4299,13 +4271,8 @@ Decrease the supply of a fungible asset by burning. ) acquires FungibleStore { assert!(object::owns(store, signer::address_of(owner)), error::permission_denied(ENOT_STORE_OWNER)); assert!(!is_frozen(store), error::invalid_argument(ESTORE_IS_FROZEN)); - let fungible_store_address = object::object_address(&store); - // be graceful if ConcurrentFungibleBalance already exists, but flag is off - if (exists<ConcurrentFungibleBalance>(fungible_store_address)) { - return - }; assert!(allow_upgrade_to_concurrent_fungible_balance(), error::invalid_argument(ECONCURRENT_BALANCE_NOT_ENABLED)); - ensure_store_upgraded_to_concurrent_internal(fungible_store_address); + ensure_store_upgraded_to_concurrent_internal(object::object_address(&store)); }
diff --git a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md index 040514b0139..efb76243673 100644 --- a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md +++ b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md @@ -36,8 +36,6 @@ - [Function `initialize`](#@Specification_1_initialize) - [Function `initialize_governed_gas_pool_extension`](#@Specification_1_initialize_governed_gas_pool_extension) - [Function `fund`](#@Specification_1_fund) - - [Function `deposit`](#@Specification_1_deposit) - - [Function `deposit_gas_fee`](#@Specification_1_deposit_gas_fee) - [Function `deposit_gas_fee_v2`](#@Specification_1_deposit_gas_fee_v2) - [Function `deposit_treasury`](#@Specification_1_deposit_treasury) - [Function `withdraw_staking_reward`](#@Specification_1_withdraw_staking_reward) @@ -334,7 +332,7 @@ Initializes the governed gas pool around a resource account creation seed. reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(), withdraw_events: account::new_event_handle<WithdrawStakingRewardEvent>(aptos_framework), }); - } + }; } else { // generate a seed to be used to create the resource account hosting the delegation pool @@ -413,7 +411,8 @@ Initializes the governed gas pool extension alone. reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(), withdraw_events: account::new_event_handle<WithdrawStakingRewardEvent>(aptos_framework), }); - } + }; + }
@@ -555,7 +554,9 @@ Funds the destination account with a given amount of coin. let governed_gas_signer = &governed_gas_signer(); coin::deposit(account, coin::withdraw<CoinType>(governed_gas_signer, amount)); - if (features::governed_gas_pool_aggregators_enabled()) { + // Use aggregators only if feature is enabled AND counters are initialized. + // This avoids aborts between feature rollout and extension initialization. + if (features::governed_gas_pool_aggregators_enabled() && exists<GovernedGasPoolCounters>(@aptos_framework)) { let counters = borrow_global_mut<GovernedGasPoolCounters>(@aptos_framework); aggregator_v2::add(&mut counters.governance_funded_total, amount); }; @@ -697,6 +698,7 @@ Deposits gas fees into the governed gas pool. Deposits gas fees into the governed gas pool. @param gas_payer The address of the account that paid the gas fees. @param gas_fee The amount of gas fees to be deposited. +Note: tracked via aggregator when feature is enabled.
public(friend) fun deposit_gas_fee_v2(gas_payer: address, gas_fee: u64)
@@ -717,7 +719,9 @@ Deposits gas fees into the governed gas pool.
         deposit_from<AptosCoin>(gas_payer, gas_fee);
     };
 
-    if (features::governed_gas_pool_aggregators_enabled()) {
+    // Use aggregators only if feature is enabled AND counters are initialized.
+    // This avoids aborts between feature rollout and extension initialization.
+    if (features::governed_gas_pool_aggregators_enabled() && exists<GovernedGasPoolCounters>(@aptos_framework)) {
         let counters = borrow_global_mut<GovernedGasPoolCounters>(@aptos_framework);
         aggregator_v2::add(&mut counters.gas_fee_total, gas_fee);
     };
@@ -750,7 +754,9 @@ Deposits from the treasury account. Treasury deposit are recorded.
     let treasury_account_address = signer::address_of(treasury_account);
     deposit_from<AptosCoin>(treasury_account_address, amount);
 
-    if (features::governed_gas_pool_aggregators_enabled()) {
+    // Use aggregators only if feature is enabled AND counters are initialized.
+    // This avoids aborts between feature rollout and extension initialization.
+    if (features::governed_gas_pool_aggregators_enabled() && exists<GovernedGasPoolCounters>(@aptos_framework)) {
         let counters = borrow_global_mut<GovernedGasPoolCounters>(@aptos_framework);
         aggregator_v2::add(&mut counters.treasury_total, amount);
     } else {
@@ -821,7 +827,13 @@ governed gas pool to authorize the withdrawal.
     let balance = get_balance<CoinType>();
     assert!(balance >= amount, EINSUFFICIENT_BALANCE);
 
-    if (features::governed_gas_pool_aggregators_enabled()) {
+    // Perform the withdrawal first so that any insufficient-balance aborts happen
+    // before event emission or aggregator updates (reduces wasted work on abort/retry).
+    let reward = coin::withdraw<CoinType>(&governed_gas_signer(), amount);
+
+    // Use aggregators only if feature is enabled AND counters are initialized.
+    // This avoids aborts between feature rollout and extension initialization.
+    if (features::governed_gas_pool_aggregators_enabled() && exists<GovernedGasPoolCounters>(@aptos_framework)) {
         let counters = borrow_global_mut<GovernedGasPoolCounters>(@aptos_framework);
         aggregator_v2::add(&mut counters.reward_withdrawn_total, amount);
         event::emit_event(
@@ -836,8 +848,7 @@ governed gas pool to authorize the withdrawal.
         );
     };
 
-    // Withdraw reward coin.
-    coin::withdraw<CoinType>(&governed_gas_signer(), amount)
+    reward
 }
 
@@ -875,7 +886,7 @@ Register Aptos coin with Governed gas signer. ## Function `get_gas_fee_total` -Returns a snapshot of the total gas fees collected. +Returns a snapshot of the total gas fees collected (aggregator-backed).
#[view]
@@ -1046,16 +1057,7 @@ Abort if the governed gas pool has insufficient funds
 
- - - -### Function `deposit` - - -
fun deposit<CoinType>(coin: coin::Coin<CoinType>)
-
- - +[high-level-req-5.2] Spec for fund
pragma aborts_if_is_partial = true;
@@ -1063,17 +1065,6 @@ Abort if the governed gas pool has insufficient funds
 
 
 
-
-
-### Function `deposit_gas_fee`
-
-
-
public fun deposit_gas_fee(_gas_payer: address, _gas_fee: u64)
-
- - - - ### Function `deposit_gas_fee_v2` diff --git a/aptos-move/framework/aptos-framework/doc/ordered_map.md b/aptos-move/framework/aptos-framework/doc/ordered_map.md index 9042ddb3a64..78995bdbb8a 100644 --- a/aptos-move/framework/aptos-framework/doc/ordered_map.md +++ b/aptos-move/framework/aptos-framework/doc/ordered_map.md @@ -762,16 +762,6 @@ Takes all elements from other and adds them to self, r if (ord.is_eq()) { // we skip the entries one, and below put in the result one from other. overwritten.push_back(self.entries.pop_back()); - - if (cur_i == 0) { - // make other_entries empty, and rest in entries. - // TODO cannot use mem::swap until it is public/released - // mem::swap(&mut self.entries, &mut other_entries); - self.entries.append(other_entries); - break; - } else { - cur_i -= 1; - }; }; reverse_result.push_back(other_entries.pop_back()); diff --git a/aptos-move/framework/aptos-framework/doc/stake.md b/aptos-move/framework/aptos-framework/doc/stake.md index 62a39294ee3..6b7b42fdf01 100644 --- a/aptos-move/framework/aptos-framework/doc/stake.md +++ b/aptos-move/framework/aptos-framework/doc/stake.md @@ -120,8 +120,7 @@ or if their stake drops below the min required, they would get removed at the en - [Function `append`](#0x1_stake_append) - [Function `find_validator`](#0x1_stake_find_validator) - [Function `generate_validator_info`](#0x1_stake_generate_validator_info) -- [Function `get_voting_power`](#0x1_stake_get_voting_power) -- [Function `settle_expired_pending_inactive`](#0x1_stake_settle_expired_pending_inactive) +- [Function `get_next_epoch_voting_power`](#0x1_stake_get_next_epoch_voting_power) - [Function `update_voting_power_increase`](#0x1_stake_update_voting_power_increase) - [Function `assert_stake_pool_exists`](#0x1_stake_assert_stake_pool_exists) - [Function `configure_allowed_validators`](#0x1_stake_configure_allowed_validators) @@ -2898,7 +2897,7 @@ Add coins into pool_address. this requires the corresp }; let (_, maximum_stake) = staking_config::get_required_stake(&staking_config::get()); - let voting_power = get_voting_power(stake_pool); + let voting_power = get_next_epoch_voting_power(stake_pool); assert!(voting_power <= maximum_stake, error::invalid_argument(ESTAKE_EXCEEDS_MAX)); if (std::features::module_event_migration_enabled()) { @@ -3288,12 +3287,7 @@ This internal version can only be called by the Genesis module during Genesis. let config = staking_config::get(); let (minimum_stake, maximum_stake) = staking_config::get_required_stake(&config); - // The pool was inactive while held outside the validator set; its `pending_inactive` - // is never touched by the per-epoch update routine. Settle any expired stake here so - // the min/max-stake check (and the published voting power on join) reflect the - // post-sweep view. - settle_expired_pending_inactive(stake_pool, timestamp::now_seconds()); - let voting_power = get_voting_power(stake_pool); + let voting_power = get_next_epoch_voting_power(stake_pool); assert!(voting_power >= minimum_stake, error::invalid_argument(ESTAKE_TOO_LOW)); assert!(voting_power <= maximum_stake, error::invalid_argument(ESTAKE_TOO_HIGH)); @@ -3559,7 +3553,7 @@ Can only be called by the operator of the validator/staking pool. // Decrease the voting power increase as the pending validator's voting power was added when they requested // to join. Now that they changed their mind, their voting power should not affect the joining limit of this // epoch. - let validator_stake = (get_voting_power(stake_pool) as u128); + let validator_stake = (get_next_epoch_voting_power(stake_pool) as u128); // total_joining_power should be larger than validator_stake but just in case there has been a small // rounding error somewhere that can lead to an underflow, we still want to allow this transaction to // succeed. @@ -3741,19 +3735,6 @@ power. update_stake_pool(validator_perf, validator.addr, &config); }); - // Settle expired `pending_inactive` on each pending_active pool before it is activated. - // The per-validator update routine above runs only over active and leaving-pending_inactive - // validators, so a pool joining this epoch with an expired lockup would otherwise carry - // its unswept `pending_inactive` into the published next-epoch voting power and diverge - // from DKG's recomputation. Use the reconfig start time so all sweeps in this - // reconfiguration agree on a single comparison clock. - let reconfig_start_secs = get_reconfig_start_time_secs(); - vector::for_each_ref(&validator_set.pending_active, |validator| { - let validator: &ValidatorInfo = validator; - let pending_active_pool = borrow_global_mut<StakePool>(validator.addr); - settle_expired_pending_inactive(pending_active_pool, reconfig_start_secs); - }); - // Activate currently pending_active validators. append(&mut validator_set.active_validators, &mut validator_set.pending_active); @@ -4204,11 +4185,7 @@ This function shouldn't abort. ## Function `get_reconfig_start_time_secs` -Get the reconfiguration start time when one is in progress; otherwise fall back to the -current wall-clock time. Note: reconfiguration_state::is_initialized() is permanently -true after framework genesis, so we must gate on is_in_progress() to avoid returning the -previous reconfig's start time outside any active reconfig (which would also abort here -since start_time_secs() requires the state to be active). +Assuming we are in a middle of a reconfiguration (no matter it is immediate or async), get its start time.
fun get_reconfig_start_time_secs(): u64
@@ -4221,7 +4198,7 @@ since start_time_secs() requires the state to be active).
 
 
 
fun get_reconfig_start_time_secs(): u64 {
-    if (reconfiguration_state::is_in_progress()) {
+    if (reconfiguration_state::is_initialized()) {
         reconfiguration_state::start_time_secs()
     } else {
         timestamp::now_seconds()
@@ -4284,7 +4261,6 @@ Calculate the rewards amount.
 ## Function `distribute_rewards`
 
 Get rewards from the Governed Gas Pool corresponding to current epoch's stake and num_successful_votes.
-This function includes failsafe logic to allow epoch changes even when the governed gas pool has insufficient funds.
 
 
 
fun distribute_rewards(stake: &mut coin::Coin<aptos_coin::AptosCoin>, num_successful_proposals: u64, num_total_proposals: u64, rewards_rate: u64, rewards_rate_denominator: u64): u64
@@ -4315,29 +4291,16 @@ This function includes failsafe logic to allow epoch changes even when the gover
     } else {
         0
     };
-    let actual_rewards_amount = if (rewards_amount > 0) {
-        if (features::stake_reward_using_treasury_enabled()) {
-            // Failsafe: Check balance before attempting withdrawal to prevent epoch change from aborting
-            let available_balance = governed_gas_pool::get_balance<AptosCoin>();
-            let withdraw_amount = min(rewards_amount, available_balance);
-            if (withdraw_amount > 0) {
-                let rewards = governed_gas_pool::withdraw_staking_reward<AptosCoin>(withdraw_amount);
-                coin::merge(stake, rewards);
-                withdraw_amount
-            } else {
-                // Insufficient funds in governed gas pool - epoch change proceeds with zero rewards
-                0
-            }
+    if (rewards_amount > 0) {
+        let rewards = if (features::stake_reward_using_treasury_enabled()) {
+            governed_gas_pool::withdraw_staking_reward<AptosCoin>(rewards_amount)
         } else {
             let mint_cap = &borrow_global<AptosCoinCapabilities>(@aptos_framework).mint_cap;
-            let rewards = coin::mint(rewards_amount, mint_cap);
-            coin::merge(stake, rewards);
-            rewards_amount
-        }
-    } else {
-        0
+            coin::mint(rewards_amount, mint_cap)
+        };
+        coin::merge(stake, rewards);
     };
-    actual_rewards_amount
+    rewards_amount
 }
 
@@ -4424,7 +4387,7 @@ This function includes failsafe logic to allow epoch changes even when the gover
fun generate_validator_info(addr: address, stake_pool: &StakePool, config: ValidatorConfig): ValidatorInfo {
-    let voting_power = get_voting_power(stake_pool);
+    let voting_power = get_next_epoch_voting_power(stake_pool);
     ValidatorInfo {
         addr,
         voting_power,
@@ -4437,19 +4400,14 @@ This function includes failsafe logic to allow epoch changes even when the gover
 
 
 
-
+
 
-## Function `get_voting_power`
+## Function `get_next_epoch_voting_power`
 
-Returns the sum of a stake pool's non-inactive coin buckets
-(pending_active + active + pending_inactive). This equals the validator's
-next-epoch voting power **only** when callers have already settled any expired
-pending_inactive into inactive via settle_expired_pending_inactive. Calling
-this on a pool with unswept expired stake will overstate voting power and diverge
-from the post-sweep view DKG independently recomputes from the same buckets.
+Returns validator's next epoch voting power, including pending_active, active, and pending_inactive stake.
 
 
-
fun get_voting_power(stake_pool: &stake::StakePool): u64
+
fun get_next_epoch_voting_power(stake_pool: &stake::StakePool): u64
 
@@ -4458,7 +4416,7 @@ from the post-sweep view DKG independently recomputes from the same buckets. Implementation -
fun get_voting_power(stake_pool: &StakePool): u64 {
+
fun get_next_epoch_voting_power(stake_pool: &StakePool): u64 {
     let value_pending_active = coin::value(&stake_pool.pending_active);
     let value_active = coin::value(&stake_pool.active);
     let value_pending_inactive = coin::value(&stake_pool.pending_inactive);
@@ -4471,44 +4429,6 @@ from the post-sweep view DKG independently recomputes from the same buckets.
 
 
 
-
-
-
-
-## Function `settle_expired_pending_inactive`
-
-Move a stake pool's pending_inactive stake into inactive if its lockup has elapsed
-by the supplied cmp_time_secs. The locked_until_secs > 0 guard skips pools whose
-lockup has not yet been initialized (e.g. a freshly created pool), which would
-otherwise be considered "expired" against any positive timestamp.
-
-Used at sites that read voting power on pools the per-epoch update routine does not
-touch — joiners (pending_active validators) and inactive pools — to keep the
-framework-published voting power in agreement with DKG's post-sweep view.
-
-
-
fun settle_expired_pending_inactive(stake_pool: &mut stake::StakePool, cmp_time_secs: u64)
-
- - - -
-Implementation - - -
fun settle_expired_pending_inactive(stake_pool: &mut StakePool, cmp_time_secs: u64) {
-    if (stake_pool.locked_until_secs > 0
-        && cmp_time_secs >= stake_pool.locked_until_secs) {
-        coin::merge(
-            &mut stake_pool.inactive,
-            coin::extract_all(&mut stake_pool.pending_inactive),
-        );
-    };
-}
-
- - -
@@ -4761,6 +4681,39 @@ framework-published voting power in agreement with DKG's post-sweep view. + + + +
fun spec_validator_index_upper_bound(): u64 {
+   len(global<ValidatorPerformance>(@aptos_framework).validators)
+}
+
+ + + + + + + +
fun spec_has_stake_pool(a: address): bool {
+   exists<StakePool>(a)
+}
+
+ + + + + + + +
fun spec_has_validator_config(a: address): bool {
+   exists<ValidatorConfig>(a)
+}
+
+ + + + @@ -5436,7 +5389,7 @@ framework-published voting power in agreement with DKG's post-sweep view. option::spec_is_some(spec_find_validator(validator_set.pending_inactive, pool_address)) || option::spec_is_some(spec_find_validator(validator_set.pending_active, pool_address)); let config = staking_config::get(); -let voting_power = get_voting_power(stake_pool); +let voting_power = get_next_epoch_voting_power(stake_pool); let minimum_stake = config.minimum_stake; let maximum_stake = config.maximum_stake; aborts_if voting_power < minimum_stake; @@ -5574,7 +5527,7 @@ framework-published voting power in agreement with DKG's post-sweep view. aborts_if !validator_find_bool && vector::length(validator_set.active_validators) < 2; aborts_if validator_find_bool && vector::length(validator_set.pending_active) <= option::spec_borrow(spec_find_validator(pending_active, pool_address)); let post p_validator_set = global<ValidatorSet>(@aptos_framework); -let validator_stake = (get_voting_power(stake_pool) as u128); +let validator_stake = (get_next_epoch_voting_power(stake_pool) as u128); ensures validator_find_bool && validator_set.total_joining_power > validator_stake ==> p_validator_set.total_joining_power == validator_set.total_joining_power - validator_stake; ensures !validator_find_bool ==> !option::spec_is_some(spec_find_validator(p_validator_set.pending_active, pool_address)); @@ -5839,39 +5792,6 @@ framework-published voting power in agreement with DKG's post-sweep view. - - - - -
fun spec_validator_index_upper_bound(): u64 {
-   len(global<ValidatorPerformance>(@aptos_framework).validators)
-}
-
- - - - - - - -
fun spec_has_stake_pool(a: address): bool {
-   exists<StakePool>(a)
-}
-
- - - - - - - -
fun spec_has_validator_config(a: address): bool {
-   exists<ValidatorConfig>(a)
-}
-
- - - ### Function `update_stake_pool` diff --git a/aptos-move/framework/aptos-framework/doc/staking_config.md b/aptos-move/framework/aptos-framework/doc/staking_config.md index 16c8ccb4d0a..27f42fd19ba 100644 --- a/aptos-move/framework/aptos-framework/doc/staking_config.md +++ b/aptos-move/framework/aptos-framework/doc/staking_config.md @@ -914,8 +914,9 @@ Can only be called as part of the Aptos governance proposal process established new_voting_power_increase_limit: u64, ) acquires StakingConfig { system_addresses::assert_aptos_framework(aptos_framework); + //TODO(bowu): revert the limit back to 50 assert!( - new_voting_power_increase_limit > 0 && new_voting_power_increase_limit <= 50, + new_voting_power_increase_limit > 0 && new_voting_power_increase_limit <= 50*1_000_000_000, error::invalid_argument(EINVALID_VOTING_POWER_INCREASE_LIMIT), ); diff --git a/aptos-move/framework/aptos-framework/doc/staking_contract.md b/aptos-move/framework/aptos-framework/doc/staking_contract.md index 85a4ffa6b75..534999c039b 100644 --- a/aptos-move/framework/aptos-framework/doc/staking_contract.md +++ b/aptos-move/framework/aptos-framework/doc/staking_contract.md @@ -2212,10 +2212,6 @@ Allows staker to switch operator without going through the lenghthy process to u let staker_address = signer::address_of(staker); assert_staking_contract_exists(staker_address, old_operator); - assert!( - new_commission_percentage <= 100, - error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE), - ); // Merging two existing staking contracts is too complex as we'd need to merge two separate stake pools. let store = borrow_global_mut<Store>(staker_address); let staking_contracts = &mut store.staking_contracts; diff --git a/types/src/on_chain_config/aptos_features.rs b/types/src/on_chain_config/aptos_features.rs index baca5752346..4aa56a7f413 100644 --- a/types/src/on_chain_config/aptos_features.rs +++ b/types/src/on_chain_config/aptos_features.rs @@ -149,6 +149,7 @@ pub enum FeatureFlag { /// compiler-generated abort codes (e.g. `UNSPECIFIED_ABORT_CODE`) against /// user-defined error constants whose lower bits happen to coincide. EXTRACT_ABORT_INFO_EXACT_MATCH = 225, + GOVERNED_GAS_POOL_AGGREGATORS = 226, } impl FeatureFlag { @@ -249,6 +250,7 @@ impl FeatureFlag { // FeatureFlag::CALCULATE_TRANSACTION_FEE_FOR_DISTRIBUTION, // FeatureFlag::DISTRIBUTE_TRANSACTION_FEE, FeatureFlag::GOVERNED_GAS_POOL, + FeatureFlag::GOVERNED_GAS_POOL_AGGREGATORS, ] } } From 1acdeb21ce2d73b2a35f21d1fa3c999e82981359 Mon Sep 17 00:00:00 2001 From: Anirudh Prasad Date: Tue, 9 Dec 2025 20:25:01 +0530 Subject: [PATCH 04/20] feat: bring tps back up and remove spec invariant checks --- .../sources/governed_gas_pool.move | 45 +++++++++---------- .../sources/governed_gas_pool.spec.move | 32 +++---------- 2 files changed, 28 insertions(+), 49 deletions(-) diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move index d7f1d2966f4..95989422aa6 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move @@ -101,7 +101,7 @@ module aptos_framework::governed_gas_pool { reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(), withdraw_events: account::new_event_handle(aptos_framework), }); - } + }; } else { // generate a seed to be used to create the resource account hosting the delegation pool @@ -160,7 +160,8 @@ module aptos_framework::governed_gas_pool { reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(), withdraw_events: account::new_event_handle(aptos_framework), }); - } + }; + } /// Initialize the governed gas pool as a module @@ -255,6 +256,7 @@ module aptos_framework::governed_gas_pool { /// Deposits gas fees into the governed gas pool. /// @param gas_payer The address of the account that paid the gas fees. /// @param gas_fee The amount of gas fees to be deposited. + /// Note: tracked via aggregator when feature is enabled. public(friend) fun deposit_gas_fee_v2(gas_payer: address, gas_fee: u64) acquires GovernedGasPool, GovernedGasPoolCounters { if (gas_fee == 0) return; @@ -336,7 +338,7 @@ module aptos_framework::governed_gas_pool { // ========== View Functions for Aggregator Totals ========== #[view] - /// Returns a snapshot of the total gas fees collected. + /// Returns a snapshot of the total gas fees collected (aggregator-backed). public fun get_gas_fee_total(): AggregatorSnapshot acquires GovernedGasPoolCounters { aggregator_v2::snapshot(&borrow_global(@aptos_framework).gas_fee_total) } @@ -601,8 +603,8 @@ module aptos_framework::governed_gas_pool { } #[test(aptos_framework = @aptos_framework, depositor = @0xdddd)] - /// Test gas fee tracking with aggregators enabled - fun test_gas_fee_tracking_with_aggregators( + /// Test that gas fees are NOT tracked (for performance - hot path) + fun test_gas_fee_not_tracked_for_performance( aptos_framework: &signer, depositor: &signer ) acquires GovernedGasPool, GovernedGasPoolCounters, AptosCoinMintCapability { @@ -616,12 +618,12 @@ module aptos_framework::governed_gas_pool { deposit_gas_fee_v2(signer::address_of(depositor), 200); deposit_gas_fee_v2(signer::address_of(depositor), 300); + // Gas fees are NOT tracked in aggregators (hot path optimization) let gas_total = aggregator_v2::read_snapshot(&get_gas_fee_total()); - assert!(gas_total == 600, 1); + assert!(gas_total == 0, 1); - deposit_gas_fee_v2(signer::address_of(depositor), 0); - let gas_total_after = aggregator_v2::read_snapshot(&get_gas_fee_total()); - assert!(gas_total_after == 600, 2); + // But balance should reflect the deposits + assert!(get_balance() >= 600, 2); } #[test(aptos_framework = @aptos_framework, treasury = @0xdddd)] @@ -691,7 +693,8 @@ module aptos_framework::governed_gas_pool { } #[test(aptos_framework = @aptos_framework, treasury = @0xdddd, beneficiary = @0xbbbb)] - /// Comprehensive test: verify accounting invariant (inflows >= outflows) + /// Comprehensive test: verify accounting for tracked flows (treasury/governance/rewards) + /// Note: Gas fees are not tracked for performance, so they're excluded from this test fun test_accounting_invariant_with_aggregators( aptos_framework: &signer, treasury: &signer, @@ -705,9 +708,7 @@ module aptos_framework::governed_gas_pool { aptos_account::register_apt(beneficiary); mint_for_test(signer::address_of(treasury), 100000); - // INFLOWS - deposit_gas_fee_v2(signer::address_of(treasury), 1000); - deposit_gas_fee_v2(signer::address_of(treasury), 2000); + // INFLOWS (treasury tracked, gas fees not tracked) deposit_treasury(treasury, 5000); // OUTFLOWS @@ -715,22 +716,20 @@ module aptos_framework::governed_gas_pool { let reward = withdraw_staking_reward(300); coin::deposit(signer::address_of(beneficiary), reward); - let gas_total = aggregator_v2::read_snapshot(&get_gas_fee_total()); let treasury_total = aggregator_v2::read_snapshot(&get_treasury_total()); let governance_total = aggregator_v2::read_snapshot(&get_governance_funded_total()); let reward_total = aggregator_v2::read_snapshot(&get_reward_withdrawn_total()); - assert!(gas_total == 3000, 1); - assert!(treasury_total == 5000, 2); - assert!(governance_total == 500, 3); - assert!(reward_total == 300, 4); + assert!(treasury_total == 5000, 1); + assert!(governance_total == 500, 2); + assert!(reward_total == 300, 3); - let total_inflows = gas_total + treasury_total; - let total_outflows = governance_total + reward_total; - assert!(total_outflows <= total_inflows, 5); + // Accounting invariant: tracked outflows <= tracked inflows + assert!(governance_total + reward_total <= treasury_total, 4); - let expected_balance = total_inflows - total_outflows; - assert!(get_balance() == expected_balance, 6); + // Balance should reflect: treasury - governance - rewards + let expected_balance = treasury_total - governance_total - reward_total; + assert!(get_balance() == expected_balance, 5); } #[test(aptos_framework = @aptos_framework)] diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move index c77b195ef5e..efda8b6fb47 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move @@ -46,6 +46,7 @@ spec aptos_framework::governed_gas_pool { /// [high-level-req-1] /// The GovernedGasPool resource must exist at aptos_framework after initialization. invariant exists(@aptos_framework); + // Note: Aggregator invariants are omitted in specs to avoid unsupported snapshot expressions. } spec initialize(aptos_framework: &signer, delegation_pool_creation_seed: vector) { @@ -65,32 +66,6 @@ spec aptos_framework::governed_gas_pool { aborts_with coin::EINSUFFICIENT_BALANCE, error::invalid_argument(EINSUFFICIENT_BALANCE), 0x1, 0x5, 0x7; } - spec deposit(coin: Coin) { - pragma aborts_if_is_partial = true; - - /* - /// [high-level-req-3] - /// Ensure the deposit increases the value in the CoinStore - - //@TODO: Calling governed_gas_pool_adddress() doesn't work as the boogie gen cant check the signer - // created for the resource account created at runtime - - /// Ensure the governed gas pool resource account exists - //aborts_if !exists>(governed_gas_pool_address()); - - //ensures global>(aptos_framework_address).coin.value == - //old(global>(aptos_framework_address).coin.value) + coin.value; - */ - } - - spec deposit_gas_fee(_gas_payer: address, _gas_fee: u64) { - /* - /// [high-level-req-5] - // ensures governed_gas_pool_balance == old(governed_gas_pool_balance) + gas_fee; - // ensures gas_payer_balance == old(gas_payer_balance) - gas_fee; - */ - } - /// [high-level-req-5] Spec for deposit_gas_fee_v2 spec deposit_gas_fee_v2(gas_payer: address, gas_fee: u64) { pragma aborts_if_is_partial = true; @@ -101,6 +76,11 @@ spec aptos_framework::governed_gas_pool { pragma aborts_if_is_partial = true; } + /// [high-level-req-5.2] Spec for fund + spec fund(aptos_framework: &signer, account: address, amount: u64) { + pragma aborts_if_is_partial = true; + } + /// [high-level-req-5.3] Spec for withdraw_staking_reward spec withdraw_staking_reward(amount: u64): Coin { pragma aborts_if_is_partial = true; From 4dc2e4b7cecf122fb6815015d9385419312d9f34 Mon Sep 17 00:00:00 2001 From: Anirudh Prasad Date: Wed, 17 Dec 2025 09:46:17 +0530 Subject: [PATCH 05/20] fix: address possible race condition --- .../doc/governed_gas_pool_aggregator_test.md | 30 +++++++++++++++++ .../sources/governed_gas_pool.move | 33 ++++++++++++------- 2 files changed, 52 insertions(+), 11 deletions(-) create mode 100644 aptos-move/framework/aptos-framework/doc/governed_gas_pool_aggregator_test.md diff --git a/aptos-move/framework/aptos-framework/doc/governed_gas_pool_aggregator_test.md b/aptos-move/framework/aptos-framework/doc/governed_gas_pool_aggregator_test.md new file mode 100644 index 00000000000..d7ce186248d --- /dev/null +++ b/aptos-move/framework/aptos-framework/doc/governed_gas_pool_aggregator_test.md @@ -0,0 +1,30 @@ + + + +# Module `0x1::governed_gas_pool_aggregator_test` + +Isolated test to verify Aggregator V2 parallelism for GGP +This test creates multiple concurrent aggregator updates and measures performance + + +- [Constants](#@Constants_0) + + +
+ + + + + +## Constants + + + + + + +
const EAGGREGATOR_NOT_PARALLEL: u64 = 1;
+
+ + +[move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move index 95989422aa6..2ed7c99646b 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move @@ -203,7 +203,9 @@ module aptos_framework::governed_gas_pool { let governed_gas_signer = &governed_gas_signer(); coin::deposit(account, coin::withdraw(governed_gas_signer, amount)); - if (features::governed_gas_pool_aggregators_enabled()) { + // Use aggregators only if feature is enabled AND counters are initialized. + // This avoids aborts between feature rollout and extension initialization. + if (features::governed_gas_pool_aggregators_enabled() && exists(@aptos_framework)) { let counters = borrow_global_mut(@aptos_framework); aggregator_v2::add(&mut counters.governance_funded_total, amount); }; @@ -266,7 +268,9 @@ module aptos_framework::governed_gas_pool { deposit_from(gas_payer, gas_fee); }; - if (features::governed_gas_pool_aggregators_enabled()) { + // Use aggregators only if feature is enabled AND counters are initialized. + // This avoids aborts between feature rollout and extension initialization. + if (features::governed_gas_pool_aggregators_enabled() && exists(@aptos_framework)) { let counters = borrow_global_mut(@aptos_framework); aggregator_v2::add(&mut counters.gas_fee_total, gas_fee); }; @@ -279,7 +283,9 @@ module aptos_framework::governed_gas_pool { let treasury_account_address = signer::address_of(treasury_account); deposit_from(treasury_account_address, amount); - if (features::governed_gas_pool_aggregators_enabled()) { + // Use aggregators only if feature is enabled AND counters are initialized. + // This avoids aborts between feature rollout and extension initialization. + if (features::governed_gas_pool_aggregators_enabled() && exists(@aptos_framework)) { let counters = borrow_global_mut(@aptos_framework); aggregator_v2::add(&mut counters.treasury_total, amount); } else { @@ -310,7 +316,13 @@ module aptos_framework::governed_gas_pool { let balance = get_balance(); assert!(balance >= amount, EINSUFFICIENT_BALANCE); - if (features::governed_gas_pool_aggregators_enabled()) { + // Perform the withdrawal first so that any insufficient-balance aborts happen + // before event emission or aggregator updates (reduces wasted work on abort/retry). + let reward = coin::withdraw(&governed_gas_signer(), amount); + + // Use aggregators only if feature is enabled AND counters are initialized. + // This avoids aborts between feature rollout and extension initialization. + if (features::governed_gas_pool_aggregators_enabled() && exists(@aptos_framework)) { let counters = borrow_global_mut(@aptos_framework); aggregator_v2::add(&mut counters.reward_withdrawn_total, amount); event::emit_event( @@ -325,8 +337,7 @@ module aptos_framework::governed_gas_pool { ); }; - // Withdraw reward coin. - coin::withdraw(&governed_gas_signer(), amount) + reward } /// Register Aptos coin with Governed gas signer. @@ -603,8 +614,8 @@ module aptos_framework::governed_gas_pool { } #[test(aptos_framework = @aptos_framework, depositor = @0xdddd)] - /// Test that gas fees are NOT tracked (for performance - hot path) - fun test_gas_fee_not_tracked_for_performance( + /// Test that gas fees ARE tracked with aggregators when feature is enabled + fun test_gas_fee_tracking_with_aggregators( aptos_framework: &signer, depositor: &signer ) acquires GovernedGasPool, GovernedGasPoolCounters, AptosCoinMintCapability { @@ -618,11 +629,11 @@ module aptos_framework::governed_gas_pool { deposit_gas_fee_v2(signer::address_of(depositor), 200); deposit_gas_fee_v2(signer::address_of(depositor), 300); - // Gas fees are NOT tracked in aggregators (hot path optimization) + // Gas fees ARE tracked in aggregators when feature is enabled let gas_total = aggregator_v2::read_snapshot(&get_gas_fee_total()); - assert!(gas_total == 0, 1); + assert!(gas_total == 600, 1); - // But balance should reflect the deposits + // Balance should reflect the deposits assert!(get_balance() >= 600, 2); } From b669e39e3c6f56d68b4fb9a7d6626813935f426b Mon Sep 17 00:00:00 2001 From: Sean Young Date: Thu, 11 Jun 2026 16:15:17 +0100 Subject: [PATCH 06/20] fix racey --- .../smoke-test/src/aptos_cli/validator.rs | 52 +++++++++++++++---- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/testsuite/smoke-test/src/aptos_cli/validator.rs b/testsuite/smoke-test/src/aptos_cli/validator.rs index 852c0badcd5..9ba2c9ab3fa 100644 --- a/testsuite/smoke-test/src/aptos_cli/validator.rs +++ b/testsuite/smoke-test/src/aptos_cli/validator.rs @@ -1745,15 +1745,18 @@ async fn test_multivalidator_staking_reward_impl() { tokio::time::sleep(Duration::from_secs(5)).await; // Trigger epoch change - let epoch_result = reconfig( + let epoch_state = reconfig( &rest_client, &transaction_factory, swarm.chain_info().root_account(), ) .await; - // Get state after epoch - let (epoch_state, epoch_validator_set) = get_validator_set_and_state(&rest_client).await; + // Read the validator set at the exact version the reconfig produced — not + // "latest", which can drift forward due to background (timer-based) epoch + // changes and make the per-epoch reward deltas race intermittently. + let epoch_validator_set = + get_validator_set_at_version(&rest_client, epoch_state.version).await; println!( "\n=== After Round {} (Blockchain Epoch: {}, Version: {}) ===", epoch_num, epoch_state.epoch, epoch_state.version @@ -1804,15 +1807,15 @@ async fn test_multivalidator_staking_reward_impl() { // Store final epoch info if epoch_num == 2 { - final_epoch_info = Some((epoch_result, epoch_state, epoch_validator_set)); + final_epoch_info = Some((epoch_state, epoch_validator_set)); } } // Extract final epoch data - let (final_epoch_result, final_state, final_validator_set) = final_epoch_info.unwrap(); + let (final_state, final_validator_set) = final_epoch_info.unwrap(); // Calculate actual epoch count and expected rate - let actual_epochs = final_epoch_result.epoch - initial_state.epoch; + let actual_epochs = final_state.epoch - initial_state.epoch; let expected_rate = per_epoch_rate * (actual_epochs as f64); println!( @@ -1880,16 +1883,16 @@ async fn test_multivalidator_staking_reward_impl() { // Use the CLI to analyze validator performance cli.analyze_validator_performance( Some(initial_state.epoch as i64), - Some(final_epoch_result.epoch as i64), + Some(final_state.epoch as i64), ) .await .unwrap(); // Verify we ran through at least 2 epochs (may be more due to initialization) assert!( - final_epoch_result.epoch - initial_state.epoch >= 2, + final_state.epoch - initial_state.epoch >= 2, "Should have progressed through at least 2 epochs, actual: {}", - final_epoch_result.epoch - initial_state.epoch + final_state.epoch - initial_state.epoch ); // Fetch and verify WithdrawStakingRewardEvent amounts match the stake rewards @@ -1977,6 +1980,30 @@ async fn get_validator_set_and_state(rest_client: &Client) -> (State, HashMap HashMap { + let validator_set: ValidatorSet = rest_client + .get_account_resource_at_version_bcs( + CORE_CODE_ADDRESS, + "0x1::stake::ValidatorSet", + version, + ) + .await + .unwrap() + .into_inner(); + + validator_set + .active_validators + .iter() + .map(|v| (v.account_address, v.consensus_voting_power())) + .collect::>() +} + /// Creates a Features object with specific features disabled for testing /// Disables FA migration features (treasury rewards will be enabled via governance after GGP has balance) /// Disables: @@ -2163,7 +2190,7 @@ async fn test_governed_gas_pool_depletion_failsafe_impl() { // Before the failsafe fix, this would ABORT if pool balance < required rewards // After the fix, this should SUCCEED with partial or zero rewards println!("\nTriggering epoch change #{}...", epoch_num); - let _epoch_result = reconfig( + let epoch_state = reconfig( &rest_client, &transaction_factory, swarm.chain_info().root_account(), @@ -2171,7 +2198,10 @@ async fn test_governed_gas_pool_depletion_failsafe_impl() { .await; // Get state after epoch - if we get here, epoch change succeeded! - let (epoch_state, epoch_validator_set) = get_validator_set_and_state(&rest_client).await; + // Read the validator set at the exact version the reconfig produced, so it + // can't drift due to background (timer-based) epoch changes. + let epoch_validator_set = + get_validator_set_at_version(&rest_client, epoch_state.version).await; println!( "Epoch change #{} SUCCEEDED! (Blockchain Epoch: {}, Version: {})", epoch_num, epoch_state.epoch, epoch_state.version From 47a1dd5f91bbfd196f3325018fbe39c6ab8090ed Mon Sep 17 00:00:00 2001 From: Sean Young Date: Wed, 24 Jun 2026 16:44:40 +0100 Subject: [PATCH 07/20] really fix race --- .../src/components/feature_flags.rs | 1 + .../aptos-framework/doc/fungible_asset.md | 35 +++- .../aptos-framework/doc/governed_gas_pool.md | 35 +++- .../aptos-framework/doc/ordered_map.md | 10 + .../framework/aptos-framework/doc/stake.md | 188 +++++++++++++----- .../aptos-framework/doc/staking_config.md | 3 +- .../aptos-framework/doc/staking_contract.md | 20 ++ .../sources/governed_gas_pool.move | 14 +- .../framework/move-stdlib/doc/features.md | 1 + testsuite/single_node_performance.py | 2 +- 10 files changed, 247 insertions(+), 62 deletions(-) diff --git a/aptos-move/aptos-release-builder/src/components/feature_flags.rs b/aptos-move/aptos-release-builder/src/components/feature_flags.rs index 90060fb3fb4..5ead6761292 100644 --- a/aptos-move/aptos-release-builder/src/components/feature_flags.rs +++ b/aptos-move/aptos-release-builder/src/components/feature_flags.rs @@ -581,6 +581,7 @@ impl From for FeatureFlag { AptosFeatureFlag::EXTRACT_ABORT_INFO_EXACT_MATCH => { FeatureFlag::ExtractAbortInfoExactMatch }, + _ => todo!(), } } } diff --git a/aptos-move/framework/aptos-framework/doc/fungible_asset.md b/aptos-move/framework/aptos-framework/doc/fungible_asset.md index f43390ecf8d..583099be5c6 100644 --- a/aptos-move/framework/aptos-framework/doc/fungible_asset.md +++ b/aptos-move/framework/aptos-framework/doc/fungible_asset.md @@ -68,6 +68,7 @@ metadata object can be any object that equipped with + +## Function `is_asset_type_dispatchable` + +Return whether a fungible asset type has any dispatch or derived-supply hooks registered. + + +
#[view]
+public fun is_asset_type_dispatchable(metadata: object::Object<fungible_asset::Metadata>): bool
+
+ + + +
+Implementation + + +
public fun is_asset_type_dispatchable(metadata: Object<Metadata>): bool {
+    let metadata_addr = object::object_address(&metadata);
+    exists<DispatchFunctionStore>(metadata_addr) || exists<DeriveSupply>(metadata_addr)
+}
+
+ + +
@@ -4271,8 +4299,13 @@ Decrease the supply of a fungible asset by burning. ) acquires FungibleStore { assert!(object::owns(store, signer::address_of(owner)), error::permission_denied(ENOT_STORE_OWNER)); assert!(!is_frozen(store), error::invalid_argument(ESTORE_IS_FROZEN)); + let fungible_store_address = object::object_address(&store); + // be graceful if ConcurrentFungibleBalance already exists, but flag is off + if (exists<ConcurrentFungibleBalance>(fungible_store_address)) { + return + }; assert!(allow_upgrade_to_concurrent_fungible_balance(), error::invalid_argument(ECONCURRENT_BALANCE_NOT_ENABLED)); - ensure_store_upgraded_to_concurrent_internal(object::object_address(&store)); + ensure_store_upgraded_to_concurrent_internal(fungible_store_address); }
diff --git a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md index efb76243673..3010bcb1197 100644 --- a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md +++ b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md @@ -14,6 +14,7 @@ - [Function `create_resource_account_seed`](#0x1_governed_gas_pool_create_resource_account_seed) - [Function `initialize`](#0x1_governed_gas_pool_initialize) - [Function `initialize_governed_gas_pool_extension`](#0x1_governed_gas_pool_initialize_governed_gas_pool_extension) +- [Function `upgrade_pool_store_to_concurrent`](#0x1_governed_gas_pool_upgrade_pool_store_to_concurrent) - [Function `init_module`](#0x1_governed_gas_pool_init_module) - [Function `governed_gas_signer`](#0x1_governed_gas_pool_governed_gas_signer) - [Function `governed_gas_pool_address`](#0x1_governed_gas_pool_governed_gas_pool_address) @@ -313,7 +314,7 @@ Initializes the governed gas pool around a resource account creation seed.
public fun initialize(
     aptos_framework: &signer,
     delegation_pool_creation_seed: vector<u8>,
-) {
+) acquires GovernedGasPool {
     system_addresses::assert_aptos_framework(aptos_framework);
 
     // return if the governed gas pool has already been initialized
@@ -325,6 +326,8 @@ Initializes the governed gas pool around a resource account creation seed.
             });
         };
         if (!exists<GovernedGasPoolCounters>(signer::address_of(aptos_framework))) {
+            upgrade_pool_store_to_concurrent(&governed_gas_signer());
+
             move_to(aptos_framework, GovernedGasPoolCounters{
                 gas_fee_total: aggregator_v2::create_unbounded_aggregator(),
                 treasury_total: aggregator_v2::create_unbounded_aggregator(),
@@ -351,6 +354,8 @@ Initializes the governed gas pool around a resource account creation seed.
             withdraw_staking_reward_events: account::new_event_handle<WithdrawStakingRewardEvent>(aptos_framework),
         });
 
+        upgrade_pool_store_to_concurrent(&governed_gas_pool_signer);
+
         move_to(aptos_framework, GovernedGasPoolCounters{
             gas_fee_total: aggregator_v2::create_unbounded_aggregator(),
             treasury_total: aggregator_v2::create_unbounded_aggregator(),
@@ -418,6 +423,32 @@ Initializes the governed gas pool extension alone.
 
 
 
+
+
+
+
+## Function `upgrade_pool_store_to_concurrent`
+
+
+
+
fun upgrade_pool_store_to_concurrent(pool_signer: &signer)
+
+ + + +
+Implementation + + +
fun upgrade_pool_store_to_concurrent(pool_signer: &signer) {
+    let store_addr = primary_fungible_store_address(signer::address_of(pool_signer));
+    let store = object::address_to_object<fungible_asset::FungibleStore>(store_addr);
+    fungible_asset::upgrade_store_to_concurrent(pool_signer, store);
+}
+
+ + +
@@ -437,7 +468,7 @@ Initialize the governed gas pool as a module Implementation -
fun init_module(aptos_framework: &signer) {
+
fun init_module(aptos_framework: &signer) acquires GovernedGasPool {
     // Initialize the governed gas pool
     let seed : vector<u8> = b"aptos_framework::governed_gas_pool";
     initialize(aptos_framework, seed);
diff --git a/aptos-move/framework/aptos-framework/doc/ordered_map.md b/aptos-move/framework/aptos-framework/doc/ordered_map.md
index 78995bdbb8a..9042ddb3a64 100644
--- a/aptos-move/framework/aptos-framework/doc/ordered_map.md
+++ b/aptos-move/framework/aptos-framework/doc/ordered_map.md
@@ -762,6 +762,16 @@ Takes all elements from other and adds them to self, r
             if (ord.is_eq()) {
                 // we skip the entries one, and below put in the result one from other.
                 overwritten.push_back(self.entries.pop_back());
+
+                if (cur_i == 0) {
+                    // make other_entries empty, and rest in entries.
+                    // TODO cannot use mem::swap until it is public/released
+                    // mem::swap(&mut self.entries, &mut other_entries);
+                    self.entries.append(other_entries);
+                    break;
+                } else {
+                    cur_i -= 1;
+                };
             };
 
             reverse_result.push_back(other_entries.pop_back());
diff --git a/aptos-move/framework/aptos-framework/doc/stake.md b/aptos-move/framework/aptos-framework/doc/stake.md
index 6b7b42fdf01..62a39294ee3 100644
--- a/aptos-move/framework/aptos-framework/doc/stake.md
+++ b/aptos-move/framework/aptos-framework/doc/stake.md
@@ -120,7 +120,8 @@ or if their stake drops below the min required, they would get removed at the en
 -  [Function `append`](#0x1_stake_append)
 -  [Function `find_validator`](#0x1_stake_find_validator)
 -  [Function `generate_validator_info`](#0x1_stake_generate_validator_info)
--  [Function `get_next_epoch_voting_power`](#0x1_stake_get_next_epoch_voting_power)
+-  [Function `get_voting_power`](#0x1_stake_get_voting_power)
+-  [Function `settle_expired_pending_inactive`](#0x1_stake_settle_expired_pending_inactive)
 -  [Function `update_voting_power_increase`](#0x1_stake_update_voting_power_increase)
 -  [Function `assert_stake_pool_exists`](#0x1_stake_assert_stake_pool_exists)
 -  [Function `configure_allowed_validators`](#0x1_stake_configure_allowed_validators)
@@ -2897,7 +2898,7 @@ Add coins into pool_address. this requires the corresp
     };
 
     let (_, maximum_stake) = staking_config::get_required_stake(&staking_config::get());
-    let voting_power = get_next_epoch_voting_power(stake_pool);
+    let voting_power = get_voting_power(stake_pool);
     assert!(voting_power <= maximum_stake, error::invalid_argument(ESTAKE_EXCEEDS_MAX));
 
     if (std::features::module_event_migration_enabled()) {
@@ -3287,7 +3288,12 @@ This internal version can only be called by the Genesis module during Genesis.
 
     let config = staking_config::get();
     let (minimum_stake, maximum_stake) = staking_config::get_required_stake(&config);
-    let voting_power = get_next_epoch_voting_power(stake_pool);
+    // The pool was inactive while held outside the validator set; its `pending_inactive`
+    // is never touched by the per-epoch update routine. Settle any expired stake here so
+    // the min/max-stake check (and the published voting power on join) reflect the
+    // post-sweep view.
+    settle_expired_pending_inactive(stake_pool, timestamp::now_seconds());
+    let voting_power = get_voting_power(stake_pool);
     assert!(voting_power >= minimum_stake, error::invalid_argument(ESTAKE_TOO_LOW));
     assert!(voting_power <= maximum_stake, error::invalid_argument(ESTAKE_TOO_HIGH));
 
@@ -3553,7 +3559,7 @@ Can only be called by the operator of the validator/staking pool.
         // Decrease the voting power increase as the pending validator's voting power was added when they requested
         // to join. Now that they changed their mind, their voting power should not affect the joining limit of this
         // epoch.
-        let validator_stake = (get_next_epoch_voting_power(stake_pool) as u128);
+        let validator_stake = (get_voting_power(stake_pool) as u128);
         // total_joining_power should be larger than validator_stake but just in case there has been a small
         // rounding error somewhere that can lead to an underflow, we still want to allow this transaction to
         // succeed.
@@ -3735,6 +3741,19 @@ power.
         update_stake_pool(validator_perf, validator.addr, &config);
     });
 
+    // Settle expired `pending_inactive` on each pending_active pool before it is activated.
+    // The per-validator update routine above runs only over active and leaving-pending_inactive
+    // validators, so a pool joining this epoch with an expired lockup would otherwise carry
+    // its unswept `pending_inactive` into the published next-epoch voting power and diverge
+    // from DKG's recomputation. Use the reconfig start time so all sweeps in this
+    // reconfiguration agree on a single comparison clock.
+    let reconfig_start_secs = get_reconfig_start_time_secs();
+    vector::for_each_ref(&validator_set.pending_active, |validator| {
+        let validator: &ValidatorInfo = validator;
+        let pending_active_pool = borrow_global_mut<StakePool>(validator.addr);
+        settle_expired_pending_inactive(pending_active_pool, reconfig_start_secs);
+    });
+
     // Activate currently pending_active validators.
     append(&mut validator_set.active_validators, &mut validator_set.pending_active);
 
@@ -4185,7 +4204,11 @@ This function shouldn't abort.
 
 ## Function `get_reconfig_start_time_secs`
 
-Assuming we are in a middle of a reconfiguration (no matter it is immediate or async), get its start time.
+Get the reconfiguration start time when one is in progress; otherwise fall back to the
+current wall-clock time. Note: reconfiguration_state::is_initialized() is permanently
+true after framework genesis, so we must gate on is_in_progress() to avoid returning the
+previous reconfig's start time outside any active reconfig (which would also abort here
+since start_time_secs() requires the state to be active).
 
 
 
fun get_reconfig_start_time_secs(): u64
@@ -4198,7 +4221,7 @@ Assuming we are in a middle of a reconfiguration (no matter it is immediate or a
 
 
 
fun get_reconfig_start_time_secs(): u64 {
-    if (reconfiguration_state::is_initialized()) {
+    if (reconfiguration_state::is_in_progress()) {
         reconfiguration_state::start_time_secs()
     } else {
         timestamp::now_seconds()
@@ -4261,6 +4284,7 @@ Calculate the rewards amount.
 ## Function `distribute_rewards`
 
 Get rewards from the Governed Gas Pool corresponding to current epoch's stake and num_successful_votes.
+This function includes failsafe logic to allow epoch changes even when the governed gas pool has insufficient funds.
 
 
 
fun distribute_rewards(stake: &mut coin::Coin<aptos_coin::AptosCoin>, num_successful_proposals: u64, num_total_proposals: u64, rewards_rate: u64, rewards_rate_denominator: u64): u64
@@ -4291,16 +4315,29 @@ Get rewards from the Governed Gas Pool corresponding to current epoch's else {
         0
     };
-    if (rewards_amount > 0) {
-        let rewards = if (features::stake_reward_using_treasury_enabled()) {
-            governed_gas_pool::withdraw_staking_reward<AptosCoin>(rewards_amount)
+    let actual_rewards_amount = if (rewards_amount > 0) {
+        if (features::stake_reward_using_treasury_enabled()) {
+            // Failsafe: Check balance before attempting withdrawal to prevent epoch change from aborting
+            let available_balance = governed_gas_pool::get_balance<AptosCoin>();
+            let withdraw_amount = min(rewards_amount, available_balance);
+            if (withdraw_amount > 0) {
+                let rewards = governed_gas_pool::withdraw_staking_reward<AptosCoin>(withdraw_amount);
+                coin::merge(stake, rewards);
+                withdraw_amount
+            } else {
+                // Insufficient funds in governed gas pool - epoch change proceeds with zero rewards
+                0
+            }
         } else {
             let mint_cap = &borrow_global<AptosCoinCapabilities>(@aptos_framework).mint_cap;
-            coin::mint(rewards_amount, mint_cap)
-        };
-        coin::merge(stake, rewards);
+            let rewards = coin::mint(rewards_amount, mint_cap);
+            coin::merge(stake, rewards);
+            rewards_amount
+        }
+    } else {
+        0
     };
-    rewards_amount
+    actual_rewards_amount
 }
 
@@ -4387,7 +4424,7 @@ Get rewards from the Governed Gas Pool corresponding to current epoch's fun generate_validator_info(addr: address, stake_pool: &StakePool, config: ValidatorConfig): ValidatorInfo { - let voting_power = get_next_epoch_voting_power(stake_pool); + let voting_power = get_voting_power(stake_pool); ValidatorInfo { addr, voting_power, @@ -4400,14 +4437,19 @@ Get rewards from the Governed Gas Pool corresponding to current epoch's - + -## Function `get_next_epoch_voting_power` +## Function `get_voting_power` -Returns validator's next epoch voting power, including pending_active, active, and pending_inactive stake. +Returns the sum of a stake pool's non-inactive coin buckets +(pending_active + active + pending_inactive). This equals the validator's +next-epoch voting power **only** when callers have already settled any expired +pending_inactive into inactive via settle_expired_pending_inactive. Calling +this on a pool with unswept expired stake will overstate voting power and diverge +from the post-sweep view DKG independently recomputes from the same buckets. -
fun get_next_epoch_voting_power(stake_pool: &stake::StakePool): u64
+
fun get_voting_power(stake_pool: &stake::StakePool): u64
 
@@ -4416,7 +4458,7 @@ Returns validator's next epoch voting power, including pending_active, active, a Implementation -
fun get_next_epoch_voting_power(stake_pool: &StakePool): u64 {
+
fun get_voting_power(stake_pool: &StakePool): u64 {
     let value_pending_active = coin::value(&stake_pool.pending_active);
     let value_active = coin::value(&stake_pool.active);
     let value_pending_inactive = coin::value(&stake_pool.pending_inactive);
@@ -4429,6 +4471,44 @@ Returns validator's next epoch voting power, including pending_active, active, a
 
 
 
+
+
+
+
+## Function `settle_expired_pending_inactive`
+
+Move a stake pool's pending_inactive stake into inactive if its lockup has elapsed
+by the supplied cmp_time_secs. The locked_until_secs > 0 guard skips pools whose
+lockup has not yet been initialized (e.g. a freshly created pool), which would
+otherwise be considered "expired" against any positive timestamp.
+
+Used at sites that read voting power on pools the per-epoch update routine does not
+touch — joiners (pending_active validators) and inactive pools — to keep the
+framework-published voting power in agreement with DKG's post-sweep view.
+
+
+
fun settle_expired_pending_inactive(stake_pool: &mut stake::StakePool, cmp_time_secs: u64)
+
+ + + +
+Implementation + + +
fun settle_expired_pending_inactive(stake_pool: &mut StakePool, cmp_time_secs: u64) {
+    if (stake_pool.locked_until_secs > 0
+        && cmp_time_secs >= stake_pool.locked_until_secs) {
+        coin::merge(
+            &mut stake_pool.inactive,
+            coin::extract_all(&mut stake_pool.pending_inactive),
+        );
+    };
+}
+
+ + +
@@ -4681,39 +4761,6 @@ Returns validator's next epoch voting power, including pending_active, active, a - - - -
fun spec_validator_index_upper_bound(): u64 {
-   len(global<ValidatorPerformance>(@aptos_framework).validators)
-}
-
- - - - - - - -
fun spec_has_stake_pool(a: address): bool {
-   exists<StakePool>(a)
-}
-
- - - - - - - -
fun spec_has_validator_config(a: address): bool {
-   exists<ValidatorConfig>(a)
-}
-
- - - - @@ -5389,7 +5436,7 @@ Returns validator's next epoch voting power, including pending_active, active, a option::spec_is_some(spec_find_validator(validator_set.pending_inactive, pool_address)) || option::spec_is_some(spec_find_validator(validator_set.pending_active, pool_address)); let config = staking_config::get(); -let voting_power = get_next_epoch_voting_power(stake_pool); +let voting_power = get_voting_power(stake_pool); let minimum_stake = config.minimum_stake; let maximum_stake = config.maximum_stake; aborts_if voting_power < minimum_stake; @@ -5527,7 +5574,7 @@ Returns validator's next epoch voting power, including pending_active, active, a aborts_if !validator_find_bool && vector::length(validator_set.active_validators) < 2; aborts_if validator_find_bool && vector::length(validator_set.pending_active) <= option::spec_borrow(spec_find_validator(pending_active, pool_address)); let post p_validator_set = global<ValidatorSet>(@aptos_framework); -let validator_stake = (get_next_epoch_voting_power(stake_pool) as u128); +let validator_stake = (get_voting_power(stake_pool) as u128); ensures validator_find_bool && validator_set.total_joining_power > validator_stake ==> p_validator_set.total_joining_power == validator_set.total_joining_power - validator_stake; ensures !validator_find_bool ==> !option::spec_is_some(spec_find_validator(p_validator_set.pending_active, pool_address)); @@ -5792,6 +5839,39 @@ Returns validator's next epoch voting power, including pending_active, active, a + + + + +
fun spec_validator_index_upper_bound(): u64 {
+   len(global<ValidatorPerformance>(@aptos_framework).validators)
+}
+
+ + + + + + + +
fun spec_has_stake_pool(a: address): bool {
+   exists<StakePool>(a)
+}
+
+ + + + + + + +
fun spec_has_validator_config(a: address): bool {
+   exists<ValidatorConfig>(a)
+}
+
+ + + ### Function `update_stake_pool` diff --git a/aptos-move/framework/aptos-framework/doc/staking_config.md b/aptos-move/framework/aptos-framework/doc/staking_config.md index 27f42fd19ba..16c8ccb4d0a 100644 --- a/aptos-move/framework/aptos-framework/doc/staking_config.md +++ b/aptos-move/framework/aptos-framework/doc/staking_config.md @@ -914,9 +914,8 @@ Can only be called as part of the Aptos governance proposal process established new_voting_power_increase_limit: u64, ) acquires StakingConfig { system_addresses::assert_aptos_framework(aptos_framework); - //TODO(bowu): revert the limit back to 50 assert!( - new_voting_power_increase_limit > 0 && new_voting_power_increase_limit <= 50*1_000_000_000, + new_voting_power_increase_limit > 0 && new_voting_power_increase_limit <= 50, error::invalid_argument(EINVALID_VOTING_POWER_INCREASE_LIMIT), ); diff --git a/aptos-move/framework/aptos-framework/doc/staking_contract.md b/aptos-move/framework/aptos-framework/doc/staking_contract.md index 534999c039b..4df53db1a5f 100644 --- a/aptos-move/framework/aptos-framework/doc/staking_contract.md +++ b/aptos-move/framework/aptos-framework/doc/staking_contract.md @@ -1319,6 +1319,16 @@ Store amount must be at least the min stake required for a stake pool to join th + + +Beneficiary cannot be a reserved address that cannot receive coin distributions. + + +
const EINVALID_BENEFICIARY_ADDRESS: u64 = 10;
+
+ + + Caller must be either the staker, operator, or beneficiary. @@ -2212,6 +2222,10 @@ Allows staker to switch operator without going through the lenghthy process to u let staker_address = signer::address_of(staker); assert_staking_contract_exists(staker_address, old_operator); + assert!( + new_commission_percentage <= 100, + error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE), + ); // Merging two existing staking contracts is too complex as we'd need to merge two separate stake pools. let store = borrow_global_mut<Store>(staker_address); let staking_contracts = &mut store.staking_contracts; @@ -2279,6 +2293,12 @@ the beneficiary. An operator can set one beneficiary for staking contract pools, assert!(features::operator_beneficiary_change_enabled(), std::error::invalid_state( EOPERATOR_BENEFICIARY_CHANGE_NOT_SUPPORTED )); + // @vm_reserved can never have an account created for it, so it can't receive coin distributions. + // Allowing it as a beneficiary would permanently brick distribution for the staking contract. + assert!( + new_beneficiary != @vm_reserved, + error::invalid_argument(EINVALID_BENEFICIARY_ADDRESS), + ); // The beneficiay address of an operator is stored under the operator's address. // So, the operator does not need to be validated with respect to a staking pool. let operator_addr = signer::address_of(operator); diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move index 2ed7c99646b..d9d3d0d5ce1 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move @@ -82,7 +82,7 @@ module aptos_framework::governed_gas_pool { public fun initialize( aptos_framework: &signer, delegation_pool_creation_seed: vector, - ) { + ) acquires GovernedGasPool { system_addresses::assert_aptos_framework(aptos_framework); // return if the governed gas pool has already been initialized @@ -94,6 +94,8 @@ module aptos_framework::governed_gas_pool { }); }; if (!exists(signer::address_of(aptos_framework))) { + upgrade_pool_store_to_concurrent(&governed_gas_signer()); + move_to(aptos_framework, GovernedGasPoolCounters{ gas_fee_total: aggregator_v2::create_unbounded_aggregator(), treasury_total: aggregator_v2::create_unbounded_aggregator(), @@ -120,6 +122,8 @@ module aptos_framework::governed_gas_pool { withdraw_staking_reward_events: account::new_event_handle(aptos_framework), }); + upgrade_pool_store_to_concurrent(&governed_gas_pool_signer); + move_to(aptos_framework, GovernedGasPoolCounters{ gas_fee_total: aggregator_v2::create_unbounded_aggregator(), treasury_total: aggregator_v2::create_unbounded_aggregator(), @@ -164,9 +168,15 @@ module aptos_framework::governed_gas_pool { } + fun upgrade_pool_store_to_concurrent(pool_signer: &signer) { + let store_addr = primary_fungible_store_address(signer::address_of(pool_signer)); + let store = object::address_to_object(store_addr); + fungible_asset::upgrade_store_to_concurrent(pool_signer, store); + } + /// Initialize the governed gas pool as a module /// @param aptos_framework The signer of the aptos_framework module. - fun init_module(aptos_framework: &signer) { + fun init_module(aptos_framework: &signer) acquires GovernedGasPool { // Initialize the governed gas pool let seed : vector = b"aptos_framework::governed_gas_pool"; initialize(aptos_framework, seed); diff --git a/aptos-move/framework/move-stdlib/doc/features.md b/aptos-move/framework/move-stdlib/doc/features.md index c8b14d2fab1..4abf40ed32c 100644 --- a/aptos-move/framework/move-stdlib/doc/features.md +++ b/aptos-move/framework/move-stdlib/doc/features.md @@ -863,6 +863,7 @@ Lifetime: transient Whether the Atomic bridge is available Lifetime: transient +Deprecated in favor of ALLOW_SERIALIZED_SCRIPT_ARGS as feature flag 72
const NATIVE_BRIDGE: u64 = 72;
diff --git a/testsuite/single_node_performance.py b/testsuite/single_node_performance.py
index 82a361c5749..027c260c938 100755
--- a/testsuite/single_node_performance.py
+++ b/testsuite/single_node_performance.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 # Copyright © Aptos Foundation
 # SPDX-License-Identifier: Apache-2.0

From 551b7d3ac624e722114b85d197de8af838db9bd9 Mon Sep 17 00:00:00 2001
From: Sean Young 
Date: Thu, 25 Jun 2026 14:30:40 +0100
Subject: [PATCH 08/20] merge

---
 .../src/components/feature_flags.rs           |   1 -
 .../aptos-framework/doc/governed_gas_pool.md  | 256 +--------------
 .../sources/governed_gas_pool.move            | 292 +-----------------
 .../framework/move-stdlib/doc/features.md     |  61 ----
 .../move-stdlib/sources/configs/features.move |  12 -
 types/src/on_chain_config/aptos_features.rs   |   2 -
 6 files changed, 29 insertions(+), 595 deletions(-)

diff --git a/aptos-move/aptos-release-builder/src/components/feature_flags.rs b/aptos-move/aptos-release-builder/src/components/feature_flags.rs
index 5ead6761292..90060fb3fb4 100644
--- a/aptos-move/aptos-release-builder/src/components/feature_flags.rs
+++ b/aptos-move/aptos-release-builder/src/components/feature_flags.rs
@@ -581,7 +581,6 @@ impl From for FeatureFlag {
             AptosFeatureFlag::EXTRACT_ABORT_INFO_EXACT_MATCH => {
                 FeatureFlag::ExtractAbortInfoExactMatch
             },
-            _ => todo!(),
         }
     }
 }
diff --git a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md
index 3010bcb1197..e82140017fb 100644
--- a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md
+++ b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md
@@ -8,7 +8,6 @@
 -  [Struct `WithdrawStakingRewardEvent`](#0x1_governed_gas_pool_WithdrawStakingRewardEvent)
 -  [Resource `GovernedGasPool`](#0x1_governed_gas_pool_GovernedGasPool)
 -  [Resource `GovernedGasPoolExtension`](#0x1_governed_gas_pool_GovernedGasPoolExtension)
--  [Resource `GovernedGasPoolCounters`](#0x1_governed_gas_pool_GovernedGasPoolCounters)
 -  [Constants](#@Constants_0)
 -  [Function `primary_fungible_store_address`](#0x1_governed_gas_pool_primary_fungible_store_address)
 -  [Function `create_resource_account_seed`](#0x1_governed_gas_pool_create_resource_account_seed)
@@ -29,10 +28,6 @@
 -  [Function `get_balance`](#0x1_governed_gas_pool_get_balance)
 -  [Function `withdraw_staking_reward`](#0x1_governed_gas_pool_withdraw_staking_reward)
 -  [Function `register_coin`](#0x1_governed_gas_pool_register_coin)
--  [Function `get_gas_fee_total`](#0x1_governed_gas_pool_get_gas_fee_total)
--  [Function `get_treasury_total`](#0x1_governed_gas_pool_get_treasury_total)
--  [Function `get_governance_funded_total`](#0x1_governed_gas_pool_get_governance_funded_total)
--  [Function `get_reward_withdrawn_total`](#0x1_governed_gas_pool_get_reward_withdrawn_total)
 -  [Specification](#@Specification_1)
     -  [Function `initialize`](#@Specification_1_initialize)
     -  [Function `initialize_governed_gas_pool_extension`](#@Specification_1_initialize_governed_gas_pool_extension)
@@ -43,7 +38,6 @@
 
 
 
use 0x1::account;
-use 0x1::aggregator_v2;
 use 0x1::aptos_account;
 use 0x1::aptos_coin;
 use 0x1::coin;
@@ -148,58 +142,6 @@ Contains added variable needed for the GovernedGasPool staking reward update.
 
 
 
-
-
-
-
-## Resource `GovernedGasPoolCounters`
-
-Aggregator-backed counters for parallel gas pool accounting.
-
-
-
struct GovernedGasPoolCounters has key
-
- - - -
-Fields - - -
-
-gas_fee_total: aggregator_v2::Aggregator<u64> -
-
- -
-
-treasury_total: aggregator_v2::Aggregator<u64> -
-
- -
-
-governance_funded_total: aggregator_v2::Aggregator<u64> -
-
- -
-
-reward_withdrawn_total: aggregator_v2::Aggregator<u64> -
-
- -
-
-withdraw_events: event::EventHandle<governed_gas_pool::WithdrawStakingRewardEvent> -
-
- -
-
- -
@@ -325,17 +267,8 @@ Initializes the governed gas pool around a resource account creation seed. withdraw_staking_reward_events: account::new_event_handle<WithdrawStakingRewardEvent>(aptos_framework), }); }; - if (!exists<GovernedGasPoolCounters>(signer::address_of(aptos_framework))) { - upgrade_pool_store_to_concurrent(&governed_gas_signer()); - - move_to(aptos_framework, GovernedGasPoolCounters{ - gas_fee_total: aggregator_v2::create_unbounded_aggregator(), - treasury_total: aggregator_v2::create_unbounded_aggregator(), - governance_funded_total: aggregator_v2::create_unbounded_aggregator(), - reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(), - withdraw_events: account::new_event_handle<WithdrawStakingRewardEvent>(aptos_framework), - }); - }; + + upgrade_pool_store_to_concurrent(&governed_gas_signer()); } else { // generate a seed to be used to create the resource account hosting the delegation pool @@ -355,14 +288,6 @@ Initializes the governed gas pool around a resource account creation seed. }); upgrade_pool_store_to_concurrent(&governed_gas_pool_signer); - - move_to(aptos_framework, GovernedGasPoolCounters{ - gas_fee_total: aggregator_v2::create_unbounded_aggregator(), - treasury_total: aggregator_v2::create_unbounded_aggregator(), - governance_funded_total: aggregator_v2::create_unbounded_aggregator(), - reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(), - withdraw_events: account::new_event_handle<WithdrawStakingRewardEvent>(aptos_framework), - }); } }
@@ -390,7 +315,7 @@ Initializes the governed gas pool extension alone.
public entry fun initialize_governed_gas_pool_extension(
     aptos_framework: &signer,
-) acquires GovernedGasPoolExtension {
+)  {
     system_addresses::assert_aptos_framework(aptos_framework);
 
     // return if the governed gas extension has already been initialized
@@ -400,24 +325,6 @@ Initializes the governed gas pool extension alone.
             withdraw_staking_reward_events: account::new_event_handle<WithdrawStakingRewardEvent>(aptos_framework),
         });
     };
-
-    // Create counters resource if missing (migration path)
-    if (!exists<GovernedGasPoolCounters>(signer::address_of(aptos_framework))) {
-        let legacy_treasury_total = if (exists<GovernedGasPoolExtension>(signer::address_of(aptos_framework))) {
-            borrow_global<GovernedGasPoolExtension>(@aptos_framework).deposited_treasury_counter
-        } else {
-            0
-        };
-
-        move_to(aptos_framework, GovernedGasPoolCounters{
-            gas_fee_total: aggregator_v2::create_unbounded_aggregator(),
-            treasury_total: aggregator_v2::create_unbounded_aggregator_with_value(legacy_treasury_total),
-            governance_funded_total: aggregator_v2::create_unbounded_aggregator(),
-            reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(),
-            withdraw_events: account::new_event_handle<WithdrawStakingRewardEvent>(aptos_framework),
-        });
-    };
-
 }
 
@@ -577,20 +484,13 @@ Funds the destination account with a given amount of coin. Implementation -
public fun fund<CoinType>(aptos_framework: &signer, account: address, amount: u64) acquires GovernedGasPool, GovernedGasPoolCounters {
+
public fun fund<CoinType>(aptos_framework: &signer, account: address, amount: u64) acquires GovernedGasPool {
     // Check that the Aptos framework is the caller
     // This is what ensures that funding can only be done by the Aptos framework,
     // i.e., via a governance proposal.
     system_addresses::assert_aptos_framework(aptos_framework);
     let governed_gas_signer = &governed_gas_signer();
     coin::deposit(account, coin::withdraw<CoinType>(governed_gas_signer, amount));
-
-    // Use aggregators only if feature is enabled AND counters are initialized.
-    // This avoids aborts between feature rollout and extension initialization.
-    if (features::governed_gas_pool_aggregators_enabled() && exists<GovernedGasPoolCounters>(@aptos_framework)) {
-        let counters = borrow_global_mut<GovernedGasPoolCounters>(@aptos_framework);
-        aggregator_v2::add(&mut counters.governance_funded_total, amount);
-    };
 }
 
@@ -729,7 +629,6 @@ Deposits gas fees into the governed gas pool. Deposits gas fees into the governed gas pool. @param gas_payer The address of the account that paid the gas fees. @param gas_fee The amount of gas fees to be deposited. -Note: tracked via aggregator when feature is enabled.
public(friend) fun deposit_gas_fee_v2(gas_payer: address, gas_fee: u64)
@@ -741,7 +640,7 @@ Note: tracked via aggregator when feature is enabled.
 Implementation
 
 
-
public(friend) fun deposit_gas_fee_v2(gas_payer: address, gas_fee: u64) acquires GovernedGasPool, GovernedGasPoolCounters {
+
public(friend) fun deposit_gas_fee_v2(gas_payer: address, gas_fee: u64) acquires GovernedGasPool {
     if (gas_fee == 0) return;
 
     if (features::operations_default_to_fa_apt_store_enabled()) {
@@ -749,13 +648,6 @@ Note: tracked via aggregator when feature is enabled.
     } else {
         deposit_from<AptosCoin>(gas_payer, gas_fee);
     };
-
-    // Use aggregators only if feature is enabled AND counters are initialized.
-    // This avoids aborts between feature rollout and extension initialization.
-    if (features::governed_gas_pool_aggregators_enabled() && exists<GovernedGasPoolCounters>(@aptos_framework)) {
-        let counters = borrow_global_mut<GovernedGasPoolCounters>(@aptos_framework);
-        aggregator_v2::add(&mut counters.gas_fee_total, gas_fee);
-    };
 }
 
@@ -781,19 +673,12 @@ Deposits from the treasury account. Treasury deposit are recorded. Implementation -
public entry fun deposit_treasury(treasury_account: &signer, amount: u64) acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters {
+
public entry fun deposit_treasury(treasury_account: &signer, amount: u64) acquires GovernedGasPool, GovernedGasPoolExtension {
     let treasury_account_address = signer::address_of(treasury_account);
     deposit_from<AptosCoin>(treasury_account_address, amount);
 
-    // Use aggregators only if feature is enabled AND counters are initialized.
-    // This avoids aborts between feature rollout and extension initialization.
-    if (features::governed_gas_pool_aggregators_enabled() && exists<GovernedGasPoolCounters>(@aptos_framework)) {
-        let counters = borrow_global_mut<GovernedGasPoolCounters>(@aptos_framework);
-        aggregator_v2::add(&mut counters.treasury_total, amount);
-    } else {
-        let ggp = borrow_global_mut<GovernedGasPoolExtension>(@aptos_framework);
-        ggp.deposited_treasury_counter = ggp.deposited_treasury_counter + amount;
-    };
+    let ggp = borrow_global_mut<GovernedGasPoolExtension>(@aptos_framework);
+    ggp.deposited_treasury_counter = ggp.deposited_treasury_counter + amount;
 }
 
@@ -854,7 +739,7 @@ governed gas pool to authorize the withdrawal.
public(friend) fun withdraw_staking_reward<CoinType>(
     amount: u64
-): Coin<CoinType> acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters {
+): Coin<CoinType> acquires GovernedGasPool, GovernedGasPoolExtension  {
     let balance = get_balance<CoinType>();
     assert!(balance >= amount, EINSUFFICIENT_BALANCE);
 
@@ -864,20 +749,11 @@ governed gas pool to authorize the withdrawal.
 
     // Use aggregators only if feature is enabled AND counters are initialized.
     // This avoids aborts between feature rollout and extension initialization.
-    if (features::governed_gas_pool_aggregators_enabled() && exists<GovernedGasPoolCounters>(@aptos_framework)) {
-        let counters = borrow_global_mut<GovernedGasPoolCounters>(@aptos_framework);
-        aggregator_v2::add(&mut counters.reward_withdrawn_total, amount);
-        event::emit_event(
-            &mut counters.withdraw_events,
-            WithdrawStakingRewardEvent { amount },
-        );
-    } else {
-        let ggpv2 = borrow_global_mut<GovernedGasPoolExtension>(@aptos_framework);
-        event::emit_event(
-            &mut ggpv2.withdraw_staking_reward_events,
-            WithdrawStakingRewardEvent { amount },
-        );
-    };
+    let ggpv2 = borrow_global_mut<GovernedGasPoolExtension>(@aptos_framework);
+    event::emit_event(
+        &mut ggpv2.withdraw_staking_reward_events,
+        WithdrawStakingRewardEvent { amount },
+    );
 
     reward
 }
@@ -911,110 +787,6 @@ Register Aptos coin with Governed gas signer.
 
 
 
-
-
-
-
-## Function `get_gas_fee_total`
-
-Returns a snapshot of the total gas fees collected (aggregator-backed).
-
-
-
#[view]
-public fun get_gas_fee_total(): aggregator_v2::AggregatorSnapshot<u64>
-
- - - -
-Implementation - - -
public fun get_gas_fee_total(): AggregatorSnapshot<u64> acquires GovernedGasPoolCounters {
-    aggregator_v2::snapshot(&borrow_global<GovernedGasPoolCounters>(@aptos_framework).gas_fee_total)
-}
-
- - - -
- - - -## Function `get_treasury_total` - -Returns a snapshot of the total treasury deposits. - - -
#[view]
-public fun get_treasury_total(): aggregator_v2::AggregatorSnapshot<u64>
-
- - - -
-Implementation - - -
public fun get_treasury_total(): AggregatorSnapshot<u64> acquires GovernedGasPoolCounters {
-    aggregator_v2::snapshot(&borrow_global<GovernedGasPoolCounters>(@aptos_framework).treasury_total)
-}
-
- - - -
- - - -## Function `get_governance_funded_total` - -Returns a snapshot of the total governance-funded payouts. - - -
#[view]
-public fun get_governance_funded_total(): aggregator_v2::AggregatorSnapshot<u64>
-
- - - -
-Implementation - - -
public fun get_governance_funded_total(): AggregatorSnapshot<u64> acquires GovernedGasPoolCounters {
-    aggregator_v2::snapshot(&borrow_global<GovernedGasPoolCounters>(@aptos_framework).governance_funded_total)
-}
-
- - - -
- - - -## Function `get_reward_withdrawn_total` - -Returns a snapshot of the total staking rewards withdrawn. - - -
#[view]
-public fun get_reward_withdrawn_total(): aggregator_v2::AggregatorSnapshot<u64>
-
- - - -
-Implementation - - -
public fun get_reward_withdrawn_total(): AggregatorSnapshot<u64> acquires GovernedGasPoolCounters {
-    aggregator_v2::snapshot(&borrow_global<GovernedGasPoolCounters>(@aptos_framework).reward_withdrawn_total)
-}
-
- - -
diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move index d9d3d0d5ce1..5aa0f54810d 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move @@ -14,7 +14,6 @@ module aptos_framework::governed_gas_pool { use std::features; use aptos_framework::signer; use aptos_framework::aptos_account::Self; - use aptos_framework::aggregator_v2::{Self, Aggregator, AggregatorSnapshot}; #[test_only] use aptos_framework::coin::{BurnCapability, MintCapability}; #[test_only] @@ -50,15 +49,6 @@ module aptos_framework::governed_gas_pool { withdraw_staking_reward_events: EventHandle, } - /// Aggregator-backed counters for parallel gas pool accounting. - struct GovernedGasPoolCounters has key { - gas_fee_total: Aggregator, - treasury_total: Aggregator, - governance_funded_total: Aggregator, - reward_withdrawn_total: Aggregator, - withdraw_events: EventHandle, - } - /// Address of APT Primary Fungible Store inline fun primary_fungible_store_address(account: address): address { object::create_user_derived_object_address(account, @aptos_fungible_asset) @@ -93,17 +83,8 @@ module aptos_framework::governed_gas_pool { withdraw_staking_reward_events: account::new_event_handle(aptos_framework), }); }; - if (!exists(signer::address_of(aptos_framework))) { - upgrade_pool_store_to_concurrent(&governed_gas_signer()); - - move_to(aptos_framework, GovernedGasPoolCounters{ - gas_fee_total: aggregator_v2::create_unbounded_aggregator(), - treasury_total: aggregator_v2::create_unbounded_aggregator(), - governance_funded_total: aggregator_v2::create_unbounded_aggregator(), - reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(), - withdraw_events: account::new_event_handle(aptos_framework), - }); - }; + + upgrade_pool_store_to_concurrent(&governed_gas_signer()); } else { // generate a seed to be used to create the resource account hosting the delegation pool @@ -123,14 +104,6 @@ module aptos_framework::governed_gas_pool { }); upgrade_pool_store_to_concurrent(&governed_gas_pool_signer); - - move_to(aptos_framework, GovernedGasPoolCounters{ - gas_fee_total: aggregator_v2::create_unbounded_aggregator(), - treasury_total: aggregator_v2::create_unbounded_aggregator(), - governance_funded_total: aggregator_v2::create_unbounded_aggregator(), - reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(), - withdraw_events: account::new_event_handle(aptos_framework), - }); } } @@ -138,7 +111,7 @@ module aptos_framework::governed_gas_pool { /// @param aptos_framework The signer of the aptos_framework module. public entry fun initialize_governed_gas_pool_extension( aptos_framework: &signer, - ) acquires GovernedGasPoolExtension { + ) { system_addresses::assert_aptos_framework(aptos_framework); // return if the governed gas extension has already been initialized @@ -148,24 +121,6 @@ module aptos_framework::governed_gas_pool { withdraw_staking_reward_events: account::new_event_handle(aptos_framework), }); }; - - // Create counters resource if missing (migration path) - if (!exists(signer::address_of(aptos_framework))) { - let legacy_treasury_total = if (exists(signer::address_of(aptos_framework))) { - borrow_global(@aptos_framework).deposited_treasury_counter - } else { - 0 - }; - - move_to(aptos_framework, GovernedGasPoolCounters{ - gas_fee_total: aggregator_v2::create_unbounded_aggregator(), - treasury_total: aggregator_v2::create_unbounded_aggregator_with_value(legacy_treasury_total), - governance_funded_total: aggregator_v2::create_unbounded_aggregator(), - reward_withdrawn_total: aggregator_v2::create_unbounded_aggregator(), - withdraw_events: account::new_event_handle(aptos_framework), - }); - }; - } fun upgrade_pool_store_to_concurrent(pool_signer: &signer) { @@ -205,20 +160,13 @@ module aptos_framework::governed_gas_pool { /// Funds the destination account with a given amount of coin. /// @param account The account to be funded. /// @param amount The amount of coin to be funded. - public fun fund(aptos_framework: &signer, account: address, amount: u64) acquires GovernedGasPool, GovernedGasPoolCounters { + public fun fund(aptos_framework: &signer, account: address, amount: u64) acquires GovernedGasPool { // Check that the Aptos framework is the caller // This is what ensures that funding can only be done by the Aptos framework, // i.e., via a governance proposal. system_addresses::assert_aptos_framework(aptos_framework); let governed_gas_signer = &governed_gas_signer(); coin::deposit(account, coin::withdraw(governed_gas_signer, amount)); - - // Use aggregators only if feature is enabled AND counters are initialized. - // This avoids aborts between feature rollout and extension initialization. - if (features::governed_gas_pool_aggregators_enabled() && exists(@aptos_framework)) { - let counters = borrow_global_mut(@aptos_framework); - aggregator_v2::add(&mut counters.governance_funded_total, amount); - }; } /// Deposits some coin into the governed gas pool. @@ -268,8 +216,7 @@ module aptos_framework::governed_gas_pool { /// Deposits gas fees into the governed gas pool. /// @param gas_payer The address of the account that paid the gas fees. /// @param gas_fee The amount of gas fees to be deposited. - /// Note: tracked via aggregator when feature is enabled. - public(friend) fun deposit_gas_fee_v2(gas_payer: address, gas_fee: u64) acquires GovernedGasPool, GovernedGasPoolCounters { + public(friend) fun deposit_gas_fee_v2(gas_payer: address, gas_fee: u64) acquires GovernedGasPool { if (gas_fee == 0) return; if (features::operations_default_to_fa_apt_store_enabled()) { @@ -277,31 +224,17 @@ module aptos_framework::governed_gas_pool { } else { deposit_from(gas_payer, gas_fee); }; - - // Use aggregators only if feature is enabled AND counters are initialized. - // This avoids aborts between feature rollout and extension initialization. - if (features::governed_gas_pool_aggregators_enabled() && exists(@aptos_framework)) { - let counters = borrow_global_mut(@aptos_framework); - aggregator_v2::add(&mut counters.gas_fee_total, gas_fee); - }; } /// Deposits from the treasury account. Treasury deposit are recorded. /// @param treasury_account The address of the account that paid the treasury. /// @param amount The amount of treasury to be deposited. - public entry fun deposit_treasury(treasury_account: &signer, amount: u64) acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters { + public entry fun deposit_treasury(treasury_account: &signer, amount: u64) acquires GovernedGasPool, GovernedGasPoolExtension { let treasury_account_address = signer::address_of(treasury_account); deposit_from(treasury_account_address, amount); - // Use aggregators only if feature is enabled AND counters are initialized. - // This avoids aborts between feature rollout and extension initialization. - if (features::governed_gas_pool_aggregators_enabled() && exists(@aptos_framework)) { - let counters = borrow_global_mut(@aptos_framework); - aggregator_v2::add(&mut counters.treasury_total, amount); - } else { - let ggp = borrow_global_mut(@aptos_framework); - ggp.deposited_treasury_counter = ggp.deposited_treasury_counter + amount; - }; + let ggp = borrow_global_mut(@aptos_framework); + ggp.deposited_treasury_counter = ggp.deposited_treasury_counter + amount; } #[view] @@ -322,7 +255,7 @@ module aptos_framework::governed_gas_pool { /// @return A `Coin` resource containing the withdrawn amount. public(friend) fun withdraw_staking_reward( amount: u64 - ): Coin acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters { + ): Coin acquires GovernedGasPool, GovernedGasPoolExtension { let balance = get_balance(); assert!(balance >= amount, EINSUFFICIENT_BALANCE); @@ -332,20 +265,11 @@ module aptos_framework::governed_gas_pool { // Use aggregators only if feature is enabled AND counters are initialized. // This avoids aborts between feature rollout and extension initialization. - if (features::governed_gas_pool_aggregators_enabled() && exists(@aptos_framework)) { - let counters = borrow_global_mut(@aptos_framework); - aggregator_v2::add(&mut counters.reward_withdrawn_total, amount); - event::emit_event( - &mut counters.withdraw_events, - WithdrawStakingRewardEvent { amount }, - ); - } else { - let ggpv2 = borrow_global_mut(@aptos_framework); - event::emit_event( - &mut ggpv2.withdraw_staking_reward_events, - WithdrawStakingRewardEvent { amount }, - ); - }; + let ggpv2 = borrow_global_mut(@aptos_framework); + event::emit_event( + &mut ggpv2.withdraw_staking_reward_events, + WithdrawStakingRewardEvent { amount }, + ); reward } @@ -356,32 +280,6 @@ module aptos_framework::governed_gas_pool { coin::register(&s); } - // ========== View Functions for Aggregator Totals ========== - - #[view] - /// Returns a snapshot of the total gas fees collected (aggregator-backed). - public fun get_gas_fee_total(): AggregatorSnapshot acquires GovernedGasPoolCounters { - aggregator_v2::snapshot(&borrow_global(@aptos_framework).gas_fee_total) - } - - #[view] - /// Returns a snapshot of the total treasury deposits. - public fun get_treasury_total(): AggregatorSnapshot acquires GovernedGasPoolCounters { - aggregator_v2::snapshot(&borrow_global(@aptos_framework).treasury_total) - } - - #[view] - /// Returns a snapshot of the total governance-funded payouts. - public fun get_governance_funded_total(): AggregatorSnapshot acquires GovernedGasPoolCounters { - aggregator_v2::snapshot(&borrow_global(@aptos_framework).governance_funded_total) - } - - #[view] - /// Returns a snapshot of the total staking rewards withdrawn. - public fun get_reward_withdrawn_total(): AggregatorSnapshot acquires GovernedGasPoolCounters { - aggregator_v2::snapshot(&borrow_global(@aptos_framework).reward_withdrawn_total) - } - #[test_only] /// The AptosCoin mint capability struct AptosCoinMintCapability has key { @@ -582,7 +480,7 @@ module aptos_framework::governed_gas_pool { /// Add some treasury to the governed gas pool. /// /// @param aptos_framework is the signer of the aptos_framework module. - fun test_deposite_treasury_and_counter(aptos_framework: &signer, treasury: &signer) acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters, AptosCoinMintCapability { + fun test_deposite_treasury_and_counter(aptos_framework: &signer, treasury: &signer) acquires GovernedGasPool, GovernedGasPoolExtension, AptosCoinMintCapability { // initialize the modules initialize_for_test(aptos_framework); @@ -611,164 +509,4 @@ module aptos_framework::governed_gas_pool { coin::deposit(@0xdddd, withdraw); } - // ============ Aggregator V2 Tests ============ - - #[test_only] - /// Helper to enable the aggregator feature flag for testing - fun enable_aggregator_feature_for_test(aptos_framework: &signer) { - features::change_feature_flags_for_testing( - aptos_framework, - vector[features::get_governed_gas_pool_aggregators_feature()], - vector[] - ); - } - - #[test(aptos_framework = @aptos_framework, depositor = @0xdddd)] - /// Test that gas fees ARE tracked with aggregators when feature is enabled - fun test_gas_fee_tracking_with_aggregators( - aptos_framework: &signer, - depositor: &signer - ) acquires GovernedGasPool, GovernedGasPoolCounters, AptosCoinMintCapability { - initialize_for_test(aptos_framework); - enable_aggregator_feature_for_test(aptos_framework); - - aptos_account::create_account(signer::address_of(depositor)); - mint_for_test(signer::address_of(depositor), 10000); - - deposit_gas_fee_v2(signer::address_of(depositor), 100); - deposit_gas_fee_v2(signer::address_of(depositor), 200); - deposit_gas_fee_v2(signer::address_of(depositor), 300); - - // Gas fees ARE tracked in aggregators when feature is enabled - let gas_total = aggregator_v2::read_snapshot(&get_gas_fee_total()); - assert!(gas_total == 600, 1); - - // Balance should reflect the deposits - assert!(get_balance() >= 600, 2); - } - - #[test(aptos_framework = @aptos_framework, treasury = @0xdddd)] - /// Test treasury tracking with aggregators enabled - fun test_treasury_tracking_with_aggregators( - aptos_framework: &signer, - treasury: &signer - ) acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters, AptosCoinMintCapability { - initialize_for_test(aptos_framework); - enable_aggregator_feature_for_test(aptos_framework); - - aptos_account::create_account(signer::address_of(treasury)); - mint_for_test(signer::address_of(treasury), 10000); - - deposit_treasury(treasury, 500); - deposit_treasury(treasury, 300); - - let treasury_total = aggregator_v2::read_snapshot(&get_treasury_total()); - assert!(treasury_total == 800, 1); - } - - #[test(aptos_framework = @aptos_framework, depositor = @0xdddd, beneficiary = @0xbbbb)] - /// Test governance funding tracking with aggregators enabled - fun test_governance_funding_tracking_with_aggregators( - aptos_framework: &signer, - depositor: &signer, - beneficiary: &signer - ) acquires GovernedGasPool, GovernedGasPoolCounters, AptosCoinMintCapability { - initialize_for_test(aptos_framework); - enable_aggregator_feature_for_test(aptos_framework); - - aptos_account::create_account(signer::address_of(depositor)); - aptos_account::create_account(signer::address_of(beneficiary)); - aptos_account::register_apt(beneficiary); - - mint_for_test(signer::address_of(depositor), 10000); - deposit_gas_fee_v2(signer::address_of(depositor), 5000); - - fund(aptos_framework, signer::address_of(beneficiary), 200); - fund(aptos_framework, signer::address_of(beneficiary), 100); - - let governance_total = aggregator_v2::read_snapshot(&get_governance_funded_total()); - assert!(governance_total == 300, 1); - } - - #[test(aptos_framework = @aptos_framework, treasury = @0xdddd)] - /// Test reward withdrawal tracking with aggregators enabled - fun test_reward_withdrawal_tracking_with_aggregators( - aptos_framework: &signer, - treasury: &signer - ) acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters, AptosCoinMintCapability { - initialize_for_test(aptos_framework); - enable_aggregator_feature_for_test(aptos_framework); - - aptos_account::create_account(signer::address_of(treasury)); - mint_for_test(signer::address_of(treasury), 10000); - deposit_treasury(treasury, 5000); - - let reward1 = withdraw_staking_reward(100); - let reward2 = withdraw_staking_reward(150); - - let reward_total = aggregator_v2::read_snapshot(&get_reward_withdrawn_total()); - assert!(reward_total == 250, 1); - - coin::deposit(signer::address_of(treasury), reward1); - coin::deposit(signer::address_of(treasury), reward2); - } - - #[test(aptos_framework = @aptos_framework, treasury = @0xdddd, beneficiary = @0xbbbb)] - /// Comprehensive test: verify accounting for tracked flows (treasury/governance/rewards) - /// Note: Gas fees are not tracked for performance, so they're excluded from this test - fun test_accounting_invariant_with_aggregators( - aptos_framework: &signer, - treasury: &signer, - beneficiary: &signer - ) acquires GovernedGasPool, GovernedGasPoolExtension, GovernedGasPoolCounters, AptosCoinMintCapability { - initialize_for_test(aptos_framework); - enable_aggregator_feature_for_test(aptos_framework); - - aptos_account::create_account(signer::address_of(treasury)); - aptos_account::create_account(signer::address_of(beneficiary)); - aptos_account::register_apt(beneficiary); - mint_for_test(signer::address_of(treasury), 100000); - - // INFLOWS (treasury tracked, gas fees not tracked) - deposit_treasury(treasury, 5000); - - // OUTFLOWS - fund(aptos_framework, signer::address_of(beneficiary), 500); - let reward = withdraw_staking_reward(300); - coin::deposit(signer::address_of(beneficiary), reward); - - let treasury_total = aggregator_v2::read_snapshot(&get_treasury_total()); - let governance_total = aggregator_v2::read_snapshot(&get_governance_funded_total()); - let reward_total = aggregator_v2::read_snapshot(&get_reward_withdrawn_total()); - - assert!(treasury_total == 5000, 1); - assert!(governance_total == 500, 2); - assert!(reward_total == 300, 3); - - // Accounting invariant: tracked outflows <= tracked inflows - assert!(governance_total + reward_total <= treasury_total, 4); - - // Balance should reflect: treasury - governance - rewards - let expected_balance = treasury_total - governance_total - reward_total; - assert!(get_balance() == expected_balance, 5); - } - - #[test(aptos_framework = @aptos_framework)] - /// Test that counters resource is created during initialization - fun test_counters_resource_created(aptos_framework: &signer) acquires GovernedGasPoolCounters { - initialize_for_test(aptos_framework); - - assert!(exists(@aptos_framework), 1); - - let gas_total = aggregator_v2::read_snapshot(&get_gas_fee_total()); - let treasury_total = aggregator_v2::read_snapshot(&get_treasury_total()); - let governance_total = aggregator_v2::read_snapshot(&get_governance_funded_total()); - let reward_total = aggregator_v2::read_snapshot(&get_reward_withdrawn_total()); - - assert!(gas_total == 0, 2); - assert!(treasury_total == 0, 3); - assert!(governance_total == 0, 4); - assert!(reward_total == 0, 5); - } - } diff --git a/aptos-move/framework/move-stdlib/doc/features.md b/aptos-move/framework/move-stdlib/doc/features.md index 4abf40ed32c..817df6403da 100644 --- a/aptos-move/framework/move-stdlib/doc/features.md +++ b/aptos-move/framework/move-stdlib/doc/features.md @@ -168,8 +168,6 @@ return true. - [Function `is_distribute_transaction_fee_enabled`](#0x1_features_is_distribute_transaction_fee_enabled) - [Function `get_stake_reward_using_treasury_feature`](#0x1_features_get_stake_reward_using_treasury_feature) - [Function `stake_reward_using_treasury_enabled`](#0x1_features_stake_reward_using_treasury_enabled) -- [Function `get_governed_gas_pool_aggregators_feature`](#0x1_features_get_governed_gas_pool_aggregators_feature) -- [Function `governed_gas_pool_aggregators_enabled`](#0x1_features_governed_gas_pool_aggregators_enabled) - [Function `change_feature_flags`](#0x1_features_change_feature_flags) - [Function `change_feature_flags_internal`](#0x1_features_change_feature_flags_internal) - [Function `change_feature_flags_for_next_epoch`](#0x1_features_change_feature_flags_for_next_epoch) @@ -707,19 +705,6 @@ Lifetime: permanent - - -Whether the Governed Gas Pool uses Aggregator V2 for concurrent accounting. -Enables parallel tracking of gas fees, treasury deposits, governance payouts, and rewards. - -Lifetime: transient - - -
const GOVERNED_GAS_POOL_AGGREGATORS: u64 = 225;
-
- - - Deprecated by aptos_framework::jwk_consensus_config::JWKConsensusConfig. @@ -4362,52 +4347,6 @@ Whether the Governed Gas Pool is enabled. - - - - -## Function `get_governed_gas_pool_aggregators_feature` - - - -
public fun get_governed_gas_pool_aggregators_feature(): u64
-
- - - -
-Implementation - - -
public fun get_governed_gas_pool_aggregators_feature(): u64 { GOVERNED_GAS_POOL_AGGREGATORS }
-
- - - -
- - - -## Function `governed_gas_pool_aggregators_enabled` - - - -
public fun governed_gas_pool_aggregators_enabled(): bool
-
- - - -
-Implementation - - -
public fun governed_gas_pool_aggregators_enabled(): bool acquires Features {
-    is_enabled(GOVERNED_GAS_POOL_AGGREGATORS)
-}
-
- - -
diff --git a/aptos-move/framework/move-stdlib/sources/configs/features.move b/aptos-move/framework/move-stdlib/sources/configs/features.move index 25a6334e56e..c5d7cc6b856 100644 --- a/aptos-move/framework/move-stdlib/sources/configs/features.move +++ b/aptos-move/framework/move-stdlib/sources/configs/features.move @@ -804,18 +804,6 @@ module std::features { is_enabled(STAKE_REWARD_USING_TREASURY) } - /// Whether the Governed Gas Pool uses Aggregator V2 for concurrent accounting. - /// Enables parallel tracking of gas fees, treasury deposits, governance payouts, and rewards. - /// - /// Lifetime: transient - const GOVERNED_GAS_POOL_AGGREGATORS: u64 = 225; - - public fun get_governed_gas_pool_aggregators_feature(): u64 { GOVERNED_GAS_POOL_AGGREGATORS } - - public fun governed_gas_pool_aggregators_enabled(): bool acquires Features { - is_enabled(GOVERNED_GAS_POOL_AGGREGATORS) - } - // ============================================================================================ // Feature Flag Implementation diff --git a/types/src/on_chain_config/aptos_features.rs b/types/src/on_chain_config/aptos_features.rs index 4aa56a7f413..baca5752346 100644 --- a/types/src/on_chain_config/aptos_features.rs +++ b/types/src/on_chain_config/aptos_features.rs @@ -149,7 +149,6 @@ pub enum FeatureFlag { /// compiler-generated abort codes (e.g. `UNSPECIFIED_ABORT_CODE`) against /// user-defined error constants whose lower bits happen to coincide. EXTRACT_ABORT_INFO_EXACT_MATCH = 225, - GOVERNED_GAS_POOL_AGGREGATORS = 226, } impl FeatureFlag { @@ -250,7 +249,6 @@ impl FeatureFlag { // FeatureFlag::CALCULATE_TRANSACTION_FEE_FOR_DISTRIBUTION, // FeatureFlag::DISTRIBUTE_TRANSACTION_FEE, FeatureFlag::GOVERNED_GAS_POOL, - FeatureFlag::GOVERNED_GAS_POOL_AGGREGATORS, ] } } From 2fcf88b8275d6c6b07f02237bca364ce8d0d3d7d Mon Sep 17 00:00:00 2001 From: Sean Young Date: Tue, 30 Jun 2026 15:05:58 +0100 Subject: [PATCH 09/20] Add comment --- .../framework/aptos-framework/sources/governed_gas_pool.move | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move index 5aa0f54810d..4fbf16cd477 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move @@ -86,7 +86,6 @@ module aptos_framework::governed_gas_pool { upgrade_pool_store_to_concurrent(&governed_gas_signer()); } else { - // generate a seed to be used to create the resource account hosting the delegation pool let seed = create_resource_account_seed(delegation_pool_creation_seed); @@ -123,6 +122,8 @@ module aptos_framework::governed_gas_pool { }; } + /// Ensure the pool is using aggregator_v2 for concurrentcy. + /// @param pool_signer The signer of the gas pool. fun upgrade_pool_store_to_concurrent(pool_signer: &signer) { let store_addr = primary_fungible_store_address(signer::address_of(pool_signer)); let store = object::address_to_object(store_addr); From cf665e0fe403906947d6c8e05d4d0831b15640a5 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Tue, 30 Jun 2026 15:29:09 +0100 Subject: [PATCH 10/20] fixup spec --- .../sources/governed_gas_pool.spec.move | 44 +++++-------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move index efda8b6fb47..474cb601788 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move @@ -1,4 +1,5 @@ spec aptos_framework::governed_gas_pool { + use aptos_framework::coin::EINSUFFICIENT_BALANCE; use aptos_framework::error; /// @@ -26,27 +27,11 @@ spec aptos_framework::governed_gas_pool { /// Implementation: The fund function verifies the signer is the aptos_framework address. /// Enforcement: Formally verified via [high-level-req-4](fund). /// - /// No.: 5 - /// Requirement: Aggregator-backed counters must track all inflows and outflows when the feature is enabled. - /// Criticality: High - /// Implementation: When governed_gas_pool_aggregators_enabled(), gas fees, treasury deposits, - /// governance payouts, and staking rewards are tracked in GovernedGasPoolCounters aggregators. - /// Enforcement: Formally verified via [high-level-req-5](deposit_gas_fee_v2), [high-level-req-5.1](deposit_treasury), - /// [high-level-req-5.2](fund), [high-level-req-5.3](withdraw_staking_reward). - /// - /// No.: 6 - /// Requirement: Total outflows must not exceed total inflows (accounting invariant). - /// Criticality: Critical - /// Implementation: reward_withdrawn_total + governance_funded_total <= gas_fee_total + treasury_total. - /// Note: This invariant is only meaningful for post-migration transactions as historical data is not tracked. - /// Enforcement: Documented invariant; runtime balance checks prevent overdraw. - /// spec module { /// [high-level-req-1] /// The GovernedGasPool resource must exist at aptos_framework after initialization. invariant exists(@aptos_framework); - // Note: Aggregator invariants are omitted in specs to avoid unsupported snapshot expressions. } spec initialize(aptos_framework: &signer, delegation_pool_creation_seed: vector) { @@ -66,28 +51,21 @@ spec aptos_framework::governed_gas_pool { aborts_with coin::EINSUFFICIENT_BALANCE, error::invalid_argument(EINSUFFICIENT_BALANCE), 0x1, 0x5, 0x7; } - /// [high-level-req-5] Spec for deposit_gas_fee_v2 - spec deposit_gas_fee_v2(gas_payer: address, gas_fee: u64) { + spec deposit(coin: Coin) { pragma aborts_if_is_partial = true; - } - /// [high-level-req-5.1] Spec for deposit_treasury - spec deposit_treasury(treasury_account: &signer, amount: u64) { - pragma aborts_if_is_partial = true; - } + /// [high-level-req-3] + /// Ensure the deposit increases the value in the CoinStore - /// [high-level-req-5.2] Spec for fund - spec fund(aptos_framework: &signer, account: address, amount: u64) { - pragma aborts_if_is_partial = true; - } + /// Ensure the governed gas pool resource account exists + aborts_if !exists>(governed_gas_pool_address()); - /// [high-level-req-5.3] Spec for withdraw_staking_reward - spec withdraw_staking_reward(amount: u64): Coin { - pragma aborts_if_is_partial = true; + ensures global>(aptos_framework_address).coin.value == old(global>(aptos_framework_address).coin.value) + coin.value; } - /// Spec for initialize_governed_gas_pool_extension - spec initialize_governed_gas_pool_extension(aptos_framework: &signer) { - pragma aborts_if_is_partial = true; + spec deposit_gas_fee_v2(_gas_payer: address, _gas_fee: u64) { + /// [high-level-req-3] + ensures governed_gas_pool_balance == old(governed_gas_pool_balance) + gas_fee; + ensures gas_payer_balance == old(gas_payer_balance) - gas_fee; } } From 01e9ac52efef5b2878e7f659baec92fbb72662c1 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Wed, 1 Jul 2026 10:37:48 +0100 Subject: [PATCH 11/20] more prover stuff --- .../sources/governed_gas_pool.move | 4 +-- .../sources/governed_gas_pool.spec.move | 33 ++++++++++++++----- .../aptos-framework/sources/stake.spec.move | 1 - 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move index 4fbf16cd477..f872d80f2d0 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move @@ -331,7 +331,7 @@ module aptos_framework::governed_gas_pool { /// @param aptos_framework The signer of the aptos_framework module. public fun initialize_for_test( aptos_framework: &signer, - ) { + ) acquires GovernedGasPool { // Create framework account to be able to send event. aptos_framework::account::create_account_for_test(@aptos_framework); @@ -469,7 +469,7 @@ module aptos_framework::governed_gas_pool { } #[test(aptos_framework = @aptos_framework)] - fun test_initialize_is_idempotent(aptos_framework: &signer) { + fun test_initialize_is_idempotent(aptos_framework: &signer) acquires GovernedGasPool { // initialize the governed gas pool initialize_for_test(aptos_framework); // initialize the governed gas pool again, no abort diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move index 474cb601788..6bb1346d8bc 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move @@ -1,5 +1,4 @@ spec aptos_framework::governed_gas_pool { - use aptos_framework::coin::EINSUFFICIENT_BALANCE; use aptos_framework::error; /// @@ -54,18 +53,34 @@ spec aptos_framework::governed_gas_pool { spec deposit(coin: Coin) { pragma aborts_if_is_partial = true; - /// [high-level-req-3] - /// Ensure the deposit increases the value in the CoinStore + let pool = signer::address_of(governed_gas_signer()); - /// Ensure the governed gas pool resource account exists - aborts_if !exists>(governed_gas_pool_address()); + /// [high-level-req-3] + /// The pool always has a registered CoinStore (register_coin at init), + /// so coin::deposit takes the merge branch and the balance increases by coin.value. + requires exists>(pool); - ensures global>(aptos_framework_address).coin.value == old(global>(aptos_framework_address).coin.value) + coin.value; + ensures global>(pool).coin.value + == old(global>(pool).coin.value) + coin.value; } - spec deposit_gas_fee_v2(_gas_payer: address, _gas_fee: u64) { + spec deposit_gas_fee_v2(gas_payer: address, gas_fee: u64) { + pragma aborts_if_is_partial = true; + + let pool = signer::address_of(governed_gas_signer()); + /// [high-level-req-3] - ensures governed_gas_pool_balance == old(governed_gas_pool_balance) + gas_fee; - ensures gas_payer_balance == old(gas_payer_balance) - gas_fee; + /// Characterizes the legacy coin path. The FA-store path + /// (operations_default_to_fa_apt_store_enabled) routes the fee through the + /// payer's primary fungible store instead and is not covered here. + requires gas_payer != pool; + requires exists>(pool); + requires exists>(gas_payer); + + /// The gas fee moves from the payer's store into the pool's store. + ensures global>(pool).coin.value + == old(global>(pool).coin.value) + gas_fee; + ensures global>(gas_payer).coin.value + == old(global>(gas_payer).coin.value) - gas_fee; } } diff --git a/aptos-move/framework/aptos-framework/sources/stake.spec.move b/aptos-move/framework/aptos-framework/sources/stake.spec.move index 49d17afbb88..a1cf807eb01 100644 --- a/aptos-move/framework/aptos-framework/sources/stake.spec.move +++ b/aptos-move/framework/aptos-framework/sources/stake.spec.move @@ -600,7 +600,6 @@ spec aptos_framework::stake { let amount = rewards_amount; let addr = type_info::type_of().account_address; aborts_if (rewards_amount > 0) && !exists>(addr); - modifies global>(addr); include (rewards_amount > 0) ==> coin::CoinAddAbortsIf { amount: amount }; } From a62ef31cd5938855487d1ea1dee501a52811c832 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Wed, 1 Jul 2026 11:41:29 +0100 Subject: [PATCH 12/20] more fixes --- .../aptos-framework/doc/governed_gas_pool.md | 72 +++++++------------ .../framework/aptos-framework/doc/stake.md | 23 +++--- .../sources/governed_gas_pool.move | 2 +- testsuite/single_node_performance.py | 2 +- 4 files changed, 37 insertions(+), 62 deletions(-) diff --git a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md index e82140017fb..0f0814c6cd7 100644 --- a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md +++ b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md @@ -30,11 +30,9 @@ - [Function `register_coin`](#0x1_governed_gas_pool_register_coin) - [Specification](#@Specification_1) - [Function `initialize`](#@Specification_1_initialize) - - [Function `initialize_governed_gas_pool_extension`](#@Specification_1_initialize_governed_gas_pool_extension) - [Function `fund`](#@Specification_1_fund) + - [Function `deposit`](#@Specification_1_deposit) - [Function `deposit_gas_fee_v2`](#@Specification_1_deposit_gas_fee_v2) - - [Function `deposit_treasury`](#@Specification_1_deposit_treasury) - - [Function `withdraw_staking_reward`](#@Specification_1_withdraw_staking_reward)
use 0x1::account;
@@ -270,7 +268,6 @@ Initializes the governed gas pool around a resource account creation seed.
 
         upgrade_pool_store_to_concurrent(&governed_gas_signer());
     } else {
-
         // generate a seed to be used to create the resource account hosting the delegation pool
         let seed = create_resource_account_seed(delegation_pool_creation_seed);
 
@@ -336,6 +333,8 @@ Initializes the governed gas pool extension alone.
 
 ## Function `upgrade_pool_store_to_concurrent`
 
+Ensure the pool is using aggregator_v2 for concurrentcy.
+@param pool_signer The signer of the gas pool.
 
 
 
fun upgrade_pool_store_to_concurrent(pool_signer: &signer)
@@ -819,23 +818,6 @@ Register Aptos coin with Governed gas signer.
 
 
 
-
-
-### Function `initialize_governed_gas_pool_extension`
-
-
-
public entry fun initialize_governed_gas_pool_extension(aptos_framework: &signer)
-
- - -Spec for initialize_governed_gas_pool_extension - - -
pragma aborts_if_is_partial = true;
-
- - - ### Function `fund` @@ -860,61 +842,55 @@ Abort if the governed gas pool has insufficient funds
-[high-level-req-5.2] Spec for fund - - -
pragma aborts_if_is_partial = true;
-
- - - + -### Function `deposit_gas_fee_v2` +### Function `deposit` -
public(friend) fun deposit_gas_fee_v2(gas_payer: address, gas_fee: u64)
+
fun deposit<CoinType>(coin: coin::Coin<CoinType>)
 
-[high-level-req-5] Spec for deposit_gas_fee_v2
pragma aborts_if_is_partial = true;
+let pool = signer::address_of(governed_gas_signer());
+// This enforces high-level requirement 3:
+requires exists<coin::CoinStore<CoinType>>(pool);
+ensures global<coin::CoinStore<CoinType>>(pool).coin.value
+    == old(global<coin::CoinStore<CoinType>>(pool).coin.value) + coin.value;
 
- + -### Function `deposit_treasury` +### Function `deposit_gas_fee_v2` -
public entry fun deposit_treasury(treasury_account: &signer, amount: u64)
+
public(friend) fun deposit_gas_fee_v2(gas_payer: address, gas_fee: u64)
 
-[high-level-req-5.1] Spec for deposit_treasury
pragma aborts_if_is_partial = true;
+let pool = signer::address_of(governed_gas_signer());
+// This enforces high-level requirement 3:
+requires gas_payer != pool;
+requires exists<coin::CoinStore<AptosCoin>>(pool);
+requires exists<coin::CoinStore<AptosCoin>>(gas_payer);
 
+The gas fee moves from the payer's store into the pool's store. - -### Function `withdraw_staking_reward` - - -
public(friend) fun withdraw_staking_reward<CoinType>(amount: u64): coin::Coin<CoinType>
-
- - -[high-level-req-5.3] Spec for withdraw_staking_reward - - -
pragma aborts_if_is_partial = true;
+
ensures global<coin::CoinStore<AptosCoin>>(pool).coin.value
+    == old(global<coin::CoinStore<AptosCoin>>(pool).coin.value) + gas_fee;
+ensures global<coin::CoinStore<AptosCoin>>(gas_payer).coin.value
+    == old(global<coin::CoinStore<AptosCoin>>(gas_payer).coin.value) - gas_fee;
 
diff --git a/aptos-move/framework/aptos-framework/doc/stake.md b/aptos-move/framework/aptos-framework/doc/stake.md index 62a39294ee3..bbc0fdd6ee7 100644 --- a/aptos-move/framework/aptos-framework/doc/stake.md +++ b/aptos-move/framework/aptos-framework/doc/stake.md @@ -4761,6 +4761,17 @@ framework-published voting power in agreement with DKG's post-sweep view. + + + +
fun spec_get_lockup_secs(pool_address: address): u64 {
+   global<StakePool>(pool_address).locked_until_secs
+}
+
+ + + + @@ -5996,17 +6007,6 @@ framework-published voting power in agreement with DKG's post-sweep view. - - - - -
fun spec_get_lockup_secs(pool_address: address): u64 {
-   global<StakePool>(pool_address).locked_until_secs
-}
-
- - - ### Function `calculate_rewards_amount` @@ -6099,7 +6099,6 @@ framework-published voting power in agreement with DKG's post-sweep view. let amount = rewards_amount; let addr = type_info::type_of<AptosCoin>().account_address; aborts_if (rewards_amount > 0) && !exists<coin::CoinInfo<AptosCoin>>(addr); - modifies global<coin::CoinInfo<AptosCoin>>(addr); include (rewards_amount > 0) ==> coin::CoinAddAbortsIf<AptosCoin> { amount: amount }; }
diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move index f872d80f2d0..cfe2b803190 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move @@ -256,7 +256,7 @@ module aptos_framework::governed_gas_pool { /// @return A `Coin` resource containing the withdrawn amount. public(friend) fun withdraw_staking_reward( amount: u64 - ): Coin acquires GovernedGasPool, GovernedGasPoolExtension { + ): Coin acquires GovernedGasPool, GovernedGasPoolExtension { let balance = get_balance(); assert!(balance >= amount, EINSUFFICIENT_BALANCE); diff --git a/testsuite/single_node_performance.py b/testsuite/single_node_performance.py index 027c260c938..82a361c5749 100755 --- a/testsuite/single_node_performance.py +++ b/testsuite/single_node_performance.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python # Copyright © Aptos Foundation # SPDX-License-Identifier: Apache-2.0 From 201d78e4dc01ab0e61b7f83b4c2b29d35a540403 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Wed, 1 Jul 2026 14:54:36 +0100 Subject: [PATCH 13/20] remove trailing whitespace --- .../framework/aptos-framework/doc/governed_gas_pool.md | 2 +- .../aptos-framework/sources/governed_gas_pool.move | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md index 0f0814c6cd7..0ab6078a98c 100644 --- a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md +++ b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md @@ -738,7 +738,7 @@ governed gas pool to authorize the withdrawal.
public(friend) fun withdraw_staking_reward<CoinType>(
     amount: u64
-): Coin<CoinType> acquires GovernedGasPool, GovernedGasPoolExtension  {
+): Coin<CoinType> acquires GovernedGasPool, GovernedGasPoolExtension {
     let balance = get_balance<CoinType>();
     assert!(balance >= amount, EINSUFFICIENT_BALANCE);
 
diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move
index cfe2b803190..b89ea3c8592 100644
--- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move
+++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move
@@ -271,7 +271,7 @@ module aptos_framework::governed_gas_pool {
             &mut ggpv2.withdraw_staking_reward_events,
             WithdrawStakingRewardEvent { amount },
         );
-        
+
         reward
     }
 
@@ -482,10 +482,10 @@ module aptos_framework::governed_gas_pool {
     ///
     /// @param aptos_framework is the signer of the aptos_framework module.
     fun test_deposite_treasury_and_counter(aptos_framework: &signer, treasury: &signer) acquires GovernedGasPool, GovernedGasPoolExtension, AptosCoinMintCapability {
-       
+
         // initialize the modules
         initialize_for_test(aptos_framework);
-    
+
         // create the depositor account and fund it
         aptos_account::create_account(signer::address_of(treasury));
         mint_for_test(signer::address_of(treasury), 1000);

From 55af7b0a4428c3aa92705a676828360a73891dc6 Mon Sep 17 00:00:00 2001
From: Sean Young 
Date: Thu, 2 Jul 2026 11:06:28 +0100
Subject: [PATCH 14/20] Add Andy's fixes to the governed gas pool spec

---
 .../sources/governed_gas_pool.spec.move       | 26 +++++++++++++++----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move
index 6bb1346d8bc..fdc166acf39 100644
--- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move
+++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move
@@ -33,6 +33,10 @@ spec aptos_framework::governed_gas_pool {
         invariant exists(@aptos_framework);
     }
 
+    spec init_module(aptos_framework: &signer) {
+       requires system_addresses::is_aptos_framework_address(signer::address_of(aptos_framework));
+    }
+
     spec initialize(aptos_framework: &signer, delegation_pool_creation_seed: vector) {
         requires system_addresses::is_aptos_framework_address(signer::address_of(aptos_framework));
         /// [high-level-req-1]
@@ -45,15 +49,12 @@ spec aptos_framework::governed_gas_pool {
         /// [high-level-req-4]
         // Abort if the caller is not the Aptos framework
         aborts_if !system_addresses::is_aptos_framework_address(signer::address_of(aptos_framework));
-
-        /// Abort if the governed gas pool has insufficient funds
-        aborts_with coin::EINSUFFICIENT_BALANCE, error::invalid_argument(EINSUFFICIENT_BALANCE), 0x1, 0x5, 0x7;
     }
 
     spec deposit(coin: Coin) {
         pragma aborts_if_is_partial = true;
 
-        let pool = signer::address_of(governed_gas_signer());
+        let pool = global(@aptos_framework).signer_capability.account;
 
         /// [high-level-req-3]
         /// The pool always has a registered CoinStore (register_coin at init),
@@ -64,10 +65,23 @@ spec aptos_framework::governed_gas_pool {
             == old(global>(pool).coin.value) + coin.value;
     }
 
+    spec deposit_from(account: address, amount: u64) {
+        pragma aborts_if_is_partial = true;
+        let pool = global(@aptos_framework).signer_capability.account;
+        requires exists>(pool);
+    }
+
+    spec deposit_treasury(treasury_account: &signer, amount: u64) {
+        pragma aborts_if_is_partial = true;
+        let pool = global(@aptos_framework).signer_capability.account;
+        requires exists>(pool);
+        requires exists(@aptos_framework);
+    }
+
     spec deposit_gas_fee_v2(gas_payer: address, gas_fee: u64) {
         pragma aborts_if_is_partial = true;
 
-        let pool = signer::address_of(governed_gas_signer());
+        let pool = global(@aptos_framework).signer_capability.account;
 
         /// [high-level-req-3]
         /// Characterizes the legacy coin path. The FA-store path
@@ -76,6 +90,8 @@ spec aptos_framework::governed_gas_pool {
         requires gas_payer != pool;
         requires exists>(pool);
         requires exists>(gas_payer);
+        requires !features::spec_is_enabled(features::OPERATIONS_DEFAULT_TO_FA_APT_STORE);
+        requires global>(gas_payer).coin.value >= gas_fee;
 
         /// The gas fee moves from the payer's store into the pool's store.
         ensures global>(pool).coin.value

From f9c6d62a9c1cc1d42f14cf1ae7d45ca8e9d63356 Mon Sep 17 00:00:00 2001
From: Sean Young 
Date: Thu, 2 Jul 2026 13:15:48 +0100
Subject: [PATCH 15/20] Update goldfiles

---
 ..._tests__create_account__create_account.exp |  2 +-
 ...__scripts__script_bad_sig_function_dep.exp |  2 +-
 ...sts__scripts__script_code_unverifiable.exp |  2 +-
 ...ed_type_argument_module_does_not_exist.exp |  2 +-
 ...ipts__script_non_existing_function_dep.exp |  2 +-
 ...ripts__script_none_existing_module_dep.exp |  2 +-
 ...pt_type_argument_module_does_not_exist.exp |  2 +-
 ...y_txn__test_arbitrary_script_execution.exp |  2 +-
 ...t_script_dependency_fails_verification.exp |  2 +-
 ...ansitive_dependency_fails_verification.exp |  2 +-
 ...type_tag_dependency_fails_verification.exp |  2 +-
 ...ansitive_dependency_fails_verification.exp |  2 +-
 .../aptos-framework/doc/governed_gas_pool.md  | 69 ++++++++++++++++---
 13 files changed, 72 insertions(+), 21 deletions(-)

diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__create_account__create_account.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__create_account__create_account.exp
index 21b46476666..cb4e3c6c33a 100644
--- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__create_account__create_account.exp
+++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__create_account__create_account.exp
@@ -7,7 +7,7 @@ Ok(
                         WriteSetMut {
                             write_set: {
                                 StateKey::AccessPath { address: 0xa550c18, path: "Resource(0x1::account::Account)" }: Modification(201304972f9242cbc3528a1e286323471ab891baa37e0053b85651693a79854a000100000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a550c1800000000000000000100000000000000000000000000000000000000000000000000000000000000000000000a550c180000, metadata:StateValueMetadata { inner: None }),
-                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(020000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a02d000000000000000, metadata:StateValueMetadata { inner: None }),
+                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(030000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f617373657419436f6e63757272656e7446756e6769626c6542616c616e6365001002d0000000000000ffffffffffffffff, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0x3f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b861891067, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Creation(020000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f726500590100000000000400f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000004003f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b86189106700000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a010000000000000000, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 40000, bytes_deposit: 13240, creation_time_usecs: 0 }) }),
                                 StateKey::AccessPath { address: 0xb26af11b4f332a7794398554b6313a38c6a102c74c5ba9a12629ae3a492acb2f, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(020000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f726500590100000000000400000000000000000000000000000000000000000000000000000000000a550c180000000000000000000000000000000400b26af11b4f332a7794398554b6313a38c6a102c74c5ba9a12629ae3a492acb2f00000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000afc2fffffffffffff00, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }),
                             },
diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_bad_sig_function_dep.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_bad_sig_function_dep.exp
index eb0d3431cca..f38fa51d81b 100644
--- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_bad_sig_function_dep.exp
+++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_bad_sig_function_dep.exp
@@ -6,7 +6,7 @@ Ok(
                     WriteSetV0(
                         WriteSetMut {
                             write_set: {
-                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(020000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a030000000000000000, metadata:StateValueMetadata { inner: None }),
+                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(030000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f617373657419436f6e63757272656e7446756e6769626c6542616c616e636500100300000000000000ffffffffffffffff, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0x3f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b861891067, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(03000000000000000000000000000000000000000000000000000000000000000104636f696e0d4d6967726174696f6e466c61670001000000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f726500590000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000003f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b86189106700000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a3d420f000000000000, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }),
                             },
diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_code_unverifiable.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_code_unverifiable.exp
index a5275c368af..fbfef785eeb 100644
--- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_code_unverifiable.exp
+++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_code_unverifiable.exp
@@ -6,7 +6,7 @@ Ok(
                     WriteSetV0(
                         WriteSetMut {
                             write_set: {
-                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(020000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a030000000000000000, metadata:StateValueMetadata { inner: None }),
+                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(030000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f617373657419436f6e63757272656e7446756e6769626c6542616c616e636500100300000000000000ffffffffffffffff, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0x3f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b861891067, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(03000000000000000000000000000000000000000000000000000000000000000104636f696e0d4d6967726174696f6e466c61670001000000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f726500590000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000003f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b86189106700000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a3d420f000000000000, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }),
                             },
diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_nested_type_argument_module_does_not_exist.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_nested_type_argument_module_does_not_exist.exp
index 484cc4a6c70..f64dd595b27 100644
--- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_nested_type_argument_module_does_not_exist.exp
+++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_nested_type_argument_module_does_not_exist.exp
@@ -6,7 +6,7 @@ Ok(
                     WriteSetV0(
                         WriteSetMut {
                             write_set: {
-                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(020000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a030000000000000000, metadata:StateValueMetadata { inner: None }),
+                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(030000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f617373657419436f6e63757272656e7446756e6769626c6542616c616e636500100300000000000000ffffffffffffffff, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0x3f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b861891067, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(03000000000000000000000000000000000000000000000000000000000000000104636f696e0d4d6967726174696f6e466c61670001000000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f726500590000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000003f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b86189106700000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a3d420f000000000000, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }),
                             },
diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_non_existing_function_dep.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_non_existing_function_dep.exp
index 0a4bd621e1d..372d34eccf9 100644
--- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_non_existing_function_dep.exp
+++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_non_existing_function_dep.exp
@@ -6,7 +6,7 @@ Ok(
                     WriteSetV0(
                         WriteSetMut {
                             write_set: {
-                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(020000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a030000000000000000, metadata:StateValueMetadata { inner: None }),
+                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(030000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f617373657419436f6e63757272656e7446756e6769626c6542616c616e636500100300000000000000ffffffffffffffff, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0x3f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b861891067, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(03000000000000000000000000000000000000000000000000000000000000000104636f696e0d4d6967726174696f6e466c61670001000000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f726500590000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000003f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b86189106700000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a3d420f000000000000, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }),
                             },
diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_none_existing_module_dep.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_none_existing_module_dep.exp
index 484cc4a6c70..f64dd595b27 100644
--- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_none_existing_module_dep.exp
+++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_none_existing_module_dep.exp
@@ -6,7 +6,7 @@ Ok(
                     WriteSetV0(
                         WriteSetMut {
                             write_set: {
-                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(020000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a030000000000000000, metadata:StateValueMetadata { inner: None }),
+                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(030000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f617373657419436f6e63757272656e7446756e6769626c6542616c616e636500100300000000000000ffffffffffffffff, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0x3f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b861891067, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(03000000000000000000000000000000000000000000000000000000000000000104636f696e0d4d6967726174696f6e466c61670001000000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f726500590000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000003f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b86189106700000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a3d420f000000000000, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }),
                             },
diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_type_argument_module_does_not_exist.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_type_argument_module_does_not_exist.exp
index 484cc4a6c70..f64dd595b27 100644
--- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_type_argument_module_does_not_exist.exp
+++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__scripts__script_type_argument_module_does_not_exist.exp
@@ -6,7 +6,7 @@ Ok(
                     WriteSetV0(
                         WriteSetMut {
                             write_set: {
-                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(020000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a030000000000000000, metadata:StateValueMetadata { inner: None }),
+                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(030000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f617373657419436f6e63757272656e7446756e6769626c6542616c616e636500100300000000000000ffffffffffffffff, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0x3f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b861891067, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(03000000000000000000000000000000000000000000000000000000000000000104636f696e0d4d6967726174696f6e466c61670001000000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f726500590000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000003f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b86189106700000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a3d420f000000000000, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }),
                             },
diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_arbitrary_script_execution.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_arbitrary_script_execution.exp
index f7da5d0f6b8..73b09f2526a 100644
--- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_arbitrary_script_execution.exp
+++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_arbitrary_script_execution.exp
@@ -6,7 +6,7 @@ Ok(
                     WriteSetV0(
                         WriteSetMut {
                             write_set: {
-                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(020000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a030000000000000000, metadata:StateValueMetadata { inner: None }),
+                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(030000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f617373657419436f6e63757272656e7446756e6769626c6542616c616e636500100300000000000000ffffffffffffffff, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0x3f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b861891067, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(03000000000000000000000000000000000000000000000000000000000000000104636f696e0d4d6967726174696f6e466c61670001000000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f726500590000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000003f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b86189106700000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a3d420f000000000000, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }),
                             },
diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_dependency_fails_verification.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_dependency_fails_verification.exp
index 587ac42b71f..3ba79fac56b 100644
--- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_dependency_fails_verification.exp
+++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_dependency_fails_verification.exp
@@ -6,7 +6,7 @@ Ok(
                     WriteSetV0(
                         WriteSetMut {
                             write_set: {
-                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(020000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a030000000000000000, metadata:StateValueMetadata { inner: None }),
+                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(030000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f617373657419436f6e63757272656e7446756e6769626c6542616c616e636500100300000000000000ffffffffffffffff, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0x3f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b861891067, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(03000000000000000000000000000000000000000000000000000000000000000104636f696e0d4d6967726174696f6e466c61670001000000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f726500590000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000003f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b86189106700000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a3d420f000000000000, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }),
                             },
diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_transitive_dependency_fails_verification.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_transitive_dependency_fails_verification.exp
index 587ac42b71f..3ba79fac56b 100644
--- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_transitive_dependency_fails_verification.exp
+++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_script_transitive_dependency_fails_verification.exp
@@ -6,7 +6,7 @@ Ok(
                     WriteSetV0(
                         WriteSetMut {
                             write_set: {
-                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(020000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a030000000000000000, metadata:StateValueMetadata { inner: None }),
+                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(030000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f617373657419436f6e63757272656e7446756e6769626c6542616c616e636500100300000000000000ffffffffffffffff, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0x3f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b861891067, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(03000000000000000000000000000000000000000000000000000000000000000104636f696e0d4d6967726174696f6e466c61670001000000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f726500590000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000003f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b86189106700000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a3d420f000000000000, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }),
                             },
diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_dependency_fails_verification.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_dependency_fails_verification.exp
index 587ac42b71f..3ba79fac56b 100644
--- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_dependency_fails_verification.exp
+++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_dependency_fails_verification.exp
@@ -6,7 +6,7 @@ Ok(
                     WriteSetV0(
                         WriteSetMut {
                             write_set: {
-                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(020000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a030000000000000000, metadata:StateValueMetadata { inner: None }),
+                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(030000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f617373657419436f6e63757272656e7446756e6769626c6542616c616e636500100300000000000000ffffffffffffffff, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0x3f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b861891067, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(03000000000000000000000000000000000000000000000000000000000000000104636f696e0d4d6967726174696f6e466c61670001000000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f726500590000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000003f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b86189106700000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a3d420f000000000000, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }),
                             },
diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_transitive_dependency_fails_verification.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_transitive_dependency_fails_verification.exp
index 587ac42b71f..3ba79fac56b 100644
--- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_transitive_dependency_fails_verification.exp
+++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_type_tag_transitive_dependency_fails_verification.exp
@@ -6,7 +6,7 @@ Ok(
                     WriteSetV0(
                         WriteSetMut {
                             write_set: {
-                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(020000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a030000000000000000, metadata:StateValueMetadata { inner: None }),
+                                StateKey::AccessPath { address: 0x975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee94809, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(030000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f7265005901000000000004009bb809cb154a393546da38ff08bc927679e77ecdb59dab49029315b54644e40e00000000000000000000000000000004000975b461453e8c36ba66937eaf7f874f7d6a9b26d65e89389304bd1bfee9480900000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f617373657419436f6e63757272656e7446756e6769626c6542616c616e636500100300000000000000ffffffffffffffff, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0x3f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b861891067, path: "ResourceGroup(0x1::object::ObjectGroup)" }: Modification(03000000000000000000000000000000000000000000000000000000000000000104636f696e0d4d6967726174696f6e466c61670001000000000000000000000000000000000000000000000000000000000000000001066f626a6563740a4f626a656374436f726500590000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000003f4fc7462763e539d6c50356f9c1d14ffc32b567d038da6bdfa454b86189106700000000000000000000000000000000000000000000000000000000000000010e66756e6769626c655f61737365740d46756e6769626c6553746f72650029000000000000000000000000000000000000000000000000000000000000000a3d420f000000000000, metadata:StateValueMetadata { inner: None }),
                                 StateKey::AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }),
                             },
diff --git a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md
index 0ab6078a98c..728b9682994 100644
--- a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md
+++ b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md
@@ -30,9 +30,12 @@
 -  [Function `register_coin`](#0x1_governed_gas_pool_register_coin)
 -  [Specification](#@Specification_1)
     -  [Function `initialize`](#@Specification_1_initialize)
+    -  [Function `init_module`](#@Specification_1_init_module)
     -  [Function `fund`](#@Specification_1_fund)
     -  [Function `deposit`](#@Specification_1_deposit)
+    -  [Function `deposit_from`](#@Specification_1_deposit_from)
     -  [Function `deposit_gas_fee_v2`](#@Specification_1_deposit_gas_fee_v2)
+    -  [Function `deposit_treasury`](#@Specification_1_deposit_treasury)
 
 
 
use 0x1::account;
@@ -818,6 +821,22 @@ Register Aptos coin with Governed gas signer.
 
 
 
+
+
+### Function `init_module`
+
+
+
fun init_module(aptos_framework: &signer)
+
+ + + + +
requires system_addresses::is_aptos_framework_address(signer::address_of(aptos_framework));
+
+ + + ### Function `fund` @@ -835,13 +854,6 @@ Register Aptos coin with Governed gas signer.
-Abort if the governed gas pool has insufficient funds - - -
aborts_with coin::EINSUFFICIENT_BALANCE, error::invalid_argument(EINSUFFICIENT_BALANCE), 0x1, 0x5, 0x7;
-
- - @@ -855,7 +867,7 @@ Abort if the governed gas pool has insufficient funds
pragma aborts_if_is_partial = true;
-let pool = signer::address_of(governed_gas_signer());
+let pool = global<GovernedGasPool>(@aptos_framework).signer_capability.account;
 // This enforces high-level requirement 3:
 requires exists<coin::CoinStore<CoinType>>(pool);
 ensures global<coin::CoinStore<CoinType>>(pool).coin.value
@@ -864,6 +876,24 @@ Abort if the governed gas pool has insufficient funds
 
 
 
+
+
+### Function `deposit_from`
+
+
+
fun deposit_from<CoinType>(account: address, amount: u64)
+
+ + + + +
pragma aborts_if_is_partial = true;
+let pool = global<GovernedGasPool>(@aptos_framework).signer_capability.account;
+requires exists<coin::CoinStore<CoinType>>(pool);
+
+ + + ### Function `deposit_gas_fee_v2` @@ -876,11 +906,13 @@ Abort if the governed gas pool has insufficient funds
pragma aborts_if_is_partial = true;
-let pool = signer::address_of(governed_gas_signer());
+let pool = global<GovernedGasPool>(@aptos_framework).signer_capability.account;
 // This enforces high-level requirement 3:
 requires gas_payer != pool;
 requires exists<coin::CoinStore<AptosCoin>>(pool);
 requires exists<coin::CoinStore<AptosCoin>>(gas_payer);
+requires !features::spec_is_enabled(features::OPERATIONS_DEFAULT_TO_FA_APT_STORE);
+requires global<coin::CoinStore<AptosCoin>>(gas_payer).coin.value >= gas_fee;
 
@@ -894,4 +926,23 @@ The gas fee moves from the payer's store into the pool's store.
+ + + +### Function `deposit_treasury` + + +
public entry fun deposit_treasury(treasury_account: &signer, amount: u64)
+
+ + + + +
pragma aborts_if_is_partial = true;
+let pool = global<GovernedGasPool>(@aptos_framework).signer_capability.account;
+requires exists<coin::CoinStore<AptosCoin>>(pool);
+requires exists<GovernedGasPoolExtension>(@aptos_framework);
+
+ + [move-book]: https://aptos.dev/move/book/SUMMARY From d3316ced29742c2fb8f19f879e497d8b7d4bfeb2 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Thu, 2 Jul 2026 15:13:26 +0100 Subject: [PATCH 16/20] Fix test_compare_vm_and_vm_uncoordinated test --- execution/executor-benchmark/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/execution/executor-benchmark/src/lib.rs b/execution/executor-benchmark/src/lib.rs index 01476eb7ae7..859a304abf9 100644 --- a/execution/executor-benchmark/src/lib.rs +++ b/execution/executor-benchmark/src/lib.rs @@ -712,7 +712,7 @@ mod tests { fa_features.enable(FeatureFlag::NEW_ACCOUNTS_DEFAULT_TO_FA_APT_STORE); fa_features.enable(FeatureFlag::OPERATIONS_DEFAULT_TO_FA_APT_STORE); fa_features.enable(FeatureFlag::NEW_ACCOUNTS_DEFAULT_TO_FA_STORE); - fa_features.disable(FeatureFlag::CONCURRENT_FUNGIBLE_BALANCE); + //fa_features.disable(FeatureFlag::CONCURRENT_FUNGIBLE_BALANCE); test_compare_prod_and_another::(values_match, fa_features.clone(), |address| { aptos_stdlib::aptos_account_fungible_transfer_only(address, 1000) From 884ef61118120e4bcd1e8a51e814fb757fc10be2 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Mon, 6 Jul 2026 14:12:43 +0100 Subject: [PATCH 17/20] Always refund storage fees refunds --- .../aptos-framework/sources/transaction_validation.move | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/aptos-move/framework/aptos-framework/sources/transaction_validation.move b/aptos-move/framework/aptos-framework/sources/transaction_validation.move index 82fdc56f617..df6c77ed342 100644 --- a/aptos-move/framework/aptos-framework/sources/transaction_validation.move +++ b/aptos-move/framework/aptos-framework/sources/transaction_validation.move @@ -868,10 +868,9 @@ module aptos_framework::transaction_validation { ); } else { let mint_amount = storage_fee_refunded - transaction_fee_amount; - // TODO: we cannot mint to do storage refund. We need to have a storage refund pool - if (!features::governed_gas_pool_enabled()){ - transaction_fee::mint_and_refund(gas_payer_address, mint_amount); - }; + // TODO: Should storage refunds go to the governed gas pool or a separate storage refund pool? + transaction_fee::mint_and_refund(gas_payer_address, mint_amount); + permissioned_signer::increase_limit( &gas_payer, (mint_amount as u256), From 12ba490d4650bc7620bb5be8996a048b2a208b20 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Mon, 6 Jul 2026 18:15:07 +0100 Subject: [PATCH 18/20] Don't refund 0 --- .../framework/aptos-framework/doc/transaction_validation.md | 5 +++-- .../aptos-framework/sources/transaction_validation.move | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/aptos-move/framework/aptos-framework/doc/transaction_validation.md b/aptos-move/framework/aptos-framework/doc/transaction_validation.md index 0c19498ab37..0cfb2ef2499 100644 --- a/aptos-move/framework/aptos-framework/doc/transaction_validation.md +++ b/aptos-move/framework/aptos-framework/doc/transaction_validation.md @@ -1673,10 +1673,11 @@ If there is no fee_payer, fee_payer = sender ); } else { let mint_amount = storage_fee_refunded - transaction_fee_amount; - // TODO: we cannot mint to do storage refund. We need to have a storage refund pool - if (!features::governed_gas_pool_enabled()){ + // TODO: Should storage refunds go to the governed gas pool or a separate storage refund pool? + if (mint_amount > 0) { transaction_fee::mint_and_refund(gas_payer_address, mint_amount); }; + permissioned_signer::increase_limit( &gas_payer, (mint_amount as u256), diff --git a/aptos-move/framework/aptos-framework/sources/transaction_validation.move b/aptos-move/framework/aptos-framework/sources/transaction_validation.move index df6c77ed342..200eb1d85f7 100644 --- a/aptos-move/framework/aptos-framework/sources/transaction_validation.move +++ b/aptos-move/framework/aptos-framework/sources/transaction_validation.move @@ -869,7 +869,9 @@ module aptos_framework::transaction_validation { } else { let mint_amount = storage_fee_refunded - transaction_fee_amount; // TODO: Should storage refunds go to the governed gas pool or a separate storage refund pool? - transaction_fee::mint_and_refund(gas_payer_address, mint_amount); + if (mint_amount > 0) { + transaction_fee::mint_and_refund(gas_payer_address, mint_amount); + }; permissioned_signer::increase_limit( &gas_payer, From a0c5b9f65bd4d18ef8f9e4ed0c02184cc165f71c Mon Sep 17 00:00:00 2001 From: Sean Young Date: Tue, 7 Jul 2026 15:59:55 +0100 Subject: [PATCH 19/20] Enable concurrency only when the CONCURRENT_FUNGIBLE_BALANCE is enabled --- .../aptos-framework/doc/governed_gas_pool.md | 69 +++---------------- .../sources/governed_gas_pool.move | 14 +++- .../sources/governed_gas_pool.spec.move | 2 + .../sources/reconfiguration.move | 2 + execution/executor-benchmark/src/lib.rs | 2 +- 5 files changed, 25 insertions(+), 64 deletions(-) diff --git a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md index 728b9682994..0ab6078a98c 100644 --- a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md +++ b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md @@ -30,12 +30,9 @@ - [Function `register_coin`](#0x1_governed_gas_pool_register_coin) - [Specification](#@Specification_1) - [Function `initialize`](#@Specification_1_initialize) - - [Function `init_module`](#@Specification_1_init_module) - [Function `fund`](#@Specification_1_fund) - [Function `deposit`](#@Specification_1_deposit) - - [Function `deposit_from`](#@Specification_1_deposit_from) - [Function `deposit_gas_fee_v2`](#@Specification_1_deposit_gas_fee_v2) - - [Function `deposit_treasury`](#@Specification_1_deposit_treasury)
use 0x1::account;
@@ -821,22 +818,6 @@ Register Aptos coin with Governed gas signer.
 
 
 
-
-
-### Function `init_module`
-
-
-
fun init_module(aptos_framework: &signer)
-
- - - - -
requires system_addresses::is_aptos_framework_address(signer::address_of(aptos_framework));
-
- - - ### Function `fund` @@ -854,6 +835,13 @@ Register Aptos coin with Governed gas signer.
+Abort if the governed gas pool has insufficient funds + + +
aborts_with coin::EINSUFFICIENT_BALANCE, error::invalid_argument(EINSUFFICIENT_BALANCE), 0x1, 0x5, 0x7;
+
+ + @@ -867,7 +855,7 @@ Register Aptos coin with Governed gas signer.
pragma aborts_if_is_partial = true;
-let pool = global<GovernedGasPool>(@aptos_framework).signer_capability.account;
+let pool = signer::address_of(governed_gas_signer());
 // This enforces high-level requirement 3:
 requires exists<coin::CoinStore<CoinType>>(pool);
 ensures global<coin::CoinStore<CoinType>>(pool).coin.value
@@ -876,24 +864,6 @@ Register Aptos coin with Governed gas signer.
 
 
 
-
-
-### Function `deposit_from`
-
-
-
fun deposit_from<CoinType>(account: address, amount: u64)
-
- - - - -
pragma aborts_if_is_partial = true;
-let pool = global<GovernedGasPool>(@aptos_framework).signer_capability.account;
-requires exists<coin::CoinStore<CoinType>>(pool);
-
- - - ### Function `deposit_gas_fee_v2` @@ -906,13 +876,11 @@ Register Aptos coin with Governed gas signer.
pragma aborts_if_is_partial = true;
-let pool = global<GovernedGasPool>(@aptos_framework).signer_capability.account;
+let pool = signer::address_of(governed_gas_signer());
 // This enforces high-level requirement 3:
 requires gas_payer != pool;
 requires exists<coin::CoinStore<AptosCoin>>(pool);
 requires exists<coin::CoinStore<AptosCoin>>(gas_payer);
-requires !features::spec_is_enabled(features::OPERATIONS_DEFAULT_TO_FA_APT_STORE);
-requires global<coin::CoinStore<AptosCoin>>(gas_payer).coin.value >= gas_fee;
 
@@ -926,23 +894,4 @@ The gas fee moves from the payer's store into the pool's store.
- - - -### Function `deposit_treasury` - - -
public entry fun deposit_treasury(treasury_account: &signer, amount: u64)
-
- - - - -
pragma aborts_if_is_partial = true;
-let pool = global<GovernedGasPool>(@aptos_framework).signer_capability.account;
-requires exists<coin::CoinStore<AptosCoin>>(pool);
-requires exists<GovernedGasPoolExtension>(@aptos_framework);
-
- - [move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move index b89ea3c8592..8ebed3395b2 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move @@ -23,6 +23,7 @@ module aptos_framework::governed_gas_pool { friend aptos_framework::stake; friend aptos_framework::transaction_fee; + friend aptos_framework::reconfiguration; /// Insufficient balance in the pool. const EINSUFFICIENT_BALANCE: u64 = 1; @@ -106,6 +107,11 @@ module aptos_framework::governed_gas_pool { } } + /// If the CONCURRENT_FUNGIBLE_BALANCE feature is enabled, upgrade the governed gas pool to a concurrent store + public(friend) fun on_reconfig() acquires GovernedGasPool { + upgrade_pool_store_to_concurrent(&governed_gas_signer()); + } + /// Initializes the governed gas pool extension alone. /// @param aptos_framework The signer of the aptos_framework module. public entry fun initialize_governed_gas_pool_extension( @@ -125,9 +131,11 @@ module aptos_framework::governed_gas_pool { /// Ensure the pool is using aggregator_v2 for concurrentcy. /// @param pool_signer The signer of the gas pool. fun upgrade_pool_store_to_concurrent(pool_signer: &signer) { - let store_addr = primary_fungible_store_address(signer::address_of(pool_signer)); - let store = object::address_to_object(store_addr); - fungible_asset::upgrade_store_to_concurrent(pool_signer, store); + if (features::concurrent_fungible_balance_enabled()) { + let store_addr = primary_fungible_store_address(signer::address_of(pool_signer)); + let store = object::address_to_object(store_addr); + fungible_asset::upgrade_store_to_concurrent(pool_signer, store); + }; } /// Initialize the governed gas pool as a module diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move index fdc166acf39..a15d4d45c9d 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.spec.move @@ -38,6 +38,8 @@ spec aptos_framework::governed_gas_pool { } spec initialize(aptos_framework: &signer, delegation_pool_creation_seed: vector) { + pragma aborts_if_is_partial = true; + requires system_addresses::is_aptos_framework_address(signer::address_of(aptos_framework)); /// [high-level-req-1] ensures exists(@aptos_framework); diff --git a/aptos-move/framework/aptos-framework/sources/reconfiguration.move b/aptos-move/framework/aptos-framework/sources/reconfiguration.move index b8a31abfb83..1c13da833d4 100644 --- a/aptos-move/framework/aptos-framework/sources/reconfiguration.move +++ b/aptos-move/framework/aptos-framework/sources/reconfiguration.move @@ -13,6 +13,7 @@ module aptos_framework::reconfiguration { use aptos_framework::chain_status; use aptos_framework::reconfiguration_state; use aptos_framework::storage_gas; + use aptos_framework::governed_gas_pool; friend aptos_framework::aptos_governance; friend aptos_framework::block; @@ -133,6 +134,7 @@ module aptos_framework::reconfiguration { // Call stake to compute the new validator set and distribute rewards and transaction fees. stake::on_new_epoch(); storage_gas::on_reconfig(); + governed_gas_pool::on_reconfig(); assert!(current_time > config_ref.last_reconfiguration_time, error::invalid_state(EINVALID_BLOCK_TIME)); config_ref.last_reconfiguration_time = current_time; diff --git a/execution/executor-benchmark/src/lib.rs b/execution/executor-benchmark/src/lib.rs index 859a304abf9..01476eb7ae7 100644 --- a/execution/executor-benchmark/src/lib.rs +++ b/execution/executor-benchmark/src/lib.rs @@ -712,7 +712,7 @@ mod tests { fa_features.enable(FeatureFlag::NEW_ACCOUNTS_DEFAULT_TO_FA_APT_STORE); fa_features.enable(FeatureFlag::OPERATIONS_DEFAULT_TO_FA_APT_STORE); fa_features.enable(FeatureFlag::NEW_ACCOUNTS_DEFAULT_TO_FA_STORE); - //fa_features.disable(FeatureFlag::CONCURRENT_FUNGIBLE_BALANCE); + fa_features.disable(FeatureFlag::CONCURRENT_FUNGIBLE_BALANCE); test_compare_prod_and_another::(values_match, fa_features.clone(), |address| { aptos_stdlib::aptos_account_fungible_transfer_only(address, 1000) From 334cd48d935562b7570d7983637a983550df4b77 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Wed, 8 Jul 2026 13:03:30 +0100 Subject: [PATCH 20/20] Fixes after review --- .../aptos-framework/doc/governed_gas_pool.md | 110 +++++++++++++++--- .../aptos-framework/doc/reconfiguration.md | 2 + .../sources/governed_gas_pool.move | 6 +- 3 files changed, 100 insertions(+), 18 deletions(-) diff --git a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md index 0ab6078a98c..09856c81797 100644 --- a/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md +++ b/aptos-move/framework/aptos-framework/doc/governed_gas_pool.md @@ -12,6 +12,7 @@ - [Function `primary_fungible_store_address`](#0x1_governed_gas_pool_primary_fungible_store_address) - [Function `create_resource_account_seed`](#0x1_governed_gas_pool_create_resource_account_seed) - [Function `initialize`](#0x1_governed_gas_pool_initialize) +- [Function `on_reconfig`](#0x1_governed_gas_pool_on_reconfig) - [Function `initialize_governed_gas_pool_extension`](#0x1_governed_gas_pool_initialize_governed_gas_pool_extension) - [Function `upgrade_pool_store_to_concurrent`](#0x1_governed_gas_pool_upgrade_pool_store_to_concurrent) - [Function `init_module`](#0x1_governed_gas_pool_init_module) @@ -30,9 +31,12 @@ - [Function `register_coin`](#0x1_governed_gas_pool_register_coin) - [Specification](#@Specification_1) - [Function `initialize`](#@Specification_1_initialize) + - [Function `init_module`](#@Specification_1_init_module) - [Function `fund`](#@Specification_1_fund) - [Function `deposit`](#@Specification_1_deposit) + - [Function `deposit_from`](#@Specification_1_deposit_from) - [Function `deposit_gas_fee_v2`](#@Specification_1_deposit_gas_fee_v2) + - [Function `deposit_treasury`](#@Specification_1_deposit_treasury)
use 0x1::account;
@@ -291,6 +295,33 @@ Initializes the governed gas pool around a resource account creation seed.
 
 
 
+
+
+
+
+## Function `on_reconfig`
+
+If the CONCURRENT_FUNGIBLE_BALANCE feature is enabled, upgrade the governed gas pool to a concurrent store
+
+
+
public(friend) fun on_reconfig()
+
+ + + +
+Implementation + + +
public(friend) fun on_reconfig() acquires GovernedGasPool {
+    if (exists<GovernedGasPool>(@aptos_framework)) {
+        upgrade_pool_store_to_concurrent(&governed_gas_signer());
+    }
+}
+
+ + +
@@ -347,9 +378,11 @@ Ensure the pool is using aggregator_v2 for concurrentcy.
fun upgrade_pool_store_to_concurrent(pool_signer: &signer) {
-    let store_addr = primary_fungible_store_address(signer::address_of(pool_signer));
-    let store = object::address_to_object<fungible_asset::FungibleStore>(store_addr);
-    fungible_asset::upgrade_store_to_concurrent(pool_signer, store);
+    if (features::concurrent_fungible_balance_enabled()) {
+        let store_addr = primary_fungible_store_address(signer::address_of(pool_signer));
+        let store = object::address_to_object<fungible_asset::FungibleStore>(store_addr);
+        fungible_asset::upgrade_store_to_concurrent(pool_signer, store);
+    };
 }
 
@@ -742,8 +775,6 @@ governed gas pool to authorize the withdrawal. let balance = get_balance<CoinType>(); assert!(balance >= amount, EINSUFFICIENT_BALANCE); - // Perform the withdrawal first so that any insufficient-balance aborts happen - // before event emission or aggregator updates (reduces wasted work on abort/retry). let reward = coin::withdraw<CoinType>(&governed_gas_signer(), amount); // Use aggregators only if feature is enabled AND counters are initialized. @@ -811,13 +842,30 @@ Register Aptos coin with Governed gas signer. -
requires system_addresses::is_aptos_framework_address(signer::address_of(aptos_framework));
+
pragma aborts_if_is_partial = true;
+requires system_addresses::is_aptos_framework_address(signer::address_of(aptos_framework));
 // This enforces high-level requirement 1:
 ensures exists<GovernedGasPool>(@aptos_framework);
 
+ + +### Function `init_module` + + +
fun init_module(aptos_framework: &signer)
+
+ + + + +
requires system_addresses::is_aptos_framework_address(signer::address_of(aptos_framework));
+
+ + + ### Function `fund` @@ -835,13 +883,6 @@ Register Aptos coin with Governed gas signer.
-Abort if the governed gas pool has insufficient funds - - -
aborts_with coin::EINSUFFICIENT_BALANCE, error::invalid_argument(EINSUFFICIENT_BALANCE), 0x1, 0x5, 0x7;
-
- - @@ -855,7 +896,7 @@ Abort if the governed gas pool has insufficient funds
pragma aborts_if_is_partial = true;
-let pool = signer::address_of(governed_gas_signer());
+let pool = global<GovernedGasPool>(@aptos_framework).signer_capability.account;
 // This enforces high-level requirement 3:
 requires exists<coin::CoinStore<CoinType>>(pool);
 ensures global<coin::CoinStore<CoinType>>(pool).coin.value
@@ -864,6 +905,24 @@ Abort if the governed gas pool has insufficient funds
 
 
 
+
+
+### Function `deposit_from`
+
+
+
fun deposit_from<CoinType>(account: address, amount: u64)
+
+ + + + +
pragma aborts_if_is_partial = true;
+let pool = global<GovernedGasPool>(@aptos_framework).signer_capability.account;
+requires exists<coin::CoinStore<CoinType>>(pool);
+
+ + + ### Function `deposit_gas_fee_v2` @@ -876,11 +935,13 @@ Abort if the governed gas pool has insufficient funds
pragma aborts_if_is_partial = true;
-let pool = signer::address_of(governed_gas_signer());
+let pool = global<GovernedGasPool>(@aptos_framework).signer_capability.account;
 // This enforces high-level requirement 3:
 requires gas_payer != pool;
 requires exists<coin::CoinStore<AptosCoin>>(pool);
 requires exists<coin::CoinStore<AptosCoin>>(gas_payer);
+requires !features::spec_is_enabled(features::OPERATIONS_DEFAULT_TO_FA_APT_STORE);
+requires global<coin::CoinStore<AptosCoin>>(gas_payer).coin.value >= gas_fee;
 
@@ -894,4 +955,23 @@ The gas fee moves from the payer's store into the pool's store.
+ + + +### Function `deposit_treasury` + + +
public entry fun deposit_treasury(treasury_account: &signer, amount: u64)
+
+ + + + +
pragma aborts_if_is_partial = true;
+let pool = global<GovernedGasPool>(@aptos_framework).signer_capability.account;
+requires exists<coin::CoinStore<AptosCoin>>(pool);
+requires exists<GovernedGasPoolExtension>(@aptos_framework);
+
+ + [move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/aptos-framework/doc/reconfiguration.md b/aptos-move/framework/aptos-framework/doc/reconfiguration.md index d551ca96cb6..b77991203c1 100644 --- a/aptos-move/framework/aptos-framework/doc/reconfiguration.md +++ b/aptos-move/framework/aptos-framework/doc/reconfiguration.md @@ -39,6 +39,7 @@ to synchronize configuration changes for the validators. use 0x1::error; use 0x1::event; use 0x1::features; +use 0x1::governed_gas_pool; use 0x1::reconfiguration_state; use 0x1::signer; use 0x1::stake; @@ -399,6 +400,7 @@ Signal validators to start using new configuration. Must be called from friend c // Call stake to compute the new validator set and distribute rewards and transaction fees. stake::on_new_epoch(); storage_gas::on_reconfig(); + governed_gas_pool::on_reconfig(); assert!(current_time > config_ref.last_reconfiguration_time, error::invalid_state(EINVALID_BLOCK_TIME)); config_ref.last_reconfiguration_time = current_time; diff --git a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move index 8ebed3395b2..d943f791432 100644 --- a/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move +++ b/aptos-move/framework/aptos-framework/sources/governed_gas_pool.move @@ -109,7 +109,9 @@ module aptos_framework::governed_gas_pool { /// If the CONCURRENT_FUNGIBLE_BALANCE feature is enabled, upgrade the governed gas pool to a concurrent store public(friend) fun on_reconfig() acquires GovernedGasPool { - upgrade_pool_store_to_concurrent(&governed_gas_signer()); + if (exists(@aptos_framework)) { + upgrade_pool_store_to_concurrent(&governed_gas_signer()); + } } /// Initializes the governed gas pool extension alone. @@ -268,8 +270,6 @@ module aptos_framework::governed_gas_pool { let balance = get_balance(); assert!(balance >= amount, EINSUFFICIENT_BALANCE); - // Perform the withdrawal first so that any insufficient-balance aborts happen - // before event emission or aggregator updates (reduces wasted work on abort/retry). let reward = coin::withdraw(&governed_gas_signer(), amount); // Use aggregators only if feature is enabled AND counters are initialized.