Skip to content

Commit 9c63e25

Browse files
authored
Merge branch 'main' into debug-assert-in-contract
2 parents ff1225f + c32bb7e commit 9c63e25

File tree

7 files changed

+154
-25
lines changed

7 files changed

+154
-25
lines changed

soroban-sdk/src/crypto.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,10 @@ impl Crypto {
161161
&self,
162162
message_digest: &Hash<32>,
163163
signature: &BytesN<64>,
164-
recorvery_id: u32,
164+
recovery_id: u32,
165165
) -> BytesN<65> {
166166
let env = self.env();
167-
CryptoHazmat::new(env).secp256k1_recover(&message_digest.0, signature, recorvery_id)
167+
CryptoHazmat::new(env).secp256k1_recover(&message_digest.0, signature, recovery_id)
168168
}
169169

170170
/// Verifies the ECDSA secp256r1 signature.
@@ -228,14 +228,14 @@ impl CryptoHazmat {
228228
&self,
229229
message_digest: &BytesN<32>,
230230
signature: &BytesN<64>,
231-
recorvery_id: u32,
231+
recovery_id: u32,
232232
) -> BytesN<65> {
233233
let env = self.env();
234234
let bytes = internal::Env::recover_key_ecdsa_secp256k1(
235235
env,
236236
message_digest.to_object(),
237237
signature.to_object(),
238-
recorvery_id.into(),
238+
recovery_id.into(),
239239
)
240240
.unwrap_infallible();
241241
unsafe { BytesN::unchecked_new(env.clone(), bytes) }

soroban-sdk/src/env.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub mod internal {
3939
// any `TestContract` frame in progress and then _panics_, unwinding back to
4040
// a panic-catcher it installed when invoking the `TestContract` frame, and
4141
// then extracting E from the frame and returning it to its caller. This
42-
// simulates the "crash, but catching the error" behaviour of the WASM case.
42+
// simulates the "crash, but catching the error" behavior of the WASM case.
4343
// This only works if we panic via `escalate_error_to_panic`.
4444
//
4545
// (The reason we don't just panic_any() here and let the panic-catcher do a
@@ -725,7 +725,7 @@ impl Env {
725725
/// Take the return value with a grain of salt. The returned resources mostly
726726
/// correspond only to the operations that have happened during the host
727727
/// invocation, i.e. this won't try to simulate the work that happens in
728-
/// production scenarios (e.g. certain XDR rountrips). This also doesn't try
728+
/// production scenarios (e.g. certain XDR roundtrips). This also doesn't try
729729
/// to model resources related to the transaction size.
730730
///
731731
/// The returned value is as useful as the preceding setup, e.g. if a test
@@ -749,7 +749,7 @@ impl Env {
749749
///
750750
/// Pass the arguments for the contract's constructor, or `()` if none. For
751751
/// contracts with a constructor, use the contract's generated `Args` type
752-
/// to construct the arguments with the appropropriate types for invoking
752+
/// to construct the arguments with the appropriate types for invoking
753753
/// the constructor during registration.
754754
///
755755
/// Returns the address of the registered contract that is the same as the
@@ -1120,15 +1120,15 @@ impl Env {
11201120
self.env_impl
11211121
.switch_to_recording_auth_inherited_from_snapshot(&prev_auth_manager)
11221122
.unwrap();
1123-
self.invoke_contract::<()>(
1123+
let admin_result = self.try_invoke_contract::<(), Error>(
11241124
&token_id,
11251125
&soroban_sdk_macros::internal_symbol_short!("set_admin"),
11261126
(admin,).try_into_val(self).unwrap(),
11271127
);
11281128
self.env_impl.set_auth_manager(prev_auth_manager).unwrap();
1129+
admin_result.unwrap().unwrap();
11291130

11301131
let issuer = StellarAssetIssuer::new(self.clone(), issuer_id);
1131-
11321132
StellarAssetContract::new(token_id, issuer, asset)
11331133
}
11341134

@@ -1167,13 +1167,14 @@ impl Env {
11671167
executable: xdr::ContractExecutable,
11681168
constructor_args: Vec<Val>,
11691169
) -> Address {
1170+
let args_vec: std::vec::Vec<xdr::ScVal> =
1171+
constructor_args.iter().map(|v| v.into_val(self)).collect();
1172+
let constructor_args = args_vec.try_into().unwrap();
11701173
let prev_auth_manager = self.env_impl.snapshot_auth_manager().unwrap();
11711174
self.env_impl
11721175
.switch_to_recording_auth_inherited_from_snapshot(&prev_auth_manager)
11731176
.unwrap();
1174-
let args_vec: std::vec::Vec<xdr::ScVal> =
1175-
constructor_args.iter().map(|v| v.into_val(self)).collect();
1176-
let contract_id: Address = self
1177+
let create_result = self
11771178
.env_impl
11781179
.invoke_function(xdr::HostFunction::CreateContractV2(
11791180
xdr::CreateContractArgsV2 {
@@ -1186,16 +1187,13 @@ impl Env {
11861187
},
11871188
),
11881189
executable,
1189-
constructor_args: args_vec.try_into().unwrap(),
1190+
constructor_args,
11901191
},
1191-
))
1192-
.unwrap()
1193-
.try_into_val(self)
1194-
.unwrap();
1192+
));
11951193

11961194
self.env_impl.set_auth_manager(prev_auth_manager).unwrap();
11971195

1198-
contract_id
1196+
create_result.unwrap().try_into_val(self).unwrap()
11991197
}
12001198

12011199
/// Set authorizations and signatures in the environment which will be
@@ -1555,7 +1553,7 @@ impl Env {
15551553
/// # fn main() {
15561554
/// let e: Env = Default::default();
15571555
/// let account_contract = NoopAccountContractClient::new(&e, &e.register(NoopAccountContract, ()));
1558-
/// // Non-succesful call of `__check_auth` with a `contracterror` error.
1556+
/// // Non-successful call of `__check_auth` with a `contracterror` error.
15591557
/// assert_eq!(
15601558
/// e.try_invoke_contract_check_auth::<NoopAccountError>(
15611559
/// &account_contract.address,

soroban-sdk/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,22 @@ pub use soroban_sdk_macros::contract;
431431
/// Functions that are publicly accessible in the implementation are invocable
432432
/// by other contracts, or directly by transactions, when deployed.
433433
///
434+
/// ### Notes
435+
///
436+
/// Each public function's export name is derived from the function name alone,
437+
/// without any type prefix or namespace. This means:
438+
///
439+
/// - **Function names must be unique across all `#[contractimpl]` blocks in a
440+
/// crate.** If two impl blocks define a function with the same name, their
441+
/// Wasm exports will collide, producing build or linker errors.
442+
///
443+
/// - **Importing a crate that contains `#[contractimpl]` blocks will pull its
444+
/// exported functions into the importing crate's Wasm binary.** This is a
445+
/// limitation of Rust — any `#[export_name = "..."]` function in a dependency
446+
/// is included in the final binary. This can cause unexpected exports or name
447+
/// collisions that are hard to diagnose. For this reason it is usually
448+
/// inadvisable to import dependencies that use `#[contractimpl]`.
449+
///
434450
/// ### Examples
435451
///
436452
/// Define a contract with one function, `hello`, and call it from within a test

soroban-sdk/src/tests/env.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::{
1414
// configured for real. Some functions in Env have in the past or may now make
1515
// assumptions about a source account being set. This is something small we do
1616
// to make sure we don't accidentally introduce Env functionality that will
17-
// panick in SDK tests.
17+
// panic in SDK tests.
1818
fn default_has_source_account_configured_in_host() {
1919
let env = Env::default();
2020
assert!(env.host().source_account_address().unwrap().is_some());
@@ -44,6 +44,11 @@ enum ContractError {
4444
AnError = 1,
4545
}
4646

47+
mod constructor_contract {
48+
use crate as soroban_sdk;
49+
soroban_sdk::contractimport!(file = "../target/wasm32v1-none/release/test_constructor.wasm");
50+
}
51+
4752
#[test]
4853
fn default_and_from_snapshot_same_settings() {
4954
let env1 = Env::default();
@@ -326,3 +331,28 @@ fn test_try_as_contract_panic() {
326331
)))
327332
);
328333
}
334+
335+
#[test]
336+
fn test_register_restores_auth_before_panics() {
337+
let env = Env::default();
338+
339+
let address = env.register(Contract, ());
340+
let client = ContractClient::new(&env, &address);
341+
let user = Address::generate(&env);
342+
343+
let pre_register = client.try_need_auth(&user);
344+
assert!(pre_register.is_err());
345+
346+
// This is contrived to cause a panic inside register_contract_with_source.
347+
// Don't actually do things like this!
348+
let another_contract = env.register(Contract, ());
349+
let register_result = env.try_as_contract::<_, Error>(&another_contract, || {
350+
// This expects arguments for the constructor, but none are provided, so it will panic
351+
env.register(constructor_contract::WASM, ());
352+
});
353+
assert!(register_result.is_err());
354+
355+
let post_register = client.try_need_auth(&user);
356+
assert!(post_register.is_err());
357+
assert_eq!(pre_register, post_register);
358+
}

soroban-sdk/src/testutils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ pub mod budget {
336336

337337
/// Budget that tracks the resources consumed for the environment.
338338
///
339-
/// The budget consistents of two cost dimensions:
339+
/// The budget consists of two cost dimensions:
340340
/// - CPU instructions
341341
/// - Memory
342342
///
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
{
2+
"generators": {
3+
"address": 4,
4+
"nonce": 0,
5+
"mux_id": 0
6+
},
7+
"auth": [
8+
[],
9+
[],
10+
[],
11+
[],
12+
[]
13+
],
14+
"ledger": {
15+
"protocol_version": 25,
16+
"sequence_number": 0,
17+
"timestamp": 0,
18+
"network_id": "0000000000000000000000000000000000000000000000000000000000000000",
19+
"base_reserve": 0,
20+
"min_persistent_entry_ttl": 4096,
21+
"min_temp_entry_ttl": 16,
22+
"max_entry_ttl": 6312000,
23+
"ledger_entries": [
24+
{
25+
"entry": {
26+
"last_modified_ledger_seq": 0,
27+
"data": {
28+
"contract_data": {
29+
"ext": "v0",
30+
"contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM",
31+
"key": "ledger_key_contract_instance",
32+
"durability": "persistent",
33+
"val": {
34+
"contract_instance": {
35+
"executable": {
36+
"wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
37+
},
38+
"storage": null
39+
}
40+
}
41+
}
42+
},
43+
"ext": "v0"
44+
},
45+
"live_until": 4095
46+
},
47+
{
48+
"entry": {
49+
"last_modified_ledger_seq": 0,
50+
"data": {
51+
"contract_data": {
52+
"ext": "v0",
53+
"contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M",
54+
"key": "ledger_key_contract_instance",
55+
"durability": "persistent",
56+
"val": {
57+
"contract_instance": {
58+
"executable": {
59+
"wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
60+
},
61+
"storage": null
62+
}
63+
}
64+
}
65+
},
66+
"ext": "v0"
67+
},
68+
"live_until": 4095
69+
},
70+
{
71+
"entry": {
72+
"last_modified_ledger_seq": 0,
73+
"data": {
74+
"contract_code": {
75+
"ext": "v0",
76+
"hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
77+
"code": ""
78+
}
79+
},
80+
"ext": "v0"
81+
},
82+
"live_until": 4095
83+
}
84+
]
85+
},
86+
"events": []
87+
}

soroban-token-sdk/src/_migrating/v23_token_transfer.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,5 @@
7575
//! don't require any changes, because the [`MuxedAddress`] is only necessary
7676
//! in a few narrow scenarios (such as direct transfer to an exchange).
7777
//!
78-
//! [`Events::publish`]: crate::events::Events::publish
79-
//! [`Address`]: crate::MuxedAddress
80-
//! [`MuxedAddress`]: crate::MuxedAddress
81-
//! [`contractevent`]: crate::contractevent
78+
//! [`Address`]: soroban_sdk::Address
79+
//! [`MuxedAddress`]: soroban_sdk::MuxedAddress

0 commit comments

Comments
 (0)