diff --git a/Cargo.lock b/Cargo.lock index 59c6bf04b..432776e5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -462,6 +462,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "dissimilar" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59f8e79d1fbf76bdfbde321e902714bf6c49df88a7dda6fc682fc2979226962d" + [[package]] name = "downcast-rs" version = "1.2.1" @@ -558,6 +564,16 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" +[[package]] +name = "expect-test" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e0be0a561335815e06dab7c62e50353134c796e7a6155402a64bcff66b6a5e0" +dependencies = [ + "dissimilar", + "once_cell", +] + [[package]] name = "fastrand" version = "2.1.1" @@ -1336,6 +1352,7 @@ dependencies = [ "curve25519-dalek", "derive_arbitrary", "ed25519-dalek", + "expect-test", "hex", "libfuzzer-sys", "proptest", diff --git a/soroban-sdk/Cargo.toml b/soroban-sdk/Cargo.toml index dd530a67b..752fbf326 100644 --- a/soroban-sdk/Cargo.toml +++ b/soroban-sdk/Cargo.toml @@ -53,6 +53,7 @@ derive_arbitrary = { version = "~1.3.0" } proptest = "1.2.0" proptest-arbitrary-interop = "0.1.0" libfuzzer-sys = "0.4.7" +expect-test = "1.4.1" [features] alloc = [] diff --git a/soroban-sdk/src/env.rs b/soroban-sdk/src/env.rs index 8903134af..aabfb7c7f 100644 --- a/soroban-sdk/src/env.rs +++ b/soroban-sdk/src/env.rs @@ -449,6 +449,8 @@ impl Env { } } +#[cfg(any(test, feature = "testutils"))] +use crate::testutils::cost_estimate::CostEstimate; #[cfg(any(test, feature = "testutils"))] use crate::{ auth, @@ -560,6 +562,7 @@ impl Env { } }))) .unwrap(); + env_impl.enable_invocation_metering(); let env = Env { env_impl, @@ -576,6 +579,31 @@ impl Env { env } + /// Returns the resources metered during the last top level contract + /// invocation. + /// + /// In order to get non-`None` results, `enable_invocation_metering` has to + /// be called and at least one invocation has to happen after that. + /// + /// Take the return value with a grain of salt. The returned resources mostly + /// correspond only to the operations that have happened during the host + /// invocation, i.e. this won't try to simulate the work that happens in + /// production scenarios (e.g. certain XDR rountrips). This also doesn't try + /// to model resources related to the transaction size. + /// + /// The returned value is as useful as the preceding setup, e.g. if a test + /// contract is used instead of a Wasm contract, all the costs related to + /// VM instantiation and execution, as well as Wasm reads/rent bumps will be + /// missed. + /// + /// While the resource metering may be useful for contract optimization, + /// keep in mind that resource and fee estimation may be imprecise. Use + /// simulation with RPC in order to get the exact resources for submitting + /// the transactions to the network. + pub fn cost_estimate(&self) -> CostEstimate { + CostEstimate::new(self.clone()) + } + /// Register a contract with the [Env] for testing. /// /// Pass the contract type when the contract is defined in the current crate @@ -1611,6 +1639,7 @@ impl Env { } /// Get the budget that tracks the resources consumed for the environment. + #[deprecated(note = "use cost_estimate().detailed_metering()")] pub fn budget(&self) -> Budget { Budget::new(self.env_impl.budget_cloned()) } diff --git a/soroban-sdk/src/tests.rs b/soroban-sdk/src/tests.rs index 054c58672..2a935f2e3 100644 --- a/soroban-sdk/src/tests.rs +++ b/soroban-sdk/src/tests.rs @@ -2,7 +2,6 @@ mod address; mod auth; -mod budget; mod bytes_alloc_vec; mod bytes_buffer; mod contract_add_i32; @@ -25,6 +24,7 @@ mod contract_udt_struct; mod contract_udt_struct_tuple; mod contractimport; mod contractimport_with_error; +mod cost_estimate; mod crypto_bls12_381; mod crypto_ed25519; mod crypto_keccak256; diff --git a/soroban-sdk/src/tests/budget.rs b/soroban-sdk/src/tests/budget.rs deleted file mode 100644 index 8391b8990..000000000 --- a/soroban-sdk/src/tests/budget.rs +++ /dev/null @@ -1,38 +0,0 @@ -use crate as soroban_sdk; -use soroban_env_host::budget::CostTracker; -use soroban_sdk::{contract, contractimpl, map, xdr::ContractCostType, Env, Map}; - -#[contract] -pub struct Contract; - -#[contractimpl] -impl Contract { - pub fn add(e: Env) -> Map { - let mut map = Map::new(&e); - map.set(1, 10); - map.set(2, 20); - map - } -} - -#[test] -fn test_budget() { - let e = Env::default(); - let contract_id = e.register(Contract, ()); - let client = ContractClient::new(&e, &contract_id); - - e.budget().reset_default(); - let b = client.add(); - e.budget().print(); - - assert_eq!( - e.budget().tracker(ContractCostType::VisitObject), - CostTracker { - iterations: 13, - inputs: None, - cpu: 793, - mem: 0, - } - ); - assert_eq!(b, map![&e, (1, 10), (2, 20)]); -} diff --git a/soroban-sdk/src/tests/cost_estimate.rs b/soroban-sdk/src/tests/cost_estimate.rs new file mode 100644 index 000000000..58da38a42 --- /dev/null +++ b/soroban-sdk/src/tests/cost_estimate.rs @@ -0,0 +1,263 @@ +use crate as soroban_sdk; +use expect_test::expect; +use soroban_sdk::Env; +use soroban_sdk_macros::symbol_short; +use stellar_xdr::curr::ContractCostType; + +mod contract_data { + use crate as soroban_sdk; + soroban_sdk::contractimport!(file = "test_wasms/test_contract_data.wasm"); +} + +// Update the test data in this test via running it with `UPDATE_EXPECT=1`. +#[test] +fn test_cost_estimate_with_storage() { + let e = Env::default(); + + let contract_id = e.register(contract_data::WASM, ()); + let client = contract_data::Client::new(&e, &contract_id); + + // Write a single new entry to the storage. + client.put(&symbol_short!("k1"), &symbol_short!("v1")); + expect![[r#" + InvocationResources { + instructions: 455853, + mem_bytes: 1162241, + read_entries: 2, + write_entries: 1, + read_bytes: 1028, + write_bytes: 80, + contract_events_size_bytes: 0, + persistent_rent_ledger_bytes: 327600, + persistent_entry_rent_bumps: 1, + temporary_rent_ledger_bytes: 0, + temporary_entry_rent_bumps: 0, + }"#]] + .assert_eq(format!("{:#?}", e.cost_estimate().resources()).as_str()); + expect![[r#" + FeeEstimate { + total: 45010, + instructions: 1140, + read_entries: 18750, + write_entries: 10000, + read_bytes: 1793, + write_bytes: 938, + contract_events: 0, + persistent_entry_rent: 12389, + temporary_entry_rent: 0, + }"#]] + .assert_eq(format!("{:#?}", e.cost_estimate().fee()).as_str()); + + // Read an entry from the storage. Now there are no write-related resources + // and fees consumed. + assert_eq!(client.get(&symbol_short!("k1")), Some(symbol_short!("v1"))); + expect![[r#" + InvocationResources { + instructions: 454080, + mem_bytes: 1161338, + read_entries: 3, + write_entries: 0, + read_bytes: 1108, + write_bytes: 0, + contract_events_size_bytes: 0, + persistent_rent_ledger_bytes: 0, + persistent_entry_rent_bumps: 0, + temporary_rent_ledger_bytes: 0, + temporary_entry_rent_bumps: 0, + }"#]] + .assert_eq(format!("{:#?}", e.cost_estimate().resources()).as_str()); + expect![[r#" + FeeEstimate { + total: 21819, + instructions: 1136, + read_entries: 18750, + write_entries: 0, + read_bytes: 1933, + write_bytes: 0, + contract_events: 0, + persistent_entry_rent: 0, + temporary_entry_rent: 0, + }"#]] + .assert_eq(format!("{:#?}", e.cost_estimate().fee()).as_str()); + + // Delete the entry. There is 1 write_entry, but 0 write_bytes and no rent + // as this is deletion. + client.del(&symbol_short!("k1")); + expect![[r#" + InvocationResources { + instructions: 452458, + mem_bytes: 1161558, + read_entries: 2, + write_entries: 1, + read_bytes: 1108, + write_bytes: 0, + contract_events_size_bytes: 0, + persistent_rent_ledger_bytes: 0, + persistent_entry_rent_bumps: 0, + temporary_rent_ledger_bytes: 0, + temporary_entry_rent_bumps: 0, + }"#]] + .assert_eq(format!("{:#?}", e.cost_estimate().resources()).as_str()); + expect![[r#" + FeeEstimate { + total: 31815, + instructions: 1132, + read_entries: 18750, + write_entries: 10000, + read_bytes: 1933, + write_bytes: 0, + contract_events: 0, + persistent_entry_rent: 0, + temporary_entry_rent: 0, + }"#]] + .assert_eq(format!("{:#?}", e.cost_estimate().fee()).as_str()); + + // Read an entry again, now it no longer exists, so there is less read_bytes + // than in the case when the entry is present. + assert_eq!(client.get(&symbol_short!("k1")), None); + expect![[r#" + InvocationResources { + instructions: 452445, + mem_bytes: 1161202, + read_entries: 3, + write_entries: 0, + read_bytes: 1028, + write_bytes: 0, + contract_events_size_bytes: 0, + persistent_rent_ledger_bytes: 0, + persistent_entry_rent_bumps: 0, + temporary_rent_ledger_bytes: 0, + temporary_entry_rent_bumps: 0, + }"#]] + .assert_eq(format!("{:#?}", e.cost_estimate().resources()).as_str()); + expect![[r#" + FeeEstimate { + total: 21675, + instructions: 1132, + read_entries: 18750, + write_entries: 0, + read_bytes: 1793, + write_bytes: 0, + contract_events: 0, + persistent_entry_rent: 0, + temporary_entry_rent: 0, + }"#]] + .assert_eq(format!("{:#?}", e.cost_estimate().fee()).as_str()); +} + +#[test] +fn test_cost_estimate_budget() { + let e = Env::default(); + + let contract_id = e.register(contract_data::WASM, ()); + let client = contract_data::Client::new(&e, &contract_id); + + client.put(&symbol_short!("k1"), &symbol_short!("v1")); + + // Budget breakdown corresponds to the last invocation only. + expect![[r#" + =============================================================================================================================================================================== + Cpu limit: 100000000; used: 455853 + Mem limit: 41943040; used: 1162241 + =============================================================================================================================================================================== + CostType iterations input cpu_insns mem_bytes const_term_cpu lin_term_cpu const_term_mem lin_term_mem + WasmInsnExec 284 None 1136 0 4 0 0 0 + MemAlloc 27 Some(1052425) 143269 1052857 434 16 16 128 + MemCpy 95 Some(9665) 5186 0 42 16 0 0 + MemCmp 43 Some(1049) 2012 0 44 16 0 0 + DispatchHostFunction 1 None 310 0 310 0 0 0 + VisitObject 2 None 122 0 61 0 0 0 + ValSer 0 Some(0) 0 0 230 29 242 384 + ValDeser 0 Some(0) 0 0 59052 4001 0 384 + ComputeSha256Hash 1 Some(0) 3738 0 3738 7012 0 0 + ComputeEd25519PubKey 0 None 0 0 40253 0 0 0 + VerifyEd25519Sig 0 Some(0) 0 0 377524 4068 0 0 + VmInstantiation 0 Some(0) 0 0 451626 45405 130065 5064 + VmCachedInstantiation 0 Some(0) 0 0 41142 634 69472 1217 + InvokeVmFunction 1 None 1948 14 1948 0 14 0 + ComputeKeccak256Hash 0 Some(0) 0 0 3766 5969 0 0 + DecodeEcdsaCurve256Sig 0 None 0 0 710 0 0 0 + RecoverEcdsaSecp256k1Key 0 None 0 0 2315295 0 181 0 + Int256AddSub 0 None 0 0 4404 0 99 0 + Int256Mul 0 None 0 0 4947 0 99 0 + Int256Div 0 None 0 0 4911 0 99 0 + Int256Pow 0 None 0 0 4286 0 99 0 + Int256Shift 0 None 0 0 913 0 99 0 + ChaCha20DrawBytes 0 Some(0) 0 0 1058 501 0 0 + ParseWasmInstructions 1 Some(137) 100273 24475 73077 25410 17564 6457 + ParseWasmFunctions 1 Some(5) 21123 1854 0 540752 0 47464 + ParseWasmGlobals 1 Some(3) 4133 314 0 176363 0 13420 + ParseWasmTableEntries 1 Some(0) 0 0 0 29989 0 6285 + ParseWasmTypes 1 Some(5) 41462 2526 0 1061449 0 64670 + ParseWasmDataSegments 1 Some(0) 0 0 0 237336 0 29074 + ParseWasmElemSegments 1 Some(0) 0 0 0 328476 0 48095 + ParseWasmImports 1 Some(4) 21932 3225 0 701845 0 103229 + ParseWasmExports 1 Some(7) 23481 1990 0 429383 0 36394 + ParseWasmDataSegmentBytes 1 Some(0) 0 0 0 28 0 257 + InstantiateWasmInstructions 1 None 43030 70704 43030 0 70704 0 + InstantiateWasmFunctions 1 Some(5) 295 570 0 7556 0 14613 + InstantiateWasmGlobals 1 Some(3) 251 160 0 10711 0 6833 + InstantiateWasmTableEntries 1 Some(0) 0 0 0 3300 0 1025 + InstantiateWasmTypes 1 None 0 0 0 0 0 0 + InstantiateWasmDataSegments 1 Some(0) 0 0 0 23038 0 129632 + InstantiateWasmElemSegments 1 Some(0) 0 0 0 42488 0 13665 + InstantiateWasmImports 1 Some(4) 25905 3051 0 828974 0 97637 + InstantiateWasmExports 1 Some(7) 16247 501 0 297100 0 9176 + InstantiateWasmDataSegmentBytes 1 Some(0) 0 0 0 14 0 126 + Sec1DecodePointUncompressed 0 None 0 0 1882 0 0 0 + VerifyEcdsaSecp256r1Sig 0 None 0 0 3000906 0 0 0 + Bls12381EncodeFp 0 None 0 0 661 0 0 0 + Bls12381DecodeFp 0 None 0 0 985 0 0 0 + Bls12381G1CheckPointOnCurve 0 None 0 0 1934 0 0 0 + Bls12381G1CheckPointInSubgroup 0 None 0 0 730510 0 0 0 + Bls12381G2CheckPointOnCurve 0 None 0 0 5921 0 0 0 + Bls12381G2CheckPointInSubgroup 0 None 0 0 1057822 0 0 0 + Bls12381G1ProjectiveToAffine 0 None 0 0 92642 0 0 0 + Bls12381G2ProjectiveToAffine 0 None 0 0 100742 0 0 0 + Bls12381G1Add 0 None 0 0 7689 0 0 0 + Bls12381G1Mul 0 None 0 0 2458985 0 0 0 + Bls12381G1Msm 0 Some(0) 0 0 2426722 96397671 109494 354667 + Bls12381MapFpToG1 0 None 0 0 1541554 0 5552 0 + Bls12381HashToG1 0 Some(0) 0 0 3211191 6713 9424 0 + Bls12381G2Add 0 None 0 0 25207 0 0 0 + Bls12381G2Mul 0 None 0 0 7873219 0 0 0 + Bls12381G2Msm 0 Some(0) 0 0 8035968 309667335 219654 354667 + Bls12381MapFp2ToG2 0 None 0 0 2420202 0 3344 0 + Bls12381HashToG2 0 Some(0) 0 0 7050564 6797 6816 0 + Bls12381Pairing 0 Some(0) 0 0 10558948 632860943 2204 9340474 + Bls12381FrFromU256 0 None 0 0 1994 0 0 0 + Bls12381FrToU256 0 None 0 0 1155 0 248 0 + Bls12381FrAddSub 0 None 0 0 74 0 0 0 + Bls12381FrMul 0 None 0 0 332 0 0 0 + Bls12381FrPow 0 Some(0) 0 0 691 74558 0 128 + Bls12381FrInv 0 None 0 0 35421 0 0 0 + =============================================================================================================================================================================== + Internal details (diagnostics info, does not affect fees) + Total # times meter was called: 192 + Shadow cpu limit: 100000000; used: 34332 + Shadow mem limit: 41943040; used: 27725 + =============================================================================================================================================================================== + + + "#]] + .assert_eq(format!("{:#?}", e.cost_estimate().budget()).as_str()); + + // Data for a specific cost type (one row in the budget table above) can be + // obtained as well via `tracker` function. + expect![[r#" + CostTracker { + iterations: 284, + inputs: None, + cpu: 1136, + mem: 0, + }"#]] + .assert_eq( + format!( + "{:#?}", + e.cost_estimate() + .budget() + .tracker(ContractCostType::WasmInsnExec) + ) + .as_str(), + ); +} diff --git a/soroban-sdk/src/tests/env.rs b/soroban-sdk/src/tests/env.rs index d5adb0f07..192a4f14a 100644 --- a/soroban-sdk/src/tests/env.rs +++ b/soroban-sdk/src/tests/env.rs @@ -52,6 +52,10 @@ fn default_and_from_snapshot_same_settings() { c1client.test(); c2client.test(); + let logs1 = env1.logs().all(); + let logs2 = env2.logs().all(); + assert_eq!(logs1, &["[Diagnostic Event] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, topics:[log], data:\"test\""]); + assert_eq!(logs2, &["[Diagnostic Event] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, topics:[log], data:\"test\""]); let c1addr2 = Address::generate(&env1); let c2addr2 = Address::generate(&env2); @@ -71,11 +75,6 @@ fn default_and_from_snapshot_same_settings() { ScErrorCode::InvalidAction ))) ); - - let logs1 = env1.logs().all(); - let logs2 = env2.logs().all(); - assert_eq!(logs1, &["[Diagnostic Event] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, topics:[log], data:\"test\""]); - assert_eq!(logs2, &["[Diagnostic Event] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, topics:[log], data:\"test\""]); } #[test] diff --git a/soroban-sdk/src/tests/proptest_scval_cmp.rs b/soroban-sdk/src/tests/proptest_scval_cmp.rs index fb18ab391..41cc64395 100644 --- a/soroban-sdk/src/tests/proptest_scval_cmp.rs +++ b/soroban-sdk/src/tests/proptest_scval_cmp.rs @@ -70,7 +70,7 @@ proptest! { prop_assert_eq!(scval_partial_eq, rawval_cmp_is_eq); // Compare for Budget - let budget = env.budget().0; + let budget = env.cost_estimate().budget().0; let scval_budget_cmp = budget.compare(&scval_1, &scval_2).expect("cmp"); if scval_budget_cmp != scval_cmp { diff --git a/soroban-sdk/src/tests/proptest_val_cmp.rs b/soroban-sdk/src/tests/proptest_val_cmp.rs index 362b15133..aeb43e40e 100644 --- a/soroban-sdk/src/tests/proptest_val_cmp.rs +++ b/soroban-sdk/src/tests/proptest_val_cmp.rs @@ -20,7 +20,7 @@ proptest! { rawval_proto_2 in arb::<::Prototype>(), ) { let env = &Env::default(); - let budget = env.budget().0; + let budget = env.cost_estimate().budget().0; let rawval_1 = Val::from_val(env, &rawval_proto_1); let rawval_2 = Val::from_val(env, &rawval_proto_2); diff --git a/soroban-sdk/src/testutils.rs b/soroban-sdk/src/testutils.rs index 55ba0b221..0ebb8545c 100644 --- a/soroban-sdk/src/testutils.rs +++ b/soroban-sdk/src/testutils.rs @@ -18,6 +18,8 @@ use soroban_env_host::TryIntoVal; pub mod storage; +pub mod cost_estimate; + use crate::{xdr, ConstructorArgs, Env, Val, Vec}; use soroban_ledger_snapshot::LedgerSnapshot; @@ -312,9 +314,9 @@ pub mod budget { /// # #[cfg(feature = "testutils")] /// # fn main() { /// # let env = Env::default(); - /// env.budget().reset_default(); + /// env.cost_estimate().budget().reset_default(); /// // ... - /// println!("{}", env.budget()); + /// println!("{}", env.cost_estimate().budget()); /// # } /// # #[cfg(not(feature = "testutils"))] /// # fn main() { } diff --git a/soroban-sdk/src/testutils/cost_estimate.rs b/soroban-sdk/src/testutils/cost_estimate.rs new file mode 100644 index 000000000..bfc045c00 --- /dev/null +++ b/soroban-sdk/src/testutils/cost_estimate.rs @@ -0,0 +1,88 @@ +use soroban_env_host::{fees::FeeConfiguration, FeeEstimate, InvocationResources}; + +use crate::{testutils::budget::Budget, Env}; + +pub struct CostEstimate { + env: Env, +} + +impl CostEstimate { + pub(crate) fn new(env: Env) -> Self { + Self { env } + } + + /// Returns the resources metered during the last top level contract + /// invocation. + /// Take the return value with a grain of salt. The returned resources mostly + /// correspond only to the operations that have happened during the host + /// invocation, i.e. this won't try to simulate the work that happens in + /// production scenarios (e.g. certain XDR rountrips). This also doesn't try + /// to model resources related to the transaction size. + /// + /// The returned value is as useful as the preceding setup, e.g. if a test + /// contract is used instead of a Wasm contract, all the costs related to + /// VM instantiation and execution, as well as Wasm reads/rent bumps will be + /// missed. + pub fn resources(&self) -> InvocationResources { + if let Some(res) = self.env.host().get_last_invocation_resources() { + res + } else { + panic!("Invocation cost estimate is not available. Make sure invocation cost metering is enabled in the EnvTestConfig and this is called after an invocation.") + } + } + + /// Estimates the fee for the last invocation's resources, i.e. the + /// resources returned by `resources()`. + /// + /// The fees are computed using the snapshot of the Stellar Pubnet fees made + /// on 2024-12-11. + /// + /// Take the return value with a grain of salt as both the resource estimate + /// and the fee rates may be imprecise. + /// + /// The returned value is as useful as the preceding setup, e.g. if a test + /// contract is used instead of a Wasm contract, all the costs related to + /// VM instantiation and execution, as well as Wasm reads/rent bumps will be + /// missed. + pub fn fee(&self) -> FeeEstimate { + // This is a snapshot of the fees as of 2024-12-11. + let pubnet_fee_config = FeeConfiguration { + fee_per_instruction_increment: 25, + fee_per_read_entry: 6250, + fee_per_write_entry: 10000, + fee_per_read_1kb: 1786, + // This is a bit higher than the current network fee, it's an + // overestimate for the sake of providing a bit more conservative + // results in case if the state grows. + fee_per_write_1kb: 12000, + fee_per_historical_1kb: 16235, + fee_per_contract_event_1kb: 10000, + fee_per_transaction_size_1kb: 1624, + }; + let pubnet_persistent_rent_rate_denominator = 2103; + let pubnet_temp_rent_rate_denominator = 4206; + + self.resources().estimate_fees( + &pubnet_fee_config, + pubnet_persistent_rent_rate_denominator, + pubnet_temp_rent_rate_denominator, + ) + } + + /// Returns the budget object that provides the detailed CPU and memory + /// metering information recorded thus far. + /// + /// The budget metering resets before every top-level contract level + /// invocation. + /// + /// budget() may also be used to adjust the CPU and memory limits via the + /// `reset_` methods. + /// + /// Note, that unlike `resources()`/`fee()` this will always return some + /// value. If there was no contract call, then the resulting value will + /// correspond to metering any environment setup that has been made thus + /// far. + pub fn budget(&self) -> Budget { + Budget::new(self.env.host().budget_cloned()) + } +} diff --git a/soroban-sdk/test_snapshots/tests/budget/test_budget.1.json b/soroban-sdk/test_snapshots/tests/budget/test_budget.1.json deleted file mode 100644 index a90f00a84..000000000 --- a/soroban-sdk/test_snapshots/tests/budget/test_budget.1.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "generators": { - "address": 1, - "nonce": 0 - }, - "auth": [ - [], - [] - ], - "ledger": { - "protocol_version": 22, - "sequence_number": 0, - "timestamp": 0, - "network_id": "0000000000000000000000000000000000000000000000000000000000000000", - "base_reserve": 0, - "min_persistent_entry_ttl": 4096, - "min_temp_entry_ttl": 16, - "max_entry_ttl": 6312000, - "ledger_entries": [ - [ - { - "contract_data": { - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", - "key": "ledger_key_contract_instance", - "durability": "persistent" - } - }, - [ - { - "last_modified_ledger_seq": 0, - "data": { - "contract_data": { - "ext": "v0", - "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", - "key": "ledger_key_contract_instance", - "durability": "persistent", - "val": { - "contract_instance": { - "executable": { - "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - }, - "storage": null - } - } - } - }, - "ext": "v0" - }, - 4095 - ] - ], - [ - { - "contract_code": { - "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - } - }, - [ - { - "last_modified_ledger_seq": 0, - "data": { - "contract_code": { - "ext": "v0", - "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "code": "" - } - }, - "ext": "v0" - }, - 4095 - ] - ] - ] - }, - "events": [] -} \ No newline at end of file diff --git a/soroban-sdk/test_snapshots/tests/cost_estimate/test_cost_estimate_budget.1.json b/soroban-sdk/test_snapshots/tests/cost_estimate/test_cost_estimate_budget.1.json new file mode 100644 index 000000000..5b0b035b5 --- /dev/null +++ b/soroban-sdk/test_snapshots/tests/cost_estimate/test_cost_estimate_budget.1.json @@ -0,0 +1,156 @@ +{ + "generators": { + "address": 1, + "nonce": 0 + }, + "auth": [ + [] + ], + "ledger": { + "protocol_version": 22, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V", + "key": { + "symbol": "k1" + }, + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V", + "key": { + "symbol": "k1" + }, + "durability": "persistent", + "val": { + "symbol": "v1" + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_data": { + "contract": "CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "fd41d2f77920ca07b723e05f732a82db4c2f6459eb2be6b40c4f225434569550" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_code": { + "hash": "fd41d2f77920ca07b723e05f732a82db4c2f6459eb2be6b40c4f225434569550" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": { + "v1": { + "ext": "v0", + "cost_inputs": { + "ext": "v0", + "n_instructions": 137, + "n_functions": 5, + "n_globals": 3, + "n_table_entries": 0, + "n_types": 5, + "n_data_segments": 0, + "n_elem_segments": 0, + "n_imports": 4, + "n_exports": 7, + "n_data_segment_bytes": 0 + } + } + }, + "hash": "fd41d2f77920ca07b723e05f732a82db4c2f6459eb2be6b40c4f225434569550", + "code": "0061736d01000000011b0560037e7e7e017e60027e7e017e60027f7e0060017e017e600000021904016c015f0000016c01300001016c01310001016c01320001030605010203030405030100100619037f01418080c0000b7f00418080c0000b7f00418080c0000b073b07066d656d6f727902000370757400040367657400060364656c0007015f00080a5f5f646174615f656e6403010b5f5f686561705f6261736503020ad502056601017f23808080800041206b2202248080808000200241106a200010858080800002402002290310a70d0020022903182100200220011085808080002002290300a70d002000200229030842011080808080001a200241206a24808080800042020f0b00000b2401017f2000200137030820002001a741ff01712202410e47200241ca004771ad3703000b7b02017f017e23808080800041206b2201248080808000200141106a200010858080800002402001290310a70d004202210002402001290318220242011081808080004201520d002001200242011082808080001085808080002001290300a70d01200129030821000b200141206a24808080800020000f0b00000b4801017f23808080800041106b22012480808080002001200010858080800002402001290300a7450d0000000b200129030842011083808080001a200141106a24808080800042020b02000b009f010e636f6e7472616374737065637630000000000000000000000003707574000000000200000000000000036b65790000000011000000000000000376616c000000001100000000000000000000000000000003676574000000000100000000000000036b6579000000001100000001000003e80000001100000000000000000000000364656c000000000100000000000000036b6579000000001100000000001e11636f6e7472616374656e766d657461763000000000000000160000000000770e636f6e74726163746d65746176300000000000000005727376657200000000000006312e38312e3000000000000000000008727373646b7665720000003532322e302e3223646665383939626331326332323937353531303633653330313531666636353466393762383265382d6469727479000000" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/soroban-sdk/test_snapshots/tests/cost_estimate/test_cost_estimate_with_storage.1.json b/soroban-sdk/test_snapshots/tests/cost_estimate/test_cost_estimate_with_storage.1.json new file mode 100644 index 000000000..ee238468b --- /dev/null +++ b/soroban-sdk/test_snapshots/tests/cost_estimate/test_cost_estimate_with_storage.1.json @@ -0,0 +1,128 @@ +{ + "generators": { + "address": 1, + "nonce": 0 + }, + "auth": [ + [], + [], + [], + [] + ], + "ledger": { + "protocol_version": 22, + "sequence_number": 0, + "timestamp": 0, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + [ + { + "contract_data": { + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": 801925984706572462 + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + 6311999 + ] + ], + [ + { + "contract_data": { + "contract": "CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V", + "key": "ledger_key_contract_instance", + "durability": "persistent" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "fd41d2f77920ca07b723e05f732a82db4c2f6459eb2be6b40c4f225434569550" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + 4095 + ] + ], + [ + { + "contract_code": { + "hash": "fd41d2f77920ca07b723e05f732a82db4c2f6459eb2be6b40c4f225434569550" + } + }, + [ + { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": { + "v1": { + "ext": "v0", + "cost_inputs": { + "ext": "v0", + "n_instructions": 137, + "n_functions": 5, + "n_globals": 3, + "n_table_entries": 0, + "n_types": 5, + "n_data_segments": 0, + "n_elem_segments": 0, + "n_imports": 4, + "n_exports": 7, + "n_data_segment_bytes": 0 + } + } + }, + "hash": "fd41d2f77920ca07b723e05f732a82db4c2f6459eb2be6b40c4f225434569550", + "code": "0061736d01000000011b0560037e7e7e017e60027e7e017e60027f7e0060017e017e600000021904016c015f0000016c01300001016c01310001016c01320001030605010203030405030100100619037f01418080c0000b7f00418080c0000b7f00418080c0000b073b07066d656d6f727902000370757400040367657400060364656c0007015f00080a5f5f646174615f656e6403010b5f5f686561705f6261736503020ad502056601017f23808080800041206b2202248080808000200241106a200010858080800002402002290310a70d0020022903182100200220011085808080002002290300a70d002000200229030842011080808080001a200241206a24808080800042020f0b00000b2401017f2000200137030820002001a741ff01712202410e47200241ca004771ad3703000b7b02017f017e23808080800041206b2201248080808000200141106a200010858080800002402001290310a70d004202210002402001290318220242011081808080004201520d002001200242011082808080001085808080002001290300a70d01200129030821000b200141206a24808080800020000f0b00000b4801017f23808080800041106b22012480808080002001200010858080800002402001290300a7450d0000000b200129030842011083808080001a200141106a24808080800042020b02000b009f010e636f6e7472616374737065637630000000000000000000000003707574000000000200000000000000036b65790000000011000000000000000376616c000000001100000000000000000000000000000003676574000000000100000000000000036b6579000000001100000001000003e80000001100000000000000000000000364656c000000000100000000000000036b6579000000001100000000001e11636f6e7472616374656e766d657461763000000000000000160000000000770e636f6e74726163746d65746176300000000000000005727376657200000000000006312e38312e3000000000000000000008727373646b7665720000003532322e302e3223646665383939626331326332323937353531303633653330313531666636353466393762383265382d6469727479000000" + } + }, + "ext": "v0" + }, + 4095 + ] + ] + ] + }, + "events": [] +} \ No newline at end of file diff --git a/soroban-sdk/test_snapshots/tests/token_client/test_mock_all_auth.1.json b/soroban-sdk/test_snapshots/tests/token_client/test_mock_all_auth.1.json index 245d5fdc9..3e2189578 100644 --- a/soroban-sdk/test_snapshots/tests/token_client/test_mock_all_auth.1.json +++ b/soroban-sdk/test_snapshots/tests/token_client/test_mock_all_auth.1.json @@ -470,71 +470,5 @@ ] ] }, - "events": [ - { - "event": { - "ext": "v0", - "contract_id": "48f1b6b8bc0d60f7140dd49b6120fbaf3cdbab2adaeea631313d9f0bae9532f1", - "type_": "contract", - "body": { - "v0": { - "topics": [ - { - "symbol": "set_admin" - }, - { - "address": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" - }, - { - "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" - } - ], - "data": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" - } - } - } - }, - "failed_call": false - }, - { - "event": { - "ext": "v0", - "contract_id": "48f1b6b8bc0d60f7140dd49b6120fbaf3cdbab2adaeea631313d9f0bae9532f1", - "type_": "contract", - "body": { - "v0": { - "topics": [ - { - "symbol": "approve" - }, - { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" - }, - { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" - }, - { - "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" - } - ], - "data": { - "vec": [ - { - "i128": { - "hi": 0, - "lo": 20 - } - }, - { - "u32": 200 - } - ] - } - } - } - }, - "failed_call": false - } - ] + "events": [] } \ No newline at end of file diff --git a/soroban-sdk/test_snapshots/tests/token_client/test_mock_auth.1.json b/soroban-sdk/test_snapshots/tests/token_client/test_mock_auth.1.json index 523006dfe..f01fdc763 100644 --- a/soroban-sdk/test_snapshots/tests/token_client/test_mock_auth.1.json +++ b/soroban-sdk/test_snapshots/tests/token_client/test_mock_auth.1.json @@ -502,71 +502,5 @@ ] ] }, - "events": [ - { - "event": { - "ext": "v0", - "contract_id": "48f1b6b8bc0d60f7140dd49b6120fbaf3cdbab2adaeea631313d9f0bae9532f1", - "type_": "contract", - "body": { - "v0": { - "topics": [ - { - "symbol": "set_admin" - }, - { - "address": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" - }, - { - "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" - } - ], - "data": { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" - } - } - } - }, - "failed_call": false - }, - { - "event": { - "ext": "v0", - "contract_id": "48f1b6b8bc0d60f7140dd49b6120fbaf3cdbab2adaeea631313d9f0bae9532f1", - "type_": "contract", - "body": { - "v0": { - "topics": [ - { - "symbol": "approve" - }, - { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4" - }, - { - "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" - }, - { - "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWF" - } - ], - "data": { - "vec": [ - { - "i128": { - "hi": 0, - "lo": 20 - } - }, - { - "u32": 200 - } - ] - } - } - } - }, - "failed_call": false - } - ] + "events": [] } \ No newline at end of file diff --git a/soroban-sdk/test_wasms/README.md b/soroban-sdk/test_wasms/README.md new file mode 100644 index 000000000..0e8b3a00c --- /dev/null +++ b/soroban-sdk/test_wasms/README.md @@ -0,0 +1,6 @@ +# test_wasms + +Files contained in this directory are used in a few SDK tests that are sensitive +to Wasm content changes. + +`test_contract_data.wasm` is a build of `tests/contract_data` test contract. diff --git a/soroban-sdk/test_wasms/test_contract_data.wasm b/soroban-sdk/test_wasms/test_contract_data.wasm new file mode 100644 index 000000000..b58060978 Binary files /dev/null and b/soroban-sdk/test_wasms/test_contract_data.wasm differ