You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Updated the advanced cross-contract call tutorial to clarify patterns and enhance explanations. Added sections on asynchronous architecture, error handling, and best practices for complex interactions.
import {CodeTabs, Language, Github} from "@site/src/components/codetabs"
9
9
10
-
This example presents 3 instances of complex cross-contract calls on the NEAR blockchain, showcasing how to batch multiple function calls to a same contract, call multiple contracts in parallel, and handle responses in the callback. It includes both the smart contract and the frontend components.
11
-
10
+
This guide explores advanced cross-contract call patterns in NEAR, demonstrating how to orchestrate complex multi-contract interactions. You'll learn to batch function calls, execute contracts in parallel, and handle sophisticated callback scenarios.
12
11
13
12
:::info Simple Cross-Contract Calls
14
13
15
14
Check the tutorial on how to use [simple cross-contract calls](xcc.md)
16
15
17
16
:::
18
17
18
+
## Understanding NEAR's Asynchronous Architecture
19
+
20
+
Before diving into complex patterns, it's crucial to understand why NEAR handles cross-contract calls differently from other blockchains.
21
+
22
+
NEAR's sharded architecture makes all cross-contract interactions asynchronous and independent. This design choice enables massive scalability but requires a different mental model:
23
+
24
+
-**Independent execution**: Each contract runs in its own environment
25
+
-**Asynchronous results**: You cannot get immediate responses from external calls
26
+
-**Promise-based coordination**: Use Promises to schedule and chain operations
27
+
28
+
Think of it like coordinating multiple teams across different time zones—you send instructions, continue with other work, and process responses as they arrive.
You have two options to start the Donation Example:
43
+
You have two options to start the Cross Contract Call Example:
24
44
25
45
1. You can use the app through `Github Codespaces`, which will open a web-based interactive environment.
26
46
2. Clone the repository locally and use it from your computer.
@@ -86,13 +106,13 @@ The smart contract is available in two flavors: Rust and JavaScript
86
106
87
107
---
88
108
89
-
## Smart Contract
109
+
## Smart Contract Patterns
90
110
91
-
### Batch Actions
111
+
### Pattern 1: Batch Actions
92
112
93
-
You can aggregate multiple actions directed towards one same contract into a batched transaction.
94
-
Methods called this way are executed sequentially, with the added benefit that, if one fails then
95
-
they **all get reverted**.
113
+
Batch actions let you aggregate multiple function calls to the same contract into a single atomic transaction. This is perfect when you need sequential operations that must all succeed or all fail together.
114
+
115
+
**Use case**: Multi-step operations that require consistency, such as complex DeFi transactions or multi-stage data updates.
96
116
97
117
<CodeTabs>
98
118
<Languagevalue="js"language="js">
@@ -110,10 +130,9 @@ they **all get reverted**.
110
130
</Language>
111
131
</CodeTabs>
112
132
113
-
#### Getting the Last Response
133
+
#### Handling Batch Responses
114
134
115
-
In this case, the callback has access to the value returned by the **last
116
-
action** from the chain.
135
+
With batch actions, your callback receives the result from the **last action** in the sequence. This design makes sense because if any earlier action failed, the entire batch would have reverted.
117
136
118
137
<CodeTabs>
119
138
<Languagevalue="js"language="js">
@@ -136,10 +155,11 @@ action** from the chain.
136
155
137
156
---
138
157
139
-
### Calling Multiple Contracts
158
+
### Pattern 2: Calling Multiple Contracts in Parallel
159
+
160
+
When you need to interact with multiple contracts simultaneously, NEAR's parallel execution shines. Each call executes independently—if one fails, the others continue unaffected.
140
161
141
-
A contract can call multiple other contracts. This creates multiple transactions that execute
142
-
all in parallel. If one of them fails the rest **ARE NOT REVERTED**.
162
+
**Use case**: Gathering data from multiple sources, executing independent operations, or building resilient multi-protocol interactions.
143
163
144
164
<CodeTabs>
145
165
<Languagevalue="js"language="js">
@@ -157,10 +177,9 @@ all in parallel. If one of them fails the rest **ARE NOT REVERTED**.
157
177
</Language>
158
178
</CodeTabs>
159
179
160
-
#### Getting All Responses
180
+
#### Processing Multiple Responses
161
181
162
-
In this case, the callback has access to an **array of responses**, which have either the
163
-
value returned by each call, or an error message.
182
+
With parallel calls, your callback receives an **array of responses**. Each response either contains the returned value or an error message, allowing you to handle partial failures gracefully.
164
183
165
184
<CodeTabs>
166
185
<Languagevalue="js"language="js">
@@ -183,12 +202,11 @@ value returned by each call, or an error message.
183
202
184
203
---
185
204
186
-
### Multiple Calls - Same Result Type
205
+
### Pattern 3: Multiple Calls with Uniform Response Types
187
206
188
-
This example is a particular case of the previous one ([Calling Multiple Contracts](#calling-multiple-contracts)).
189
-
It simply showcases a different way to check the results by directly accessing the `promise_result` array.
207
+
This pattern is particularly useful when calling multiple instances of similar contracts or the same method across different contracts. It demonstrates a clean way to handle uniform response types.
190
208
191
-
In this case, we call multiple contracts that will return the same type:
209
+
**Use case**: Polling multiple data sources, aggregating results from similar contracts, or implementing multi-oracle patterns.
192
210
193
211
<CodeTabs>
194
212
<Languagevalue="js"language="js">
@@ -206,10 +224,9 @@ In this case, we call multiple contracts that will return the same type:
206
224
</Language>
207
225
</CodeTabs>
208
226
209
-
#### Getting All Responses
227
+
#### Iterating Through Uniform Responses
210
228
211
-
In this case, the callback again has access to an **array of responses**, which we can iterate checking the
212
-
results.
229
+
When all external contracts return the same data type, you can process responses more elegantly:
213
230
214
231
<CodeTabs>
215
232
<Languagevalue="js"language="js">
@@ -232,9 +249,55 @@ results.
232
249
233
250
---
234
251
235
-
### Testing the Contract
252
+
## Production Considerations
253
+
254
+
### Critical Callback Behavior
255
+
256
+
Understanding callback execution is essential for building reliable applications:
257
+
258
+
-**Callbacks always execute**: Whether external calls succeed or fail, your callback will run
259
+
-**Manual rollbacks required**: Failed external calls don't automatically revert your contract's state changes
260
+
-**Token handling**: Failed calls return attached NEAR tokens to your contract, not the original caller
261
+
262
+
### Error Handling Strategy
263
+
264
+
Implement comprehensive error handling in your callbacks:
-**Allocate sufficient gas**: Cross-contract calls consume more gas than single-contract operations
293
+
-**Account for callback execution**: Reserve gas for your callback function
294
+
-**Handle gas estimation failures**: Implement fallbacks when gas estimates are insufficient
295
+
296
+
---
297
+
298
+
## Testing the Contract
236
299
237
-
The contract readily includes a set of unit and sandbox testing to validate its functionality. To execute the tests, run the following commands:
300
+
The contract includes comprehensive testing to validate complex interaction patterns. Run the following commands to execute tests:
238
301
239
302
<TabsgroupId="code-tabs">
240
303
<TabItemvalue="js"label="🌐 JavaScript">
@@ -257,8 +320,8 @@ The contract readily includes a set of unit and sandbox testing to validate its
257
320
258
321
</Tabs>
259
322
260
-
:::tip
261
-
The `integration tests` use a sandbox to create NEAR users and simulate interactions with the contract.
323
+
:::tip Testing Cross-Contract Logic
324
+
The integration tests use a sandbox environment to simulate multi-contract interactions. This is essential for validating that your callback logic handles both success and failure scenarios correctly.
262
325
:::
263
326
264
327
<hrclass="subsection" />
@@ -311,55 +374,157 @@ Go into the directory containing the smart contract (`cd contract-advanced-ts` o
311
374
312
375
### CLI: Interacting with the Contract
313
376
314
-
To interact with the contract through the console, you can use the following commands:
377
+
Test the different cross-contract patterns using these commands:
315
378
316
379
<TabsgroupId="cli-tabs">
317
380
<TabItemvalue="short"label="Short">
318
381
319
382
```bash
320
-
# Execute contracts sequentially
321
-
# Replace <accountId> with your account ID
383
+
# Execute contracts sequentially (batch pattern)
322
384
near call <accountId> batch_actions --accountId <accountId> --gas 300000000000000
323
385
324
-
# Execute contracts in parallel
325
-
# Replace <accountId> with your account ID
326
-
near call <accountId> multiple_contracts --accountId <accountId> --gas 300000000000000
386
+
# Execute contracts in parallel (multiple contracts pattern)
387
+
near call <accountId> multiple_contracts --accountId <accountId> --gas 300000000000000
327
388
328
-
# Execute multiple instances of the same contract in parallel
329
-
# Replace <accountId> with your account ID
389
+
# Execute multiple instances with same return type
330
390
near call <accountId> similar_contracts --accountId <accountId> --gas 300000000000000
near.log(`Callback executed with status: ${result.success?'SUCCESS':'FAILED'}`);
479
+
```
480
+
481
+
### 3. Optimize Gas Usage
352
482
353
-
:::info
354
-
If at some point you get an "Exceeded the prepaid gas" error, try to increase the gas amount used within the functions when calling other contracts
483
+
Cross-contract calls consume significant gas. Profile your operations and optimize:
484
+
485
+
- Use appropriate gas allocations for each external call
486
+
- Consider the gas cost of your callback processing
487
+
- Implement gas estimation for complex workflows
488
+
489
+
### 4. State Management Strategy
490
+
491
+
Plan your state changes carefully:
492
+
493
+
- Save original state before making external calls
494
+
- Implement clear rollback procedures
495
+
- Use consistent patterns across your application
496
+
497
+
---
498
+
499
+
## Troubleshooting Common Issues
500
+
501
+
:::warning Gas Limitations
502
+
If you encounter "Exceeded the prepaid gas" errors, increase the gas amount in your external contract calls. Complex multi-contract operations require substantial gas allocation.
355
503
:::
356
504
357
-
:::note Versioning for this article
505
+
:::info Callback Debugging
506
+
Use NEAR's sandbox testing environment to debug callback logic. The sandbox lets you simulate various failure scenarios and validate your error handling.
507
+
:::
358
508
509
+
:::note Version Compatibility
359
510
At the time of this writing, this example works with the following versions:
360
511
361
512
- near-cli: `4.0.13`
362
-
- node: `18.19.1`
513
+
- node: `18.19.1`
363
514
- rustc: `1.77.0`
364
-
365
515
:::
516
+
517
+
---
518
+
519
+
## Taking Your Skills Further
520
+
521
+
Mastering these complex cross-contract patterns opens up possibilities for building sophisticated applications:
522
+
523
+
-**DeFi protocols** that coordinate across multiple markets
524
+
-**Multi-step workflows** that span several specialized contracts
525
+
-**Resilient systems** that gracefully handle partial failures
526
+
-**High-performance applications** that leverage parallel execution
527
+
528
+
The key is understanding that NEAR's asynchronous nature isn't a constraint—it's a powerful feature that enables building applications that would be impossible on synchronous blockchains.
529
+
530
+
Start with these patterns, experiment with combining them, and you'll discover new ways to architect complex blockchain applications that take full advantage of NEAR's unique capabilities.
0 commit comments