@@ -28,3 +28,77 @@ error, retry the operation, ignore it, etc.
28
28
29
29
The default value ` ReplyOn::Success ` means the caller is not ready to handle an error in the message
30
30
execution and the entire transaction is reverted on error.
31
+
32
+ ## Dispatching Submessages
33
+
34
+ Now let's move onto the ` messages ` field of the
35
+ [ ` Response ` ] ( https://docs.rs/cosmwasm-std/latest/cosmwasm_std/struct.Response.html ) . Some contracts
36
+ are fine only talking with themselves. But many want to move tokens or call into other contracts for
37
+ more complex actions. This is where messages come in. We return
38
+ [ ` CosmosMsg ` ] ( https://docs.rs/cosmwasm-std/latest/cosmwasm_std/enum.CosmosMsg.html ) , which is a
39
+ serializable representation of any external call the contract can make.
40
+
41
+ This may be hard to understand at first. "Why can't I just call another contract?", you may ask.
42
+ However, we do this to prevent one of the most widespread and hardest to detect security holes in
43
+ Ethereum contracts - reentrancy. We do this by following the actor model, which doesn't nest
44
+ function calls, but returns messages that will be executed later. This means all state that is
45
+ carried over between one call and the next happens in storage and not in memory. For more
46
+ information on this design, I recommend you read [ our docs on the Actor Model] ( actor-model.mdx ) .
47
+
48
+ A common request was the ability to get the result from one of the messages you dispatched. For
49
+ example, you want to create a new contract with
50
+ [ ` WasmMsg::Instantiate ` ] ( https://docs.rs/cosmwasm-std/latest/cosmwasm_std/enum.WasmMsg.html#variant.Instantiate ) ,
51
+ but then you need to store the address of the newly created contract in the caller. This is possible
52
+ with ` messages ` and replies. This makes use of
53
+ [ ` CosmosMsg ` ] ( https://docs.rs/cosmwasm-std/latest/cosmwasm_std/enum.CosmosMsg.html ) as above, but it
54
+ wraps it inside a [ ` SubMsg ` ] ( https://docs.rs/cosmwasm-std/latest/cosmwasm_std/struct.SubMsg.html )
55
+ envelope.
56
+
57
+ What are the semantics of a submessage execution? First, we create a sub-transaction context around
58
+ the state, allowing it to read the latest state written by the caller, but write to yet-another
59
+ cache. If ` gas_limit ` is set, it is sandboxed to how much gas it can use until it aborts with
60
+ ` OutOfGasError ` . This error is caught and returned to the caller like any other error returned from
61
+ contract execution (unless it burned the entire gas limit of the transaction).
62
+
63
+ If it returns success, the temporary state is committed (into the caller's cache), and the
64
+ [ ` Response ` ] ( https://docs.rs/cosmwasm-std/latest/cosmwasm_std/struct.Response.html ) is processed as
65
+ normal. Once the response is fully processed, this may then be intercepted by the calling contract
66
+ (for ` ReplyOn::Always ` and ` ReplyOn::Success ` ). On an error, the subcall will revert any partial
67
+ state changes due to this message, but not revert any state changes in the calling contract. The
68
+ error may then be intercepted by the calling contract (for ` ReplyOn::Always ` and ` ReplyOn::Error ` ).
69
+ In this case, the message's error doesn't abort the whole transaction.
70
+
71
+ Note, that error doesn't abort the whole transaction _ if and only if_ the ` reply ` is called - so in
72
+ case of ` ReplyOn::Always ` and ` ReplyOn::Error ` . If the submessage is called with ` ReplyOn::Success `
73
+ or ` ReplyOn::Never ` , the error in a subsequent call would result in failing whole transaction and
74
+ not commit the changes for it. The rule here is as follows: if for any reason you want your message
75
+ handling to succeed on submessage failure, you always have to reply on failure.
76
+
77
+ ## Order of execution and rollback procedure
78
+
79
+ Submessages handling follows _ depth first_ order rules. Let's see the following example scenario:
80
+
81
+ ``` mermaid
82
+
83
+ sequenceDiagram
84
+ Note over Contract1: Contract1 returns two submessages:<br/> 1. Execute Contract2<br/> 2. Execute Contract4
85
+ Contract1->>Contract2: 1. Execute
86
+ Note over Contract2: Contract2 returns one submessage:<br/> 1. Execute Contract3
87
+ Contract2->>Contract3: 2. Execute
88
+ Contract3->>Contract2: 3. Response
89
+ Note over Contract2: Contract2 can handle the Response<br/>in the reply entrypoint or leave it
90
+ Contract2->>Contract1: 4. Response
91
+ Note over Contract1: Contract1 can handle the Response<br/>in the reply entrypoint or leave it
92
+ Contract1->>Contract4: 5. Execute
93
+ Contract4->>Contract1: 6. Response
94
+ Note over Contract1: Contract1 can handle the Response<br/>in the reply entrypoint or leave it
95
+
96
+ ```
97
+
98
+ ** Note1:** The field ` data ` of the submessages field in the response are not forwarded down the call
99
+ path. It means that for e.g. if ` Contract2 ` will not explicitly handle response from ` Contract3 ` and
100
+ forward any data, then ` Contract1 ` will never learn about results from ` Contract3 ` .
101
+
102
+ ** Note2:** If ` Contract2 ` returns an error, the error message can be handled by the ` Contract1 `
103
+ reply entry-point and prevent the whole transaction from rollback. In such a case only the
104
+ ` Contract2 ` and ` Contract3 ` states changes are reverted.
0 commit comments