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 fe8d3418f93d7..28b1374e4f850 100644 --- a/aptos-move/framework/aptos-framework/doc/primary_fungible_store.md +++ b/aptos-move/framework/aptos-framework/doc/primary_fungible_store.md @@ -25,6 +25,9 @@ fungible asset to it. This emits an deposit event. - [Function `primary_store_address`](#0x1_primary_fungible_store_primary_store_address) - [Function `primary_store`](#0x1_primary_fungible_store_primary_store) - [Function `primary_store_exists`](#0x1_primary_fungible_store_primary_store_exists) +- [Function `primary_store_address_inlined`](#0x1_primary_fungible_store_primary_store_address_inlined) +- [Function `primary_store_inlined`](#0x1_primary_fungible_store_primary_store_inlined) +- [Function `primary_store_exists_inlined`](#0x1_primary_fungible_store_primary_store_exists_inlined) - [Function `balance`](#0x1_primary_fungible_store_balance) - [Function `is_balance_at_least`](#0x1_primary_fungible_store_is_balance_at_least) - [Function `is_frozen`](#0x1_primary_fungible_store_is_frozen) @@ -280,6 +283,86 @@ Return whether the given account's primary store exists. + + + + +## Function `primary_store_address_inlined` + +Get the address of the primary store for the given account. +Use instead of the corresponding view functions for dispatchable hooks to avoid circular dependencies of modules. + + +
public fun primary_store_address_inlined<T: key>(owner: address, metadata: object::Object<T>): address
+
+ + + +
+Implementation + + +
public inline fun primary_store_address_inlined<T: key>(owner: address, metadata: Object<T>): address {
+    let metadata_addr = object::object_address(&metadata);
+    object::create_user_derived_object_address(owner, metadata_addr)
+}
+
+ + + +
+ + + +## Function `primary_store_inlined` + +Get the primary store object for the given account. +Use instead of the corresponding view functions for dispatchable hooks to avoid circular dependencies of modules. + + +
public fun primary_store_inlined<T: key>(owner: address, metadata: object::Object<T>): object::Object<fungible_asset::FungibleStore>
+
+ + + +
+Implementation + + +
public inline fun primary_store_inlined<T: key>(owner: address, metadata: Object<T>): Object<FungibleStore> {
+    let store = primary_store_address_inlined(owner, metadata);
+    object::address_to_object(store)
+}
+
+ + + +
+ + + +## Function `primary_store_exists_inlined` + +Return whether the given account's primary store exists. +Use instead of the corresponding view functions for dispatchable hooks to avoid circular dependencies of modules. + + +
public fun primary_store_exists_inlined<T: key>(account: address, metadata: object::Object<T>): bool
+
+ + + +
+Implementation + + +
public inline fun primary_store_exists_inlined<T: key>(account: address, metadata: Object<T>): bool {
+    fungible_asset::store_exists(primary_store_address_inlined(account, metadata))
+}
+
+ + +
diff --git a/aptos-move/framework/aptos-framework/sources/primary_fungible_store.move b/aptos-move/framework/aptos-framework/sources/primary_fungible_store.move index 18b410c0373e1..fc20e1cf311a6 100644 --- a/aptos-move/framework/aptos-framework/sources/primary_fungible_store.move +++ b/aptos-move/framework/aptos-framework/sources/primary_fungible_store.move @@ -104,6 +104,26 @@ module aptos_framework::primary_fungible_store { fungible_asset::store_exists(primary_store_address(account, metadata)) } + /// Get the address of the primary store for the given account. + /// Use instead of the corresponding view functions for dispatchable hooks to avoid circular dependencies of modules. + public inline fun primary_store_address_inlined(owner: address, metadata: Object): address { + let metadata_addr = object::object_address(&metadata); + object::create_user_derived_object_address(owner, metadata_addr) + } + + /// Get the primary store object for the given account. + /// Use instead of the corresponding view functions for dispatchable hooks to avoid circular dependencies of modules. + public inline fun primary_store_inlined(owner: address, metadata: Object): Object { + let store = primary_store_address_inlined(owner, metadata); + object::address_to_object(store) + } + + /// Return whether the given account's primary store exists. + /// Use instead of the corresponding view functions for dispatchable hooks to avoid circular dependencies of modules. + public inline fun primary_store_exists_inlined(account: address, metadata: Object): bool { + fungible_asset::store_exists(primary_store_address_inlined(account, metadata)) + } + #[view] /// Get the balance of `account`'s primary store. public fun balance(account: address, metadata: Object): u64 { diff --git a/aptos-move/move-examples/fungible_asset/stablecoin/sources/usdk.move b/aptos-move/move-examples/fungible_asset/stablecoin/sources/usdk.move index 666d85cfb0a8a..d96baececf837 100644 --- a/aptos-move/move-examples/fungible_asset/stablecoin/sources/usdk.move +++ b/aptos-move/move-examples/fungible_asset/stablecoin/sources/usdk.move @@ -328,8 +328,10 @@ module stablecoin::usdk { // Check that the account is not denylisted by checking the frozen flag on the primary store fun assert_not_denylisted(account: address) { let metadata = metadata(); - if (primary_fungible_store::primary_store_exists(account, metadata)) { - assert!(!fungible_asset::is_frozen(primary_fungible_store::primary_store(account, metadata)), EDENYLISTED); + // CANNOT call into pfs::store_exists in our withdraw/deposit hooks as it creates possibility of a circular dependency. + // Instead, we will call the inlined version of the function. + if (primary_fungible_store::primary_store_exists_inlined(account, metadata)) { + assert!(!fungible_asset::is_frozen(primary_fungible_store::primary_store_inlined(account, metadata)), EDENYLISTED); } }