Posting Asynchronous Requests
Asynchronous function calls between smart contracts are posted as requests on the Tangle.
They allow you to invoke any smart contract function that is not a View on any smart
contract chain. You will notice that the behavior is very similar to a synchronous
function call, but instead of using the
call() method of the
func member in the
function descriptor, you will now use the
postToChain() methods. The
post() method posts the request to the current chain, while
postToChain() takes the
chain ID of the desired chain as parameter.
In addition to the previously discussed transferBaseTokens() and
ofContract() methods, you can modify the behavior further by providing a
delay() in seconds, which enables delayed execution of the request. This is of
particular interest to smart contracts that need a delayed action like betting contracts
with a timed betting round, or to create time-lock functionality in a smart contract.
Here's how that works:
eor := ScFuncs.EndOfRound(ctx)
let eor = ScFuncs::end_of_round(ctx);
let eor = sc.ScFuncs.endOfRound(ctx);
Because it is posted as a request on the Tangle, and it is not possible to have a request without a transfer, an asynchronous request always needs to send at least some tokens. In fact, there is a minimum amount of tokens to send, because you need to cover the gas that is necessary to run the function call. You can specify the tokens explicitly, in the same way we did previously with syncronous calls, or you can have WasmLib specify a minimum amount of tokens automatically. Any tokens that are not used will end up in the caller's account on the chain.
So, if you post to a function that expects tokens you just specify the amount of tokens required, but if you post to a function that does not expect any tokens then you can have WasmLib send the minimum amount for you.
delay() before a
call() will result in a panic. We do not know the
intention of the user until the actual call() or post() is encountered, so we cannot check
for this at compile-time unless we are willing to accept a lot of extra overhead. It
should not really be a problem because using
delay() is rare and using it with
cannot have been the intention.
The function that posts the request through the function descriptor will immediately continue execution and does not wait for its completion. Therefore, it is not possible to directly retrieve the return values from such a call.
If you need some return values, you will have to create a mechanism that can do so, for example by providing a callback chain/contract/function combination as part of the input parameters of the requested function, so that upon completion that function can asynchronously post the results to the indicated function. It will require a certain degree of cooperation between both smart contracts. In the future we will probably be looking at providing a generic mechanism for this.
In the next section we will look at how we can use the function descriptors when testing smart contracts with Solo.