Problem statement: if a token has a defined transferRole, the user has to go into the specific dApp in order to make any interactions, even the simplest transfer. No standard interaction for wallet to understand how to handle those tokens.
Question: How do we ensure a smooth experience for users and tokens where we have a transferRole on the tokenID?
Resolve:
We define a standard transfer smart contract, with a set of defined functions, which can be easily interpreted and integrated into the wallet, in order to enable all use cases from any user and contract combination.
What does it mean for wallet/API?
We create a component which does the following:
-
Check the properties of the tokenID, especially check if the transferRole is set. API has this information
-
Check the Smart Contracts the tokenID has listed for transferRole
-
Check if there is a contract which fits the the transferSC1.0 standard
a, We do this by giving contracts a tag on explorer if the contract fits the standard.
b. This can be done automatically if the developer uses the automatic build tool, as we have access for the full ABI and full Rust SC. -
If multiple contracts fit the transferSC1.0 standard choose the one from the same shard as the USER. Or choose the transferContract from the shard where the destination dApp is. Explained in more detail below.
-
Form a transaction which will transfer those tokens using the transferSC1.0 standard:
a. Destination for the token transfer will be the transferContract.
b. Additional arguments of the transfer will be: forwardTransfer@destination@extraArguments
c. Thus this will look like: MutliESDTNFTTransfer@transferContract@tokenID@nonce@value@ forwardTransfer@destination@extraArguments
1. Transferring tokens from user to user
When Alice wants to send tokens to Bob, the wallet analyzes whether in the set of tokens there is a token with transferRole, and will check if Alice/Bob has transfer roles. If the token can be transferred through the transferContract, the wallet will format the transfer as explained above on step 5.c.and the destination is the user, as the real destination is in the first argument of the MultiTransfer.
MutliESDTNFTTransfer@transferContract@List<tokenID@nonce@value>@ forwardTransfer@destination@extraArguments
forwardTransfer@destination@extraArguments: will do extra checks (these extra checks regarding compliance or users or whatever is the job of the developer) on the received tokens and make a transferAndExecute to the destination, with the remaining tokens (like if a fee is taken out from one of those) and the received extra arguments. If the destination is a SC, the first argument out of those extras will be used as the function.
2. Tokens and exchanges:
The transferSC1.0 has to be able to interact with the exchanges and all the dApps in a relatively easy way. As the token has a transferRole, every transaction in regards to an exchange will fail, thus we need a dynamic execution from the transferContract to handle exchange interactions.
If the user wants to enterLP, enterFarm or simply swap to and from the token it has to be done through the transferContract. Thus we define/implement a module through which multiple actions can be performed. This is true for swapping from both to and from the token.
Thus we make new endpoints:
forwardExecuteOnDest@destination@extraArguments: after verifying the multitransfer, compliance and taking fee from the special tokenID, this will call ExecuteOnDestContext - the results on the received payments will be sent to the users after an additional set of customized operations by the contract. In case of error the tx will fail and the user will get back his tokens.
forwardAsyncCall@destination@extraArguments: does the same as above but with an asynchronous call, and will send back to the user on the callback. On callback we need to send back to the user all his tokens, even those which were taken out for a fee.
So what will the xExchange microservice do: for all the swaps/operations with the given token, which has a transferRole, the microservice has to format the transaction for the user in the above mentioned formats. ExtraArguments are actually the arguments needed for xExchange operations, and those will be executed from the transferContract.
For any token it is possible to have one/multiple transferSCs, thus you can deploy one for every shard.
Later, after implementation of the ExecutetByCaller and ExecuteByOriginalCaller we can introduce new optional endpoints for the transferRole contract, named transferRolev2.0 - which uses the new VM OPCODES as well.
3. NFTs and marketplaces:
Buying with a transferToken is simple, everything is the same as in point 2.
But what do we do with NFTs which want to get into marketplaces but they have extra transferRole checks. Short answer - those should have their own marketplace, and discuss with XOXNO and xFabric to have them integrated, this is the simplest. I do not see the point of complicating it in a transferSC contract and keep evidence of which user has which NFT, as in case of sell, the transferSC contract is not called automatically from the marketplaces as it is right now. For that case, we will use and introduce the concepts of HOOKS as standard.
For other similar cases, we will introduce new OPCODE on VM to ExecuteByOriginalCaller/ExecuteByCaller, but that is another improvement proposal.