diff --git a/aptos-move/framework/aptos-framework/doc/account.md b/aptos-move/framework/aptos-framework/doc/account.md index 383d4918dd700..447fb207802d1 100644 --- a/aptos-move/framework/aptos-framework/doc/account.md +++ b/aptos-move/framework/aptos-framework/doc/account.md @@ -19,7 +19,10 @@ - [Struct `SignerCapabilityOfferProofChallenge`](#0x1_account_SignerCapabilityOfferProofChallenge) - [Struct `RotationCapabilityOfferProofChallengeV2`](#0x1_account_RotationCapabilityOfferProofChallengeV2) - [Struct `SignerCapabilityOfferProofChallengeV2`](#0x1_account_SignerCapabilityOfferProofChallengeV2) +- [Struct `AccountPermission`](#0x1_account_AccountPermission) - [Constants](#@Constants_0) +- [Function `check_signer_permission`](#0x1_account_check_signer_permission) +- [Function `grant_permission`](#0x1_account_grant_permission) - [Function `initialize`](#0x1_account_initialize) - [Function `create_account_if_does_not_exist`](#0x1_account_create_account_if_does_not_exist) - [Function `create_account`](#0x1_account_create_account) @@ -110,6 +113,7 @@ use 0x1::hash; use 0x1::multi_ed25519; use 0x1::option; +use 0x1::permissioned_signer; use 0x1::signer; use 0x1::system_addresses; use 0x1::table; @@ -639,6 +643,33 @@ This V2 struct adds the chain_id + + + + +## Struct `AccountPermission` + + + +
struct AccountPermission has copy, drop, store
+
+ + + +
+Fields + + +
+
+dummy_field: bool +
+
+ +
+
+ +
@@ -798,6 +829,16 @@ The current authentication key and the new authentication key are the same + + +Current permissioned signer cannot perform the privilaged operations. + + +
const ENO_ACCOUNT_PERMISSION: u64 = 23;
+
+ + + The caller does not have a digital-signature-based capability to call this function @@ -926,6 +967,61 @@ Scheme identifier for MultiEd25519 signatures used to derive authentication keys + + +## Function `check_signer_permission` + +Permissions + + +
fun check_signer_permission(s: &signer)
+
+ + + +
+Implementation + + +
inline fun check_signer_permission(s: &signer) {
+    assert!(
+        permissioned_signer::check_permission_exists(s, AccountPermission {}),
+        error::permission_denied(ENO_ACCOUNT_PERMISSION),
+    );
+}
+
+ + + +
+ + + +## Function `grant_permission` + +Grant permission to perform key rotations on behalf of the master signer. + +This is **extermely dangerous** and should be granted only when it's absolutely needed. + + +
public fun grant_permission(master: &signer, permissioned_signer: &signer)
+
+ + + +
+Implementation + + +
public fun grant_permission(master: &signer, permissioned_signer: &signer) {
+    permissioned_signer::authorize_unlimited(master, permissioned_signer, AccountPermission {})
+}
+
+ + + +
+ ## Function `initialize` @@ -1256,6 +1352,7 @@ many contexts: vector::length(&new_auth_key) == 32, error::invalid_argument(EMALFORMED_AUTHENTICATION_KEY) ); + check_signer_permission(account); let account_resource = borrow_global_mut<Account>(addr); account_resource.authentication_key = new_auth_key; } @@ -1351,6 +1448,7 @@ to rotate his address to Alice's address in the first place. ) acquires Account, OriginatingAddress { let addr = signer::address_of(account); assert!(exists_at(addr), error::not_found(EACCOUNT_DOES_NOT_EXIST)); + check_signer_permission(account); let account_resource = borrow_global_mut<Account>(addr); // Verify the given `from_public_key_bytes` matches this account's current authentication key. @@ -1426,9 +1524,10 @@ to rotate his address to Alice's address in the first place. new_public_key_bytes: vector<u8>, cap_update_table: vector<u8> ) acquires Account, OriginatingAddress { + check_signer_permission(delegate_signer); assert!(exists_at(rotation_cap_offerer_address), error::not_found(EOFFERER_ADDRESS_DOES_NOT_EXIST)); - // Check that there exists a rotation capability offer at the offerer's account resource for the delegate. + // Check that there exists a rotation capability offer at the offerer's account resource for the delegate. let delegate_address = signer::address_of(delegate_signer); let offerer_account_resource = borrow_global<Account>(rotation_cap_offerer_address); assert!( @@ -1505,10 +1604,11 @@ offer, calling this function will replace the previous recipient_addressvector<u8>, recipient_address: address, ) acquires Account { + check_signer_permission(account); let addr = signer::address_of(account); assert!(exists_at(recipient_address), error::not_found(EACCOUNT_DOES_NOT_EXIST)); - // proof that this account intends to delegate its rotation capability to another account + // proof that this account intends to delegate its rotation capability to another account let account_resource = borrow_global_mut<Account>(addr); let proof_challenge = RotationCapabilityOfferProofChallengeV2 { chain_id: chain_id::get(), @@ -1548,7 +1648,7 @@ offer, calling this function will replace the previous recipient_addressabort error::invalid_argument(EINVALID_SCHEME) }; - // update the existing rotation capability offer or put in a new rotation capability offer for the current account + // update the existing rotation capability offer or put in a new rotation capability offer for the current account option::swap_or_fill(&mut account_resource.rotation_capability_offer.for, recipient_address); } @@ -1683,6 +1783,7 @@ Revoke the rotation capability offer given to to_be_revoked_recipient_addr
public entry fun revoke_rotation_capability(account: &signer, to_be_revoked_address: address) acquires Account {
     assert!(exists_at(to_be_revoked_address), error::not_found(EACCOUNT_DOES_NOT_EXIST));
+    check_signer_permission(account);
     let addr = signer::address_of(account);
     let account_resource = borrow_global<Account>(addr);
     assert!(
@@ -1714,6 +1815,7 @@ Revoke any rotation capability offer in the specified account.
 
 
 
public entry fun revoke_any_rotation_capability(account: &signer) acquires Account {
+    check_signer_permission(account);
     let account_resource = borrow_global_mut<Account>(signer::address_of(account));
     option::extract(&mut account_resource.rotation_capability_offer.for);
 }
@@ -1754,10 +1856,11 @@ to the account owner's signer capability).
     account_public_key_bytes: vector<u8>,
     recipient_address: address
 ) acquires Account {
+    check_signer_permission(account);
     let source_address = signer::address_of(account);
     assert!(exists_at(recipient_address), error::not_found(EACCOUNT_DOES_NOT_EXIST));
 
-    // Proof that this account intends to delegate its signer capability to another account.
+    // Proof that this account intends to delegate its signer capability to another account.
     let proof_challenge = SignerCapabilityOfferProofChallengeV2 {
         sequence_number: get_sequence_number(source_address),
         source_address,
@@ -1766,7 +1869,7 @@ to the account owner's signer capability).
     verify_signed_message(
         source_address, account_scheme, account_public_key_bytes, signer_capability_sig_bytes, proof_challenge);
 
-    // Update the existing signer capability offer or put in a new signer capability offer for the recipient.
+    // Update the existing signer capability offer or put in a new signer capability offer for the recipient.
     let account_resource = borrow_global_mut<Account>(source_address);
     option::swap_or_fill(&mut account_resource.signer_capability_offer.for, recipient_address);
 }
@@ -1853,6 +1956,7 @@ has a signer capability offer from accoun
 
 
public entry fun revoke_signer_capability(account: &signer, to_be_revoked_address: address) acquires Account {
     assert!(exists_at(to_be_revoked_address), error::not_found(EACCOUNT_DOES_NOT_EXIST));
+    check_signer_permission(account);
     let addr = signer::address_of(account);
     let account_resource = borrow_global<Account>(addr);
     assert!(
@@ -1884,6 +1988,7 @@ Revoke any signer capability offer in the specified account.
 
 
 
public entry fun revoke_any_signer_capability(account: &signer) acquires Account {
+    check_signer_permission(account);
     let account_resource = borrow_global_mut<Account>(signer::address_of(account));
     option::extract(&mut account_resource.signer_capability_offer.for);
 }
@@ -1911,9 +2016,10 @@ at the offerer's address.
 
 
 
public fun create_authorized_signer(account: &signer, offerer_address: address): signer acquires Account {
+    check_signer_permission(account);
     assert!(exists_at(offerer_address), error::not_found(EOFFERER_ADDRESS_DOES_NOT_EXIST));
 
-    // Check if there's an existing signer capability offer from the offerer.
+    // Check if there's an existing signer capability offer from the offerer.
     let account_resource = borrow_global<Account>(offerer_address);
     let addr = signer::address_of(account);
     assert!(
@@ -2289,7 +2395,7 @@ Coin management methods.
 Capability based functions for efficient use.
 
 
-
public fun create_signer_with_capability(capability: &account::SignerCapability): signer
+
public fun create_signer_with_capability(capability: &account::SignerCapability): signer
 
@@ -2298,8 +2404,8 @@ Capability based functions for efficient use. Implementation -
public fun create_signer_with_capability(capability: &SignerCapability): signer {
-    let addr = &capability.account;
+
public fun create_signer_with_capability(capability: &SignerCapability): signer {
+    let addr = &capability.account;
     create_signer(*addr)
 }
 
@@ -2314,7 +2420,7 @@ Capability based functions for efficient use. -
public fun get_signer_capability_address(capability: &account::SignerCapability): address
+
public fun get_signer_capability_address(capability: &account::SignerCapability): address
 
@@ -2323,8 +2429,8 @@ Capability based functions for efficient use. Implementation -
public fun get_signer_capability_address(capability: &SignerCapability): address {
-    capability.account
+
public fun get_signer_capability_address(capability: &SignerCapability): address {
+    capability.account
 }
 
@@ -2754,6 +2860,7 @@ The length of new_auth_key is 32. let post account_resource = global<Account>(addr); aborts_if !exists<Account>(addr); aborts_if vector::length(new_auth_key) != 32; +aborts_if permissioned_signer::spec_is_permissioned_signer(account); modifies global<Account>(addr); ensures account_resource.authentication_key == new_auth_key;
@@ -2776,6 +2883,7 @@ The length of new_auth_key is 32. let post account_resource = global<Account>(addr); aborts_if !exists<Account>(addr); aborts_if vector::length(new_auth_key) != 32; +aborts_if permissioned_signer::spec_is_permissioned_signer(account); modifies global<Account>(addr); ensures account_resource.authentication_key == new_auth_key;
@@ -2807,6 +2915,7 @@ The authentication scheme is ED25519_SCHEME and MULTI_ED25519_SCHEME
let addr = signer::address_of(account);
 let account_resource = global<Account>(addr);
 aborts_if !exists<Account>(addr);
+aborts_if permissioned_signer::spec_is_permissioned_signer(account);
 // This enforces high-level requirement 6:
 include from_scheme == ED25519_SCHEME ==> ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { bytes: from_public_key_bytes };
 aborts_if from_scheme == ED25519_SCHEME && ({
@@ -2871,7 +2980,8 @@ The authentication scheme is ED25519_SCHEME and MULTI_ED25519_SCHEME
 
 
 
-
aborts_if !exists<Account>(rotation_cap_offerer_address);
+
aborts_if permissioned_signer::spec_is_permissioned_signer(delegate_signer);
+aborts_if !exists<Account>(rotation_cap_offerer_address);
 let delegate_address = signer::address_of(delegate_signer);
 let offerer_account_resource = global<Account>(rotation_cap_offerer_address);
 aborts_if !from_bcs::deserializable<address>(offerer_account_resource.authentication_key);
@@ -2930,6 +3040,7 @@ The authentication scheme is ED25519_SCHEME and MULTI_ED25519_SCHEME
     source_address,
     recipient_address,
 };
+aborts_if permissioned_signer::spec_is_permissioned_signer(account);
 aborts_if !exists<chain_id::ChainId>(@aptos_framework);
 aborts_if !exists<Account>(recipient_address);
 aborts_if !exists<Account>(source_address);
@@ -3028,7 +3139,8 @@ The authentication scheme is ED25519_SCHEME and MULTI_ED25519_SCHEME
 
 
 
-
aborts_if !exists<Account>(to_be_revoked_address);
+
aborts_if permissioned_signer::spec_is_permissioned_signer(account);
+aborts_if !exists<Account>(to_be_revoked_address);
 let addr = signer::address_of(account);
 let account_resource = global<Account>(addr);
 aborts_if !exists<Account>(addr);
@@ -3052,7 +3164,8 @@ The authentication scheme is ED25519_SCHEME and MULTI_ED25519_SCHEME
 
 
 
-
let addr = signer::address_of(account);
+
aborts_if permissioned_signer::spec_is_permissioned_signer(account);
+let addr = signer::address_of(account);
 modifies global<Account>(addr);
 aborts_if !exists<Account>(addr);
 let account_resource = global<Account>(addr);
@@ -3084,6 +3197,7 @@ The authentication scheme is ED25519_SCHEME and MULTI_ED25519_SCHEME.
     source_address,
     recipient_address,
 };
+aborts_if permissioned_signer::spec_is_permissioned_signer(account);
 aborts_if !exists<Account>(recipient_address);
 aborts_if !exists<Account>(source_address);
 include account_scheme == ED25519_SCHEME ==> ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { bytes: account_public_key_bytes };
@@ -3167,7 +3281,8 @@ The Account existed under the signer.
 The value of signer_capability_offer.for of Account resource under the signer is to_be_revoked_address.
 
 
-
aborts_if !exists<Account>(to_be_revoked_address);
+
aborts_if permissioned_signer::spec_is_permissioned_signer(account);
+aborts_if !exists<Account>(to_be_revoked_address);
 let addr = signer::address_of(account);
 let account_resource = global<Account>(addr);
 aborts_if !exists<Account>(addr);
@@ -3190,6 +3305,7 @@ The value of signer_capability_offer.for of Account resource under the signer is
 
 
 
modifies global<Account>(signer::address_of(account));
+aborts_if permissioned_signer::spec_is_permissioned_signer(account);
 // This enforces high-level requirement 7:
 aborts_if !exists<Account>(signer::address_of(account));
 let account_resource = global<Account>(signer::address_of(account));
@@ -3211,7 +3327,8 @@ The Account existed under the signer.
 The value of signer_capability_offer.for of Account resource under the signer is offerer_address.
 
 
-
// This enforces high-level requirement 8:
+
aborts_if permissioned_signer::spec_is_permissioned_signer(account);
+// This enforces high-level requirement 8:
 include AccountContainsAddr{
     account,
     address: offerer_address,
@@ -3372,6 +3489,8 @@ The value of signer_capability_offer.for of Account resource under the signer is
 
 
let source_addr = signer::address_of(source);
 let resource_addr = spec_create_resource_address(source_addr, seed);
+let resource = create_signer::spec_create_signer(resource_addr);
+aborts_if permissioned_signer::spec_is_permissioned_signer(resource);
 aborts_if len(ZERO_AUTH_KEY) != 32;
 include exists_at(resource_addr) ==> CreateResourceAccountAbortsIf;
 include !exists_at(resource_addr) ==> CreateAccountAbortsIf {addr: resource_addr};
@@ -3506,13 +3625,13 @@ The guid_creation_num of the Account is up to MAX_U64.
 ### Function `create_signer_with_capability`
 
 
-
public fun create_signer_with_capability(capability: &account::SignerCapability): signer
+
public fun create_signer_with_capability(capability: &account::SignerCapability): signer
 
-
let addr = capability.account;
+
let addr = capability.account;
 ensures signer::address_of(result) == addr;
 
diff --git a/aptos-move/framework/aptos-framework/doc/fungible_asset.md b/aptos-move/framework/aptos-framework/doc/fungible_asset.md index dd994857a92af..9444aaf1af41b 100644 --- a/aptos-move/framework/aptos-framework/doc/fungible_asset.md +++ b/aptos-move/framework/aptos-framework/doc/fungible_asset.md @@ -112,6 +112,7 @@ metadata object can be any object that equipped with + +## Function `refill_permission_with_fa` + + + +
public(friend) fun refill_permission_with_fa(permissioned: &signer, fa: &fungible_asset::FungibleAsset)
+
+ + + +
+Implementation + + +
public(friend) fun refill_permission_with_fa(
+    permissioned: &signer,
+    fa: &FungibleAsset
+) {
+    permissioned_signer::increase_limit(
+        permissioned,
+        amount(fa) as u256,
+        WithdrawPermission {
+            metadata_address: object::object_address(&metadata_from_asset(fa)),
+        }
+    )
+}
+
+ + +
diff --git a/aptos-move/framework/aptos-framework/doc/primary_fungible_store.md b/aptos-move/framework/aptos-framework/doc/primary_fungible_store.md index 28b1374e4f850..ad5f5312aa431 100644 --- a/aptos-move/framework/aptos-framework/doc/primary_fungible_store.md +++ b/aptos-move/framework/aptos-framework/doc/primary_fungible_store.md @@ -33,6 +33,7 @@ fungible asset to it. This emits an deposit event. - [Function `is_frozen`](#0x1_primary_fungible_store_is_frozen) - [Function `withdraw`](#0x1_primary_fungible_store_withdraw) - [Function `deposit`](#0x1_primary_fungible_store_deposit) +- [Function `deposit_with_signer`](#0x1_primary_fungible_store_deposit_with_signer) - [Function `force_deposit`](#0x1_primary_fungible_store_force_deposit) - [Function `transfer`](#0x1_primary_fungible_store_transfer) - [Function `transfer_assert_minimum_deposit`](#0x1_primary_fungible_store_transfer_assert_minimum_deposit) @@ -507,6 +508,37 @@ Deposit fungible asset fa to the given account's primary store. + + + + +## Function `deposit_with_signer` + +Deposit fungible asset fa to the given account's primary store using signer. + +If owner is a permissioned signer, the signer will be granted with permission to withdraw +the same amount of fund in the future. + + +
public fun deposit_with_signer(owner: &signer, fa: fungible_asset::FungibleAsset)
+
+ + + +
+Implementation + + +
public fun deposit_with_signer(owner: &signer, fa: FungibleAsset) acquires DeriveRefPod {
+    fungible_asset::refill_permission_with_fa(owner, &fa);
+    let metadata = fungible_asset::asset_metadata(&fa);
+    let store = ensure_primary_store_exists(signer::address_of(owner), metadata);
+    dispatchable_fungible_asset::deposit(store, fa);
+}
+
+ + +
diff --git a/aptos-move/framework/aptos-framework/sources/account.move b/aptos-move/framework/aptos-framework/sources/account.move index 0487ed630c4e2..691f9bcc99e89 100644 --- a/aptos-move/framework/aptos-framework/sources/account.move +++ b/aptos-move/framework/aptos-framework/sources/account.move @@ -9,6 +9,7 @@ module aptos_framework::account { use aptos_framework::create_signer::create_signer; use aptos_framework::event::{Self, EventHandle}; use aptos_framework::guid; + use aptos_framework::permissioned_signer; use aptos_framework::system_addresses; use aptos_std::ed25519; use aptos_std::from_bcs; @@ -179,6 +180,8 @@ module aptos_framework::account { const ENEW_AUTH_KEY_ALREADY_MAPPED: u64 = 21; /// The current authentication key and the new authentication key are the same const ENEW_AUTH_KEY_SAME_AS_CURRENT: u64 = 22; + /// Current permissioned signer cannot perform the privilaged operations. + const ENO_ACCOUNT_PERMISSION: u64 = 23; /// Explicitly separate the GUID space between Object and Account to prevent accidental overlap. const MAX_GUID_CREATION_NUM: u64 = 0x4000000000000; @@ -187,6 +190,23 @@ module aptos_framework::account { /// Create signer for testing, independently of an Aptos-style `Account`. public fun create_signer_for_test(addr: address): signer { create_signer(addr) } + struct AccountPermission has copy, drop, store {} + + /// Permissions + inline fun check_signer_permission(s: &signer) { + assert!( + permissioned_signer::check_permission_exists(s, AccountPermission {}), + error::permission_denied(ENO_ACCOUNT_PERMISSION), + ); + } + + /// Grant permission to perform key rotations on behalf of the master signer. + /// + /// This is **extermely dangerous** and should be granted only when it's absolutely needed. + public fun grant_permission(master: &signer, permissioned_signer: &signer) { + permissioned_signer::authorize_unlimited(master, permissioned_signer, AccountPermission {}) + } + /// Only called during genesis to initialize system resources for this module. public(friend) fun initialize(aptos_framework: &signer) { system_addresses::assert_aptos_framework(aptos_framework); @@ -302,6 +322,7 @@ module aptos_framework::account { vector::length(&new_auth_key) == 32, error::invalid_argument(EMALFORMED_AUTHENTICATION_KEY) ); + check_signer_permission(account); let account_resource = borrow_global_mut(addr); account_resource.authentication_key = new_auth_key; } @@ -357,6 +378,7 @@ module aptos_framework::account { ) acquires Account, OriginatingAddress { let addr = signer::address_of(account); assert!(exists_at(addr), error::not_found(EACCOUNT_DOES_NOT_EXIST)); + check_signer_permission(account); let account_resource = borrow_global_mut(addr); // Verify the given `from_public_key_bytes` matches this account's current authentication key. @@ -412,6 +434,7 @@ module aptos_framework::account { new_public_key_bytes: vector, cap_update_table: vector ) acquires Account, OriginatingAddress { + check_signer_permission(delegate_signer); assert!(exists_at(rotation_cap_offerer_address), error::not_found(EOFFERER_ADDRESS_DOES_NOT_EXIST)); // Check that there exists a rotation capability offer at the offerer's account resource for the delegate. @@ -471,6 +494,7 @@ module aptos_framework::account { account_public_key_bytes: vector, recipient_address: address, ) acquires Account { + check_signer_permission(account); let addr = signer::address_of(account); assert!(exists_at(recipient_address), error::not_found(EACCOUNT_DOES_NOT_EXIST)); @@ -569,6 +593,7 @@ module aptos_framework::account { /// Revoke the rotation capability offer given to `to_be_revoked_recipient_address` from `account` public entry fun revoke_rotation_capability(account: &signer, to_be_revoked_address: address) acquires Account { assert!(exists_at(to_be_revoked_address), error::not_found(EACCOUNT_DOES_NOT_EXIST)); + check_signer_permission(account); let addr = signer::address_of(account); let account_resource = borrow_global(addr); assert!( @@ -580,6 +605,7 @@ module aptos_framework::account { /// Revoke any rotation capability offer in the specified account. public entry fun revoke_any_rotation_capability(account: &signer) acquires Account { + check_signer_permission(account); let account_resource = borrow_global_mut(signer::address_of(account)); option::extract(&mut account_resource.rotation_capability_offer.for); } @@ -600,6 +626,7 @@ module aptos_framework::account { account_public_key_bytes: vector, recipient_address: address ) acquires Account { + check_signer_permission(account); let source_address = signer::address_of(account); assert!(exists_at(recipient_address), error::not_found(EACCOUNT_DOES_NOT_EXIST)); @@ -639,6 +666,7 @@ module aptos_framework::account { /// has a signer capability offer from `account` but will be revoked in this function). public entry fun revoke_signer_capability(account: &signer, to_be_revoked_address: address) acquires Account { assert!(exists_at(to_be_revoked_address), error::not_found(EACCOUNT_DOES_NOT_EXIST)); + check_signer_permission(account); let addr = signer::address_of(account); let account_resource = borrow_global(addr); assert!( @@ -650,6 +678,7 @@ module aptos_framework::account { /// Revoke any signer capability offer in the specified account. public entry fun revoke_any_signer_capability(account: &signer) acquires Account { + check_signer_permission(account); let account_resource = borrow_global_mut(signer::address_of(account)); option::extract(&mut account_resource.signer_capability_offer.for); } @@ -657,6 +686,7 @@ module aptos_framework::account { /// Return an authorized signer of the offerer, if there's an existing signer capability offer for `account` /// at the offerer's address. public fun create_authorized_signer(account: &signer, offerer_address: address): signer acquires Account { + check_signer_permission(account); assert!(exists_at(offerer_address), error::not_found(EOFFERER_ADDRESS_DOES_NOT_EXIST)); // Check if there's an existing signer capability offer from the offerer. diff --git a/aptos-move/framework/aptos-framework/sources/account.spec.move b/aptos-move/framework/aptos-framework/sources/account.spec.move index 36e7a5740027e..987321f01ec77 100644 --- a/aptos-move/framework/aptos-framework/sources/account.spec.move +++ b/aptos-move/framework/aptos-framework/sources/account.spec.move @@ -199,6 +199,7 @@ spec aptos_framework::account { let post account_resource = global(addr); aborts_if !exists(addr); aborts_if vector::length(new_auth_key) != 32; + aborts_if permissioned_signer::spec_is_permissioned_signer(account); modifies global(addr); ensures account_resource.authentication_key == new_auth_key; } @@ -209,6 +210,7 @@ spec aptos_framework::account { let post account_resource = global(addr); aborts_if !exists(addr); aborts_if vector::length(new_auth_key) != 32; + aborts_if permissioned_signer::spec_is_permissioned_signer(account); modifies global(addr); ensures account_resource.authentication_key == new_auth_key; } @@ -258,6 +260,7 @@ spec aptos_framework::account { let addr = signer::address_of(account); let account_resource = global(addr); aborts_if !exists(addr); + aborts_if permissioned_signer::spec_is_permissioned_signer(account); /// [high-level-req-6.1] include from_scheme == ED25519_SCHEME ==> ed25519::NewUnvalidatedPublicKeyFromBytesAbortsIf { bytes: from_public_key_bytes }; @@ -331,6 +334,7 @@ spec aptos_framework::account { new_public_key_bytes: vector, cap_update_table: vector ) { + aborts_if permissioned_signer::spec_is_permissioned_signer(delegate_signer); aborts_if !exists(rotation_cap_offerer_address); let delegate_address = signer::address_of(delegate_signer); let offerer_account_resource = global(rotation_cap_offerer_address); @@ -390,7 +394,7 @@ spec aptos_framework::account { source_address, recipient_address, }; - + aborts_if permissioned_signer::spec_is_permissioned_signer(account); aborts_if !exists(@aptos_framework); aborts_if !exists(recipient_address); aborts_if !exists(source_address); @@ -445,6 +449,7 @@ spec aptos_framework::account { recipient_address, }; + aborts_if permissioned_signer::spec_is_permissioned_signer(account); aborts_if !exists(recipient_address); aborts_if !exists(source_address); @@ -504,6 +509,7 @@ spec aptos_framework::account { /// The Account existed under the signer. /// The value of signer_capability_offer.for of Account resource under the signer is to_be_revoked_address. spec revoke_signer_capability(account: &signer, to_be_revoked_address: address) { + aborts_if permissioned_signer::spec_is_permissioned_signer(account); aborts_if !exists(to_be_revoked_address); let addr = signer::address_of(account); let account_resource = global(addr); @@ -515,6 +521,7 @@ spec aptos_framework::account { spec revoke_any_signer_capability(account: &signer) { modifies global(signer::address_of(account)); + aborts_if permissioned_signer::spec_is_permissioned_signer(account); /// [high-level-req-7.4] aborts_if !exists(signer::address_of(account)); let account_resource = global(signer::address_of(account)); @@ -522,6 +529,7 @@ spec aptos_framework::account { } spec revoke_rotation_capability(account: &signer, to_be_revoked_address: address) { + aborts_if permissioned_signer::spec_is_permissioned_signer(account); aborts_if !exists(to_be_revoked_address); let addr = signer::address_of(account); let account_resource = global(addr); @@ -534,6 +542,7 @@ spec aptos_framework::account { } spec revoke_any_rotation_capability(account: &signer) { + aborts_if permissioned_signer::spec_is_permissioned_signer(account); let addr = signer::address_of(account); modifies global(addr); aborts_if !exists(addr); @@ -547,6 +556,7 @@ spec aptos_framework::account { /// The Account existed under the signer. /// The value of signer_capability_offer.for of Account resource under the signer is offerer_address. spec create_authorized_signer(account: &signer, offerer_address: address): signer { + aborts_if permissioned_signer::spec_is_permissioned_signer(account); /// [high-level-req-8] include AccountContainsAddr{ account, @@ -581,9 +591,13 @@ spec aptos_framework::account { spec fun spec_create_resource_address(source: address, seed: vector): address; spec create_resource_account(source: &signer, seed: vector): (signer, SignerCapability) { + use aptos_framework::create_signer; let source_addr = signer::address_of(source); let resource_addr = spec_create_resource_address(source_addr, seed); + let resource = create_signer::spec_create_signer(resource_addr); + aborts_if permissioned_signer::spec_is_permissioned_signer(resource); + aborts_if len(ZERO_AUTH_KEY) != 32; include exists_at(resource_addr) ==> CreateResourceAccountAbortsIf; include !exists_at(resource_addr) ==> CreateAccountAbortsIf {addr: resource_addr}; diff --git a/aptos-move/framework/aptos-framework/sources/aptos_account.move b/aptos-move/framework/aptos-framework/sources/aptos_account.move index 14f4a2708c66a..7e9d45511675c 100644 --- a/aptos-move/framework/aptos-framework/sources/aptos_account.move +++ b/aptos-move/framework/aptos-framework/sources/aptos_account.move @@ -328,7 +328,7 @@ module aptos_framework::aptos_account { coin::deposit(signer::address_of(alice), coin::mint(10000, &mint_cap)); let perm_handle = permissioned_signer::create_permissioned_handle(alice); - let alice_perm_signer = permissioned_signer::signer_from_permissioned(&perm_handle); + let alice_perm_signer = permissioned_signer::signer_from_permissioned_handle(&perm_handle); fungible_asset::grant_apt_permission(alice, &alice_perm_signer, 500); transfer(&alice_perm_signer, bob, 500);