This is a slightly more complex subject than it sounds. The reason is that while Polkadot guarantees the correct execution of each parachain's logic, it does not guarantee that the logic does something sensible or expected by some particular set of onlookers.
An obvious example would be teleports. The act of teleporting is basically the act of burning a token on one sending chain and at some point in the near future creating a token representing that destroyed asset on a receiving chain. One instance of this would be sending DOT from the Polkadot Relay-chain to the Statemint parachain: The DOT is destroyed on the Relay-chain and created on Statemint. It can be teleported back which involves it being destroyed on Statemint and minted again on the Relay-chain.
It is fairly easy to construct an XCM message to do this, and the XCM pallet in Cumulus includes such a facility to do just this (search for
fn teleport_assets). However, there is nothing embedded in the Polkadot protocol which stops the sending chain from sending a message to tell the "recipient" chain to mint a particular asset without actually destroying the corresponding asset. The reason we do teleporting between the Relay-chain and Statemint is because the Relay-chain is in complete control of Statemint's logic via governance, and thus it can trust Statemint to behave as expected.
The same cannot be said of arbitrary teams' parachains. Without even getting into malicious intent, an innocent bug could cause a parachain to inadvertently send unfaithful teleport counterparts, instructing the minting of tokens on receiving chains which never existed on the sending chain.
To manage this there are two solutions:
- SPREE (Secure Parachain Runtime Execution Enclaves), which allows for non-negotiable, individually addressable identical instances of logic modules (basically, pallets) to exist on parachains, thereby alleviating the need for one parachain to trust another's logic. This is not yet implemented but is at the design stage.
- Reserve Assets, the current solution, which is essentially to name a particular chain as the universally trusted home for an asset. When this asset "exists" on any chain which is not the home-chain, it in fact is just an IOU (or fully-backed derivative) which can be traded in for an instance of the real asset which exists on the home-chain.
When SPREE is delivered then the answer to this question will basically just be "have your parachain opt-in to the assets SPREE module". Until then, it's a little harder. Teleporting can work if both your parachain and the parachain from which you wish to receive the given asset trust each other's logic (to the point of bankrupting eachother if there is a bug in one). This level of trust between parachains isn't usually the case, but might work if a single parachain team end up deploying to multiple parachains. Otherwise we're basically stuck with reserve asset transfers. Right now for these to work, each asset must be configured individually with the fungible implementation in the runtime together with the home-chain on which the actual asset sits.
This is only a temporary solution. Changes which are part of the XCMv3 upgrade will bring along the possibility of automating the ability to receive, host and send foreign assets without requiring those assets to be explicitly configured in the runtime. There is already an example of this in the XCM v3 branch using the Uniques pallet
MultiLocations as a means of identifying a foreign NFT by its relative location.