# [Ride v5] dApp-to-dApp Invocation Functions
⚠️ This is the documentation for the Standard library version 5. We recommend to use version 6. Go to version 6
| Name | Description | Complexity |
|---|---|---|
| invoke | Invokes a dApp callable function, with reentrancy restriction | 75 |
| reentrantInvoke | Invokes a dApp callable function, without reentrancy restriction | 75 |
# invoke
Invokes a dApp callable function, with reentrancy restriction.
invoke(dApp: Address|Alias, function: String, arguments: List[Any], payments: List[AttachedPayments]): Any
Any means any valid type. You can extract a particular type from it using the match ... case operator, see the example.
The invoke function can be used by a callable function of a dApp script, but not by a verifier function, account script or asset script.
Via the invoke function, the callable function can invoke a callable function of another dApp, or another callable function of the same dApp, or even itself, and then use the invocation results in subsequent operations. For details, see the dApp-to-dApp Invocation article.
💡 To ensure executing callable functions and applying their actions in the right order, initialize a strict variable by the return value of an invoke function.
The invocation can contain payments that will be transferred from the balance of the parent dApp to the balance of the invoked dApp. Payments are forbidden if the dApp invokes itself.
If a payment token is a smart asset, the asset script verifies the invoke as if it was InvokeScriptTransaction with the following fields:
dApp,payments,function,argsindicated in theinvokefunction;sender,senderPublicKeyof the dApp that performs the invocation;id,timestamp,fee,feeAssetIdindicated in the original Invoke Script transaction;version= 0;
If the asset script denies the action, the Invoke Script transaction is either discarded or saved on the blockchain as failed, see the Transaction Validation.
# Reentrancy Restriction
The invocation stack generated by the invoke function must not contain invocations of the parent dApp after invocation of another dApp.
Let the parent dApp A invokes dApp B using the invoke function. Regardless of whether dApp B uses invoke or reentrantInvoke, the following invocation stacks will fail:
→ dApp A
→ dapp B
→ dApp A
→ dApp A
→ dapp B
→ dApp C
→ dApp A
The following invocation stacks are valid:
→ dApp A
→ dapp A
→ dapp A
→ dApp N
→ dapp A
→ dApp A
→ dapp N
→ dapp A
→ dapp B
→ dapp B
→ dapp A
→ dapp C
# Parameters
| Parameter | Description |
|---|---|
| dApp: Address|Alias | Address or alias of a dApp to invoke |
| function: String|Unit | Name of a callable function. unit for a default function invocation |
| arguments: List[Any] | Parameters of a callable function |
| payments: List[AttachedPayment] | Payments to transfer from the parent dApp to the invoked dApp, up to 10 |
# Example
A user sends an Invoke Script transaction that invokes the callable function foo of dApp1.
The foo function invokes the bar function of dApp2 passing the number a and attaching a payment of 1 XTN.
The bar function transfers 1 WAVES to dApp1 and returns the doubled number a.
The foo function writes to dApp1 data storage:
- the value returned by
bar, - the new balance of dApp2 (reduced by 1 WAVES transferred to dApp1).
dApp1:
{-# STDLIB_VERSION 5 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}
@Callable(i)
func foo(dapp2: String, a: Int, key1: String, key2: String) = {
strict res = invoke(addressFromStringValue(dapp2),"bar",[a],[AttachedPayment(base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p',1000000)])
match res {
case r : Int =>
(
[
IntegerEntry(key1, r),
IntegerEntry(key2, wavesBalance(addressFromStringValue(dapp2)).regular)
],
unit
)
case _ => throw("Incorrect invoke result")
}
}
dApp2:
{-# STDLIB_VERSION 5 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}
@Callable(i)
func bar(a: Int) = {
(
[
ScriptTransfer(i.caller, 100000000, unit)
],
a*2
)
}
# reentrantInvoke
Invokes a dApp callable function. The only difference from the invoke function is that there is no reentrancy restriction for the parent dApp that uses reentrantInvoke.
However, if the parent dApp is invoked again and this time uses the invoke function, the parent dApp cannot be invoked again in this invocation stack.
For example, the invocation stack
→ dApp A
→ dapp B
→ dApp A
→ dApp C
→ dApp A
- is valid if dApp A invokes both dApp B and dApp C via the
reentrantInvokefunction; - fails if dApp A invokes dApp B via the
reentrantInvokefunction and invokes dApp C via theinvokefunction.
reentrantInvoke(dApp: Address|Alias, function: String, arguments: List[Any], payments: List[AttachedPayments]): Any