diff --git a/soroban-env-host/src/test/stellar_asset_contract.rs b/soroban-env-host/src/test/stellar_asset_contract.rs index 8502778a6..0c637dd05 100644 --- a/soroban-env-host/src/test/stellar_asset_contract.rs +++ b/soroban-env-host/src/test/stellar_asset_contract.rs @@ -22,8 +22,9 @@ use crate::{ use ed25519_dalek::SigningKey; use soroban_env_common::{ xdr::{ - self, AccountFlags, ContractExecutable, InvokeContractArgs, ScAddress, ScContractInstance, - ScSymbol, ScVal, SorobanAuthorizedFunction, SorobanAuthorizedInvocation, + self, AccountFlags, ContractEventType, ContractExecutable, InvokeContractArgs, ScAddress, + ScContractInstance, ScSymbol, ScVal, SorobanAuthorizedFunction, + SorobanAuthorizedInvocation, }, xdr::{ AccountId, AlphaNum12, AlphaNum4, Asset, AssetCode12, AssetCode4, Hash, LedgerEntryData, @@ -33,6 +34,7 @@ use soroban_env_common::{ EnvBase, Val, }; use soroban_env_common::{Env, Symbol, TryFromVal, TryIntoVal}; +use soroban_test_wasms::{ERR, INVOKE_CONTRACT}; use stellar_strkey::ed25519; use crate::builtin_contracts::base_types::BytesN; @@ -421,7 +423,10 @@ fn test_asset_init(asset_code: &[u8]) { assert_eq!(contract.decimals().unwrap(), 7); let name = contract.name().unwrap().to_string(); - let mut expected = String::from_utf8(asset_code.to_vec()).unwrap(); + let mut expected = String::from_utf8(asset_code.to_vec()) + .unwrap() + .trim_matches(char::from(0)) + .to_string(); expected.push(':'); let k = ed25519::PublicKey(test.issuer_key.verifying_key().to_bytes()); expected.push_str(k.to_string().as_str()); @@ -449,6 +454,16 @@ fn test_asset12_smart_init() { ]); } +#[test] +fn test_asset4_smart_leading_zero_init() { + test_asset_init(&[b'z', b'a', 0, 0]); +} + +#[test] +fn test_asset12_smart_leading_zero_init() { + test_asset_init(&[65, 76, b'a', b'b', b'a', b'b', b'c', b'a', b'b', b'a', 0, 0]); +} + #[test] fn test_zero_amounts() { let test = StellarAssetContractTest::setup(); @@ -3007,3 +3022,71 @@ fn test_recording_auth_for_stellar_asset_contract() { )] ); } + +#[test] +fn verify_nested_try_call_rollback() -> Result<(), HostError> { + // This test calls "invoke" in the ivocation contract, which then dispatches a call + // to "fail_after_updates". "fail_after_updates" emits an event, saves data, and does a + // SAC token transfer before emitting an error. + + let test = StellarAssetContractTest::setup(); + + let invoke_id_obj = test.host.register_test_contract_wasm(INVOKE_CONTRACT); + let err_id_obj = test.host.register_test_contract_wasm(ERR); + let err_address = Address::try_from_val(&test.host, &err_id_obj)?; + + let admin = TestSigner::account(&test.issuer_key); + let contract = test.default_stellar_asset_contract(); + + contract + .mint(&admin, err_address.clone(), 100_000_000) + .unwrap(); + + test.host.call( + invoke_id_obj, + Symbol::try_from_small_str("invoke")?, + host_vec![ + &test.host, + err_id_obj, + Symbol::try_from_val(&test.host, &"fail_after_updates").unwrap(), + contract.address.as_object() + ] + .into(), + )?; + + assert_eq!(contract.balance(err_address.clone()).unwrap(), 100_000_000); + assert_eq!(contract.balance(contract.address.clone()).unwrap(), 0); + + assert_eq!( + bool::try_from_val( + &test.host, + &test.host.call( + err_id_obj, + Symbol::try_from_val(&test.host, &"storage_updated")?, + host_vec![&test.host].into(), + )? + )?, + false + ); + + let events = test.host.get_events()?.0; + + // Make sure the event emitted in "fail_after_updates" is marked as failed + assert!( + events + .iter() + .find(|e| { + if e.event.type_ == ContractEventType::Contract && e.event.contract_id.is_some() { + let address = ScAddress::Contract(e.event.contract_id.clone().unwrap()); + let id = test.host.add_host_object(address).unwrap(); + test.host.obj_cmp(err_id_obj.to_val(), id.to_val()).unwrap() == 0 + } else { + false + } + }) + .unwrap() + .failed_call + ); + + Ok(()) +} diff --git a/soroban-test-wasms/wasm-workspace/err/src/lib.rs b/soroban-test-wasms/wasm-workspace/err/src/lib.rs index 39cf9529d..b1a77e861 100644 --- a/soroban-test-wasms/wasm-workspace/err/src/lib.rs +++ b/soroban-test-wasms/wasm-workspace/err/src/lib.rs @@ -1,5 +1,5 @@ #![no_std] -use soroban_sdk::{contract, contractimpl, contracterror, Val, Error}; +use soroban_sdk::{contract, contractimpl, contracterror, Val, Error, Env, Symbol, Address, symbol_short, token}; #[contract] pub struct Contract; @@ -47,4 +47,28 @@ impl Contract { Error::from_contract_error(12345).into() } + // This function is used in a try_call invocation test to make sure + // state is rolled back on failure. + pub fn fail_after_updates(env: Env, token: Address) -> Result<(), Error> { + env.events() + .publish((Symbol::new(&env, &"fail_after_updates"),), ()); + + env.storage().instance().set(&symbol_short!("key"), &symbol_short!("val")); + env.storage().persistent().set(&symbol_short!("key"), &symbol_short!("val")); + env.storage().temporary().set(&symbol_short!("key"), &symbol_short!("val")); + + let client = token::Client::new(&env, &token); + let contract_address = env.current_contract_address(); + // Transfer to the token address to make the test easier. + client.transfer(&contract_address, &token, &10); + + let e: Error = Error::from_contract_error(12345).into(); + Err(e) + } + + pub fn storage_updated(e: Env) -> bool { + e.storage().instance().has(&symbol_short!("key")) || + e.storage().persistent().has(&symbol_short!("key")) || + e.storage().temporary().has(&symbol_short!("key")) + } } diff --git a/soroban-test-wasms/wasm-workspace/invoke_contract/src/lib.rs b/soroban-test-wasms/wasm-workspace/invoke_contract/src/lib.rs index 3a8e6a5c0..92279d0f4 100644 --- a/soroban-test-wasms/wasm-workspace/invoke_contract/src/lib.rs +++ b/soroban-test-wasms/wasm-workspace/invoke_contract/src/lib.rs @@ -1,5 +1,5 @@ #![no_std] -use soroban_sdk::{contract, contractimpl, vec, Address, Env, IntoVal, symbol_short}; +use soroban_sdk::{contract, contractimpl, vec, Address, Env, IntoVal, Symbol, symbol_short, Error}; #[contract] pub struct Contract; @@ -20,4 +20,13 @@ impl Contract { vec![&env, x.into_val(&env), y.into_val(&env)], ) } + + // This is used through a single test case to test various rollback scenarios + pub fn invoke(env: Env, contract_id: Address, function_name: Symbol, token: Address) { + assert!(env.try_invoke_contract::<(), Error>( + &contract_id, + &function_name, + vec![&env, token.into_val(&env)], + ).is_err()); + } } diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/auth_test_contract.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/auth_test_contract.wasm index a6cffaa37..aac71402d 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/auth_test_contract.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/auth_test_contract.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/example_add_f32.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/example_add_f32.wasm index 2421e2a19..aefb5d7e2 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/example_add_f32.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/example_add_f32.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/example_add_i32.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/example_add_i32.wasm index 5c5623c06..c33f1d25c 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/example_add_i32.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/example_add_i32.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/example_alloc.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/example_alloc.wasm index e65fa8d9d..d0ebc6847 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/example_alloc.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/example_alloc.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/example_complex.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/example_complex.wasm index 20973bad0..100662db9 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/example_complex.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/example_complex.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/example_contract_data.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/example_contract_data.wasm index fbdc0437b..8f9b8738a 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/example_contract_data.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/example_contract_data.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/example_create_contract.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/example_create_contract.wasm index d31328ca1..45ae4f99b 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/example_create_contract.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/example_create_contract.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/example_err.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/example_err.wasm index 15e3978a6..c8626cd0e 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/example_err.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/example_err.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/example_fannkuch.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/example_fannkuch.wasm index e6077a090..939b52d7b 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/example_fannkuch.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/example_fannkuch.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/example_fib.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/example_fib.wasm index d9df187ee..a6cb79b14 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/example_fib.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/example_fib.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/example_hostile.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/example_hostile.wasm index 3d51e467c..64e8bfd36 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/example_hostile.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/example_hostile.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/example_invoke_contract.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/example_invoke_contract.wasm index 64731c053..9a6330121 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/example_invoke_contract.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/example_invoke_contract.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/example_linear_memory.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/example_linear_memory.wasm index f3e95fac1..a782cd98f 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/example_linear_memory.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/example_linear_memory.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/example_simple_account.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/example_simple_account.wasm index a0e025e13..42cb637f6 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/example_simple_account.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/example_simple_account.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/example_updateable_contract.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/example_updateable_contract.wasm index 5d6786340..703627b9b 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/example_updateable_contract.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/example_updateable_contract.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/example_vec.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/example_vec.wasm index 4f471980f..c59d1bb7f 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/example_vec.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/example_vec.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/soroban_write_upgrade_bytes_contract.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/soroban_write_upgrade_bytes_contract.wasm index 629d9da78..bbc8ac8e8 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/soroban_write_upgrade_bytes_contract.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/soroban_write_upgrade_bytes_contract.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/test_conditional_account.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/test_conditional_account.wasm index 149976628..d53ed0071 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/test_conditional_account.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/test_conditional_account.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/curr/test_delegated_account.wasm b/soroban-test-wasms/wasm-workspace/opt/curr/test_delegated_account.wasm index 62ced7b16..9804ba514 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/curr/test_delegated_account.wasm and b/soroban-test-wasms/wasm-workspace/opt/curr/test_delegated_account.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/auth_test_contract.wasm b/soroban-test-wasms/wasm-workspace/opt/next/auth_test_contract.wasm index b9068f688..f7bb95c75 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/auth_test_contract.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/auth_test_contract.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/example_add_f32.wasm b/soroban-test-wasms/wasm-workspace/opt/next/example_add_f32.wasm index 0ec922d71..34c1423f2 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/example_add_f32.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/example_add_f32.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/example_add_i32.wasm b/soroban-test-wasms/wasm-workspace/opt/next/example_add_i32.wasm index 1ec8cad48..d7d175423 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/example_add_i32.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/example_add_i32.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/example_alloc.wasm b/soroban-test-wasms/wasm-workspace/opt/next/example_alloc.wasm index a48ecb7bc..d819b7e8f 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/example_alloc.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/example_alloc.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/example_complex.wasm b/soroban-test-wasms/wasm-workspace/opt/next/example_complex.wasm index 6b5c52e4d..182016093 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/example_complex.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/example_complex.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/example_contract_data.wasm b/soroban-test-wasms/wasm-workspace/opt/next/example_contract_data.wasm index 9202f8af0..d5eecd304 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/example_contract_data.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/example_contract_data.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/example_create_contract.wasm b/soroban-test-wasms/wasm-workspace/opt/next/example_create_contract.wasm index 6dd9bbb40..90c725288 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/example_create_contract.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/example_create_contract.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/example_err.wasm b/soroban-test-wasms/wasm-workspace/opt/next/example_err.wasm index 214d93d26..35622eabc 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/example_err.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/example_err.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/example_fannkuch.wasm b/soroban-test-wasms/wasm-workspace/opt/next/example_fannkuch.wasm index 4430bc308..05968ca38 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/example_fannkuch.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/example_fannkuch.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/example_fib.wasm b/soroban-test-wasms/wasm-workspace/opt/next/example_fib.wasm index 6ba1f418a..861d45dc6 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/example_fib.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/example_fib.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/example_hostile.wasm b/soroban-test-wasms/wasm-workspace/opt/next/example_hostile.wasm index d52c3a472..78b60d253 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/example_hostile.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/example_hostile.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/example_invoke_contract.wasm b/soroban-test-wasms/wasm-workspace/opt/next/example_invoke_contract.wasm index 37b86ba3f..5e87197d2 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/example_invoke_contract.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/example_invoke_contract.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/example_linear_memory.wasm b/soroban-test-wasms/wasm-workspace/opt/next/example_linear_memory.wasm index d79f49344..7a3400051 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/example_linear_memory.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/example_linear_memory.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/example_simple_account.wasm b/soroban-test-wasms/wasm-workspace/opt/next/example_simple_account.wasm index 1a1e773d5..e2651e8e5 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/example_simple_account.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/example_simple_account.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/example_updateable_contract.wasm b/soroban-test-wasms/wasm-workspace/opt/next/example_updateable_contract.wasm index 4d71b34ea..7ff2ce6c7 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/example_updateable_contract.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/example_updateable_contract.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/example_vec.wasm b/soroban-test-wasms/wasm-workspace/opt/next/example_vec.wasm index d47c8a61d..9e211b39b 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/example_vec.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/example_vec.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/soroban_write_upgrade_bytes_contract.wasm b/soroban-test-wasms/wasm-workspace/opt/next/soroban_write_upgrade_bytes_contract.wasm index f5250abd1..422a2237c 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/soroban_write_upgrade_bytes_contract.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/soroban_write_upgrade_bytes_contract.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/test_conditional_account.wasm b/soroban-test-wasms/wasm-workspace/opt/next/test_conditional_account.wasm index 4813ededf..6d9d3d688 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/test_conditional_account.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/test_conditional_account.wasm differ diff --git a/soroban-test-wasms/wasm-workspace/opt/next/test_delegated_account.wasm b/soroban-test-wasms/wasm-workspace/opt/next/test_delegated_account.wasm index a921a32c0..348457a6e 100644 Binary files a/soroban-test-wasms/wasm-workspace/opt/next/test_delegated_account.wasm and b/soroban-test-wasms/wasm-workspace/opt/next/test_delegated_account.wasm differ