What is the underlying difference between transfer::public_transfer() and transfer::transfer()

Hey team, i was trying to understand transfer policy, I see we need to use public_transfer to transfer store objects outside of the module but when i try to do transfer::transfer for store object from the same module where it is defined as shown below:

module 0x123::board {
    use sui::object::UID;
    use sui::transfer;
    
    struct MyObj has key, store {
        id: UID,
    }
    
    public fun transfer(object: MyObj, receiver: address) {
        //should have been transfer::public_transfer(object, receiver);
        transfer::transfer(object, receiver);
    }
}

I am getting warning message saying:

public fun transfer(object: OwnedObject, receiver: address) {
   │                ^^^^^^^^ ------ An instance of a module-private type with a store ability to be transferred coming from here
   │                │         
   │                Potential unintended implementation of a custom transfer function.
10 │         transfer::transfer(object, receiver);
   │                 -------- Instances of a type with a store ability can be transferred using the public_transfer function which often negates the intent of enforcing a custom transfer policy
  

is it just the standard practice or what is the prime difference in this case?

2 Likes

Hi @bipin_bhandari,

This warning is spotting that you are calling transfer::transfer on a type that has store, which means you may be trying to implement a custom transfer function, but the fact that the type has store means this custom transfer function (and any restrictions it enforces) could be bypassed.

If you are trying to implement a custom transfer function, then you:

  • Remove store from the type.
  • Retain the use of transfer::transfer in the function defined within the type’s module.
  • Use the module’s custom transfer function to initiate transfers from other modules.

If you are not trying to implement a custom transfer function, then you should use transfer::public_transfer everywhere. This makes the intention clearer to the compiler.

The docs related to custom transfer rules share more background.

2 Likes

Pefect Thank you Team.

1 Like