1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//! Resource limit enforcement in tests.
//!
//! ## Breaking Change: Tests May Fail Due to Resource Limits
//!
//! By default, [`Env::default()`] now enforces mainnet resource limits for contract invocations in
//! tests. **If your contract exceeds any resource limit, your tests will panic** with details
//! about which limits were exceeded.
//!
//! This provides an early warning that a contract might be too resource-heavy to run on mainnet.
//!
//! **If you see test failures after upgrading**, and you wish to test without mainnet limits
//! (e.g., while experimenting or optimizing), see [Disabling Resource
//! Limits](#disabling-resource-limits) below.
//!
//! ## New Default Behavior
//!
//! When creating a new `Env` with [`Env::default()`], mainnet resource limits are automatically
//! enforced. No changes to existing test code are required to benefit from this protection.
//!
//! ```
//! use soroban_sdk::{contract, contractimpl, Env};
//!
//! #[contract]
//! pub struct Contract;
//!
//! #[contractimpl]
//! impl Contract {
//! pub fn execute() {
//! // ... code
//! }
//! }
//!
//! #[test]
//! fn test() {
//! # }
//! # #[cfg(feature = "testutils")]
//! # fn main() {
//! let env = Env::default(); // Mainnet limits enforced automatically
//! let contract_id = env.register(Contract, ());
//! let client = ContractClient::new(&env, &contract_id);
//! client.execute(); // Will panic if resource limit exceeded
//! }
//! # #[cfg(not(feature = "testutils"))]
//! # fn main() { }
//! ```
//!
//! ## Disabling Resource Limits
//!
//! For experimental contracts that are still being optimized, resource limit enforcement can be
//! disabled using [`CostEstimate::disable_resource_limits()`]:
//!
//! ```
//! use soroban_sdk::{contract, contractimpl, Env};
//!
//! #[contract]
//! pub struct Contract;
//!
//! #[contractimpl]
//! impl Contract {
//! pub fn execute() {
//! // ... resource-heavy code
//! }
//! }
//!
//! #[test]
//! fn test() {
//! # }
//! # #[cfg(feature = "testutils")]
//! # fn main() {
//! let env = Env::default();
//! env.cost_estimate().disable_resource_limits(); // Disable resource limit
//!
//! let contract_id = env.register(Contract, ());
//! let client = ContractClient::new(&env, &contract_id);
//! client.execute(); // Won't panic even if limits exceeded
//! }
//! # #[cfg(not(feature = "testutils"))]
//! # fn main() { }
//! ```
//!
//! ## Custom Resource Limits
//!
//! Custom resource limits can be enforced using [`CostEstimate::enforce_resource_limits()`]:
//!
//! ```
//! use soroban_sdk::{contract, contractimpl, Env};
//! use soroban_sdk::testutils::cost_estimate::NetworkInvocationResourceLimits;
//! use soroban_env_host::InvocationResourceLimits;
//!
//! #[contract]
//! pub struct Contract;
//!
//! #[contractimpl]
//! impl Contract {
//! pub fn execute() {
//! // ... code
//! }
//! }
//!
//! #[test]
//! fn test() {
//! # }
//! # #[cfg(feature = "testutils")]
//! # fn main() {
//! let env = Env::default();
//!
//! // Use custom limits (this example uses mainnet limits as a base)
//! let mut limits = InvocationResourceLimits::mainnet();
//! limits.instructions = 100_000_000; // Reduce instruction limit
//! env.cost_estimate().enforce_resource_limits(limits);
//!
//! let contract_id = env.register(Contract, ());
//! let client = ContractClient::new(&env, &contract_id);
//! client.execute(); // Uses the custom limits
//! }
//! # #[cfg(not(feature = "testutils"))]
//! # fn main() { }
//! ```
//!
//! ## Mainnet Resource Limits
//!
//! The [`NetworkInvocationResourceLimits`] trait provides the `mainnet()` method on
//! [`InvocationResourceLimits`] to get the current mainnet limits:
//!
//! - Instructions: 600,000,000
//! - Memory: 41,943,040 bytes
//! - Disk read entries: 100
//! - Write entries: 50
//! - Ledger entries: 100
//! - Disk read bytes: 200,000
//! - Write bytes: 132,096
//! - Contract events size: 16,384 bytes
//! - Max contract data key size: 250 bytes
//! - Max contract data entry size: 65,536 bytes
//! - Max contract code entry size: 131,072 bytes
//!
//! Note: These values are not pulled dynamically. The SDK will be updated from time-to-time to
//! pick up changes to mainnet limits. These changes may occur in any major, minor, or patch
//! release.
//!
//! [`Env::default()`]: crate::Env::default
//! [`CostEstimate::disable_resource_limits()`]: crate::testutils::cost_estimate::CostEstimate::disable_resource_limits
//! [`CostEstimate::enforce_resource_limits()`]: crate::testutils::cost_estimate::CostEstimate::enforce_resource_limits
//! [`InvocationResourceLimits`]: soroban_env_host::InvocationResourceLimits
//! [`NetworkInvocationResourceLimits`]: crate::testutils::cost_estimate::NetworkInvocationResourceLimits