TODO: Add scenarios?
I'm diving this into three parts: Tokens, Queries and Fees.
In order to operate with ERC20 tokens, a user needs to call specific functions in its origin smart contract, for example, for transferring it.
In XCM, assets are operated upon by means of the TransactAsset trait.
In order for XCM to recognize we are dealing with an ERC20, we would need to create an asset transactor to handle them.
This asset transactor has to match ERC20s based on their id. A possible one is the following: [PalletInstance(<pallet-revive index>), AccountKey20 { id }]
where id
is the contract's address.
Then, different XCM instructions need to call functions in the contract, like TransferAsset
, DepositAsset
and WithdrawAsset
.
TransferAsset
would call transfer
.
With WithdrawAsset
and DepositAsset
we could call something like burn
and mint
respectively or we could transfer
to a checking account.
Acala has one for this purpose which we could use as a reference.
We probably need the same for ERC721 but I'm less familiar with that standard.
We could make use of the traits for NFTs.
This could be further split into receiving and sending.
In order to send a query we need a host function for contracts that calls pallet-xcm's new_query function to store a Query.
Both scenarios assume that a new query is created using the XCM precompile. Then, an XCM message (e.g.: Xcm(vec![Transact {...}, ReportTransactStatus(QueryResponseInfo {queryId …}])
) should be sent to the destination chain, essentially linking a queryId
to some bytes that are meant to be executed.
We need to have a way of getting the result of the execution of a remote call. This should return a response with the result. In case of failing, the response should contain the actual error.
Allow the smart contracts on Asset Hub to query data on external consensus systems. This might be a call to a specific pallet or a view function in a smart contract. We should be able to send PVQ blobs using the new ReportQuery instruction.
A message is received by the runtime to respond to a query with some query id.
This will match the query id of the query created previously.
We need a host function in contracts that calls pallet-xcm's take_response to poll for the response, this could result in an callback, which could be handled by a function in the contract.
Pallet-revive charges an additional fee for storage deposits.
We can use the new fees
register to charge this fee.
We need some place to charge them, be it in CallDispatcher
for Transact
or in the new instruction EvmCall
if we decide to go for it.
The EvmCall
instruction would be easier since we already know we have to deal with these storage deposits.
The fees
register can also be exposed to the transactor to charge storage deposits.
Storage deposits need to be charged in this way, but regular gas cost could be charged up-front with PayFees
, as part of execution costs.
An open question I have is if we should separate them or treat them in the same way.
We would need to make sure the DryRunApi
can successfully dry-run a program with EVM calls.
We already have calls for execution fees and delivery fees in XcmPaymentApi
. Do we just add another one for EVM storage deposits?
Should we just have a more powerful DryRunApi
that returns all fees: execution, delivery, EVM storage deposits, etc.