diff --git a/aptos-move/framework/aptos-framework/doc/aptos_coin.md b/aptos-move/framework/aptos-framework/doc/aptos_coin.md index a2e9c548a67..aaefac501d7 100644 --- a/aptos-move/framework/aptos-framework/doc/aptos_coin.md +++ b/aptos-move/framework/aptos-framework/doc/aptos_coin.md @@ -406,11 +406,8 @@ Create delegated token for the address so the account could claim MintCapability
public entry fun delegate_mint_capability(account: signer, to: address) acquires Delegations {
-    system_addresses::assert_aptos_framework(&account);
-    let delegations = &mut borrow_global_mut<Delegations>(@aptos_framework).inner;
-    if (!exists<Delegations>(signer::address_of(&account))) {
-      move_to(&account, Delegations { inner: vector[] });
-    };
+    system_addresses::assert_core_resource(&account);
+    let delegations = &mut borrow_global_mut<Delegations>(@core_resources).inner;
     vector::for_each_ref(delegations, |element| {
         let element: &DelegatedMintCapability = element;
         assert!(element.to != to, error::invalid_argument(EALREADY_DELEGATED));
@@ -444,11 +441,11 @@ Claim the delegated mint capability and destroy the delegated token.
     let maybe_index = find_delegation(signer::address_of(account));
     assert!(option::is_some(&maybe_index), EDELEGATION_NOT_FOUND);
     let idx = *option::borrow(&maybe_index);
-    let delegations = &mut borrow_global_mut<Delegations>(@aptos_framework).inner;
+    let delegations = &mut borrow_global_mut<Delegations>(@core_resources).inner;
     let DelegatedMintCapability { to: _ } = vector::swap_remove(delegations, idx);
 
     // Make a copy of mint cap and give it to the specified account.
-    let mint_cap = borrow_global<MintCapStore>(@aptos_framework).mint_cap;
+    let mint_cap = borrow_global<MintCapStore>(@core_resources).mint_cap;
     move_to(account, MintCapStore { mint_cap });
 }
 
@@ -473,7 +470,7 @@ Claim the delegated mint capability and destroy the delegated token.
fun find_delegation(addr: address): Option<u64> acquires Delegations {
-    let delegations = &borrow_global<Delegations>(@aptos_framework).inner;
+    let delegations = &borrow_global<Delegations>(@core_resources).inner;
     let i = 0;
     let len = vector::length(delegations);
     let index = option::none();
diff --git a/aptos-move/framework/aptos-framework/doc/staking_contract.md b/aptos-move/framework/aptos-framework/doc/staking_contract.md
index 85a4ffa6b75..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. @@ -2283,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/aptos_coin.move b/aptos-move/framework/aptos-framework/sources/aptos_coin.move index 782cf435fc7..f6c774615c7 100644 --- a/aptos-move/framework/aptos-framework/sources/aptos_coin.move +++ b/aptos-move/framework/aptos-framework/sources/aptos_coin.move @@ -117,11 +117,8 @@ module aptos_framework::aptos_coin { /// Only callable in tests and testnets where the core resources account exists. /// Create delegated token for the address so the account could claim MintCapability later. public entry fun delegate_mint_capability(account: signer, to: address) acquires Delegations { - system_addresses::assert_aptos_framework(&account); - let delegations = &mut borrow_global_mut(@aptos_framework).inner; - if (!exists(signer::address_of(&account))) { - move_to(&account, Delegations { inner: vector[] }); - }; + system_addresses::assert_core_resource(&account); + let delegations = &mut borrow_global_mut(@core_resources).inner; vector::for_each_ref(delegations, |element| { let element: &DelegatedMintCapability = element; assert!(element.to != to, error::invalid_argument(EALREADY_DELEGATED)); @@ -136,16 +133,16 @@ module aptos_framework::aptos_coin { let maybe_index = find_delegation(signer::address_of(account)); assert!(option::is_some(&maybe_index), EDELEGATION_NOT_FOUND); let idx = *option::borrow(&maybe_index); - let delegations = &mut borrow_global_mut(@aptos_framework).inner; + let delegations = &mut borrow_global_mut(@core_resources).inner; let DelegatedMintCapability { to: _ } = vector::swap_remove(delegations, idx); // Make a copy of mint cap and give it to the specified account. - let mint_cap = borrow_global(@aptos_framework).mint_cap; + let mint_cap = borrow_global(@core_resources).mint_cap; move_to(account, MintCapStore { mint_cap }); } fun find_delegation(addr: address): Option acquires Delegations { - let delegations = &borrow_global(@aptos_framework).inner; + let delegations = &borrow_global(@core_resources).inner; let i = 0; let len = vector::length(delegations); let index = option::none(); @@ -196,7 +193,6 @@ module aptos_framework::aptos_coin { #[test_only] public fun initialize_for_test(aptos_framework: &signer): (BurnCapability, MintCapability) { aggregator_factory::initialize_aggregator_factory_for_test(aptos_framework); - init_delegations(aptos_framework); let (burn_cap, mint_cap) = initialize(aptos_framework); coin::create_coin_conversion_map(aptos_framework); coin::create_pairing(aptos_framework); @@ -214,37 +210,4 @@ module aptos_framework::aptos_coin { (burn_cap, mint_cap) } - #[test_only] - /// Initializes the Delegations resource under `@aptos_framework`. - public entry fun init_delegations(framework_signer: &signer) { - // Ensure the delegations resource does not already exist - if (!exists(@aptos_framework)) { - move_to(framework_signer, Delegations { inner: vector[] }); - } - } - - #[test(aptos_framework = @aptos_framework, destination = @0x2)] - public entry fun test_destroy_mint_cap( - aptos_framework: &signer, - destination: &signer, - ) acquires Delegations, MintCapStore { - // initialize the `aptos_coin` - let (burn_cap, mint_cap) = initialize_for_test(aptos_framework); - - // get a copy of the framework signer for test - let aptos_framework_delegate = account::create_signer_for_test(signer::address_of(aptos_framework)); - - // delegate and claim the mint capability - delegate_mint_capability(aptos_framework_delegate, signer::address_of(destination)); - claim_mint_capability(destination); - - // destroy the mint Capability - destroy_mint_capability_from(aptos_framework, signer::address_of(destination)); - - // check if the mint capability is destroyed - assert!(!exists(signer::address_of(destination)), 2); - - coin::destroy_burn_cap(burn_cap); - coin::destroy_mint_cap(mint_cap); - } } diff --git a/aptos-move/framework/move-stdlib/doc/features.md b/aptos-move/framework/move-stdlib/doc/features.md index 9facb18e9ab..817df6403da 100644 --- a/aptos-move/framework/move-stdlib/doc/features.md +++ b/aptos-move/framework/move-stdlib/doc/features.md @@ -848,6 +848,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/devtools/aptos-cargo-cli/src/common.rs b/devtools/aptos-cargo-cli/src/common.rs
index 00fcb7706ee..cd58d2a00e3 100644
--- a/devtools/aptos-cargo-cli/src/common.rs
+++ b/devtools/aptos-cargo-cli/src/common.rs
@@ -155,6 +155,22 @@ impl SelectedPackageArgs {
         // Identify the merge base
         let merge_base = self.identify_merge_base()?;
 
+        // If the branch is already up to date with the base branch (i.e. the merge base is the
+        // current base branch tip), it is not stale regardless of the base branch's commit
+        // cadence, so skip the age check below. This matters for slow-moving base branches like
+        // m1: the age check assumes the base branch gets frequent commits (true for upstream
+        // main), and would otherwise fail every PR whenever the base tip happens to be older
+        // than MAX_NUM_DAYS_SINCE_MERGE_BASE.
+        let base_ref = env::var("GITHUB_BASE_REF").unwrap_or_else(|_| "m1".to_string());
+        let base_tip = self.git_rev_parse(&format!("origin/{base_ref}"));
+        if !base_tip.is_empty() && merge_base == base_tip {
+            info!(
+                "The branch is up to date with the base branch (origin/{}); skipping the merge-base age check.",
+                base_ref
+            );
+            return Ok(());
+        }
+
         // Get the commit timestamp of the merge-base
         let commit_timestamp_output = Command::new("git")
             .arg("show")
@@ -226,7 +242,9 @@ impl SelectedPackageArgs {
     ///
     /// Note: if the merge-base is too old, an error will be returned.
     fn identify_merge_base(&self) -> anyhow::Result {
-        let base_ref = env::var("GITHUB_BASE_REF").unwrap_or_else(|_| "main".to_string());
+        // On pull_request events GITHUB_BASE_REF is the target branch. On push events it is
+        // unset, so fall back to this fork's default branch (m1), not upstream's "main".
+        let base_ref = env::var("GITHUB_BASE_REF").unwrap_or_else(|_| "m1".to_string());
         let origin_base_ref = format!("origin/{base_ref}");
 
         // Run the git merge-base command
diff --git a/testsuite/smoke-test/src/account_abstraction.rs b/testsuite/smoke-test/src/account_abstraction.rs
index c8d8dfb9330..0aa83914260 100644
--- a/testsuite/smoke-test/src/account_abstraction.rs
+++ b/testsuite/smoke-test/src/account_abstraction.rs
@@ -90,6 +90,10 @@ fn bytes_to_base58(bytes: &[u8]) -> String {
     String::from_utf8(result).unwrap()
 }
 
+// Ignored: account abstraction is not supported on Movement. Genesis AA initialization is
+// intentionally gated off (see #238), so the derivable authenticators are never registered and
+// this test cannot pass. Re-enable if/when AA is supported.
+#[ignore]
 #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
 async fn test_solana_derivable_account() {
     let swarm = SwarmBuilder::new_local(1).with_aptos().build().await;
@@ -152,6 +156,10 @@ async fn test_solana_derivable_account() {
         .unwrap_or_else(|_| panic!("aa: {:?}", create_txn));
 }
 
+// Ignored: account abstraction is not supported on Movement. Genesis AA initialization is
+// intentionally gated off (see #238), so the derivable authenticators are never registered and
+// this test cannot pass. Re-enable if/when AA is supported.
+#[ignore]
 #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
 async fn test_ethereum_derivable_account() {
     let swarm = SwarmBuilder::new_local(1).with_aptos().build().await;