diff --git a/soroban-env-host/src/test/lifecycle.rs b/soroban-env-host/src/test/lifecycle.rs index c5e3f56ef..b58ebeef1 100644 --- a/soroban-env-host/src/test/lifecycle.rs +++ b/soroban-env-host/src/test/lifecycle.rs @@ -2402,7 +2402,7 @@ mod cap_xx_opt_in_reentry { use crate::{Host, HostError, MeteredOrdMap}; use soroban_env_common::{AddressObject, Env, Symbol, TryFromVal, TryIntoVal, Val, VecObject}; use soroban_test_wasms::{ - SIMPLE_NO_REENTRY_CONTRACT_B, SIMPLE_REENTRY_CONTRACT_A, SIMPLE_REENTRY_CONTRACT_B, + SIMPLE_NO_REENTRY_CONTRACT_A, SIMPLE_NO_REENTRY_CONTRACT_B, SIMPLE_REENTRY_CONTRACT_A, SIMPLE_REENTRY_CONTRACT_B }; use stellar_xdr::curr::{ ContractEvent, ContractEventBody, ContractEventType, ContractEventV0, ExtensionPoint, Hash, @@ -2453,6 +2453,18 @@ mod cap_xx_opt_in_reentry { call_contract(&host, contract_id_a, args); } + #[test] + #[should_panic] + fn test_reentry_disabled_from_caller() { + let host = Host::test_host_with_recording_footprint(); + let contract_id_a = host.register_test_contract_wasm(SIMPLE_NO_REENTRY_CONTRACT_A); + let contract_id_b = host.register_test_contract_wasm(SIMPLE_REENTRY_CONTRACT_B); + host.enable_debug().unwrap(); + let args = test_vec![&host, contract_id_b].into(); + + call_contract(&host, contract_id_a, args); + } + fn call_contract(host: &Host, called: AddressObject, args: VecObject) { let fname = Symbol::try_from_val(host, &"test_reentry").unwrap(); host.call(called, fname, args).unwrap(); diff --git a/soroban-env-host/src/vm.rs b/soroban-env-host/src/vm.rs index b50f6c401..9591fdd62 100644 --- a/soroban-env-host/src/vm.rs +++ b/soroban-env-host/src/vm.rs @@ -110,7 +110,7 @@ impl Host { if symbols.contains(&("d", "1")) || symbols.contains(&("d", "2")) { return Err(crate::Error::from_type_and_code( ScErrorType::WasmVm, - ScErrorCode::ArithDomain, + ScErrorCode::InvalidAction, ) .try_into()?); } diff --git a/soroban-test-wasms/src/lib.rs b/soroban-test-wasms/src/lib.rs index c69f67dc8..258bbc6c2 100644 --- a/soroban-test-wasms/src/lib.rs +++ b/soroban-test-wasms/src/lib.rs @@ -123,6 +123,9 @@ pub const CUSTOM_ACCOUNT_CONTEXT_TEST_CONTRACT: &[u8] = pub const SIMPLE_REENTRY_CONTRACT_A: &[u8] = include_bytes!("../wasm-workspace/opt/23/example_reentry_a.wasm").as_slice(); +pub const SIMPLE_NO_REENTRY_CONTRACT_A: &[u8] = + include_bytes!("../wasm-workspace/opt/23/example_no_reentry_a.wasm").as_slice(); + pub const SIMPLE_REENTRY_CONTRACT_B: &[u8] = include_bytes!("../wasm-workspace/opt/23/example_reentry_b.wasm").as_slice(); diff --git a/soroban-test-wasms/wasm-workspace/Cargo.lock b/soroban-test-wasms/wasm-workspace/Cargo.lock index 7cd3acb10..bc0f31938 100644 --- a/soroban-test-wasms/wasm-workspace/Cargo.lock +++ b/soroban-test-wasms/wasm-workspace/Cargo.lock @@ -521,6 +521,14 @@ dependencies = [ "soroban-sdk", ] +[[package]] +name = "example_no_reentry_a" +version = "0.0.0" +dependencies = [ + "soroban-env-common 22.0.0-rc.1", + "soroban-sdk", +] + [[package]] name = "example_no_reentry_b" version = "0.0.0" diff --git a/soroban-test-wasms/wasm-workspace/Cargo.toml b/soroban-test-wasms/wasm-workspace/Cargo.toml index ce4e6e734..f2a708459 100644 --- a/soroban-test-wasms/wasm-workspace/Cargo.toml +++ b/soroban-test-wasms/wasm-workspace/Cargo.toml @@ -51,6 +51,7 @@ members = [ "constructor_with_result", "custom_account_context", "reentry_a", + "no_reentry_a", "no_reentry_b", "reentry_b", ] diff --git a/soroban-test-wasms/wasm-workspace/no_reentry_a/Cargo.toml b/soroban-test-wasms/wasm-workspace/no_reentry_a/Cargo.toml new file mode 100644 index 000000000..3a4b2553d --- /dev/null +++ b/soroban-test-wasms/wasm-workspace/no_reentry_a/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "example_no_reentry_a" +version = "0.0.0" +authors = ["Stellar Development Foundation "] +license = "Apache-2.0" +edition = "2021" +publish = false +rust-version.workspace = true + +[lib] +crate-type = ["cdylib", "rlib"] +doctest = false + +[dependencies] +soroban-sdk = { workspace = true } +soroban-env-common = { workspace = true } + +[features] +next = ["soroban-env-common/next"] diff --git a/soroban-test-wasms/wasm-workspace/no_reentry_a/src/lib.rs b/soroban-test-wasms/wasm-workspace/no_reentry_a/src/lib.rs new file mode 100644 index 000000000..2ba311eae --- /dev/null +++ b/soroban-test-wasms/wasm-workspace/no_reentry_a/src/lib.rs @@ -0,0 +1,31 @@ +#![no_std] +use soroban_sdk::{contract, contractimpl, Env, Address, Symbol, TryIntoVal, Vec, Val}; + +#[link(wasm_import_module = "d")] +extern "C" { + #[allow(improper_ctypes)] + #[link_name = "_"] + pub fn call_contract(contract: i64, func: i64, args: i64, ) -> i64; +} + +#[contract] +pub struct Contract; + +#[contractimpl] +impl Contract { + pub fn test_reentry(env: Env, called: Address) { + let args: Vec = (env.current_contract_address(), ).try_into_val(&env).unwrap(); + let func = Symbol::new(&env, "do_reentry"); + let called_val = called.as_val().get_payload() as i64; + let func_val = func.as_val().get_payload() as i64; + let args_val = args.as_val().get_payload() as i64; + + unsafe { + call_contract(called_val, func_val, args_val); + }; + } + + pub fn do_nothing(env: Env) { + env.events().publish((Symbol::new(&env, "first_soroban_reentry"),), ()); + } +} diff --git a/soroban-test-wasms/wasm-workspace/opt/23/example_no_reentry_a.wasm b/soroban-test-wasms/wasm-workspace/opt/23/example_no_reentry_a.wasm new file mode 100755 index 000000000..1165746cd Binary files /dev/null and b/soroban-test-wasms/wasm-workspace/opt/23/example_no_reentry_a.wasm differ