Repository: stellar/rs-soroban-env
Pull request #823 (2023-05-31 00:56:27)

Support Auth Next for host fns
### What

- Add support for host fn frames in auth manager
- Add support for host fns in custom account contracts
- Adapt to the XDR refactoring in https://github.com/stellar/stellar-xdr/pull/95
- Use `Address` instead of 32-bytes for most of the host functions
- Modify/add host fns to be able to perform the operations that currently are only available via a top-level invocation only (create contracts on behalf of any address, create asset contracts, upload wasm).

### Why

- Improve consistency of how authorization works across the system (unify the way host fns and contract fns are authorized). 
- Reach feature parity between the host interface available to contracts and host interface invokable from classic ops

### Known limitations

N/A



Patch:
diff --git a/Cargo.lock b/Cargo.lock
index ec11573f..3ab69056 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
 
 [[package]]
 name = "addr2line"
-version = "0.17.0"
+version = "0.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
+checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
 dependencies = [
  "gimli",
 ]
@@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
 
 [[package]]
 name = "aho-corasick"
-version = "0.7.18"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
 dependencies = [
  "memchr",
 ]
@@ -46,9 +46,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.66"
+version = "1.0.71"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
+checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
 
 [[package]]
 name = "approx"
@@ -87,9 +87,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
 [[package]]
 name = "backtrace"
-version = "0.3.66"
+version = "0.3.67"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
+checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
 dependencies = [
  "addr2line",
  "cc",
@@ -102,15 +102,15 @@ dependencies = [
 
 [[package]]
 name = "base64"
-version = "0.13.0"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
+checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
 
 [[package]]
 name = "base64"
-version = "0.21.0"
+version = "0.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
+checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105"
 
 [[package]]
 name = "bitflags"
@@ -129,15 +129,15 @@ dependencies = [
 
 [[package]]
 name = "bumpalo"
-version = "3.11.1"
+version = "3.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
+checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
 
 [[package]]
 name = "bytemuck"
-version = "1.12.1"
+version = "1.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da"
+checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
 
 [[package]]
 name = "byteorder"
@@ -154,14 +154,14 @@ dependencies = [
  "num-bigint",
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
 name = "cc"
-version = "1.0.73"
+version = "1.0.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
 
 [[package]]
 name = "cfg-if"
@@ -171,9 +171,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "chrono"
-version = "0.4.22"
+version = "0.4.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
+checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
 dependencies = [
  "iana-time-zone",
  "num-integer",
@@ -197,16 +197,6 @@ dependencies = [
  "vec_map",
 ]
 
-[[package]]
-name = "codespan-reporting"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
-dependencies = [
- "termcolor",
- "unicode-width",
-]
-
 [[package]]
 name = "colored"
 version = "2.0.0"
@@ -220,15 +210,15 @@ dependencies = [
 
 [[package]]
 name = "core-foundation-sys"
-version = "0.8.3"
+version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
 
 [[package]]
 name = "cpufeatures"
-version = "0.2.5"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
+checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58"
 dependencies = [
  "libc",
 ]
@@ -257,50 +247,6 @@ dependencies = [
  "zeroize",
 ]
 
-[[package]]
-name = "cxx"
-version = "1.0.80"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a"
-dependencies = [
- "cc",
- "cxxbridge-flags",
- "cxxbridge-macro",
- "link-cplusplus",
-]
-
-[[package]]
-name = "cxx-build"
-version = "1.0.80"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827"
-dependencies = [
- "cc",
- "codespan-reporting",
- "once_cell",
- "proc-macro2",
- "quote",
- "scratch",
- "syn 1.0.104",
-]
-
-[[package]]
-name = "cxxbridge-flags"
-version = "1.0.80"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a"
-
-[[package]]
-name = "cxxbridge-macro"
-version = "1.0.80"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.104",
-]
-
 [[package]]
 name = "darling"
 version = "0.20.1"
@@ -322,7 +268,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "strsim 0.10.0",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -333,7 +279,7 @@ checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a"
 dependencies = [
  "darling_core",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -344,7 +290,7 @@ checksum = "f3cdeb9ec472d588e539a818b2dee436825730da08ad0017c4b1a17676bdc8b7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.104",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -358,9 +304,9 @@ dependencies = [
 
 [[package]]
 name = "dissimilar"
-version = "1.0.4"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c97b9233581d84b8e1e689cdd3a47b6f69770084fc246e86a7f78b0d9c1d4a5"
+checksum = "210ec60ae7d710bed8683e333e9d2855a8a56a3e9892b38bad3bb0d4d29b0d5e"
 
 [[package]]
 name = "downcast-rs"
@@ -403,15 +349,15 @@ dependencies = [
 
 [[package]]
 name = "either"
-version = "1.8.0"
+version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
+checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
 
 [[package]]
 name = "env_logger"
-version = "0.9.0"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
+checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
 dependencies = [
  "atty",
  "humantime",
@@ -428,9 +374,9 @@ checksum = "0198b9d0078e0f30dedc7acbb21c974e838fc8fae3ee170128658a98cb2c1c04"
 
 [[package]]
 name = "expect-test"
-version = "1.4.0"
+version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d4661aca38d826eb7c72fe128e4238220616de4c0cc00db7bfc38e2e1364dd3"
+checksum = "30d9eafeadd538e68fb28016364c9732d78e420b9ff8853fa5e4058861e9f8d3"
 dependencies = [
  "dissimilar",
  "once_cell",
@@ -442,11 +388,20 @@ version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 
+[[package]]
+name = "form_urlencoded"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
+dependencies = [
+ "percent-encoding",
+]
+
 [[package]]
 name = "generic-array"
-version = "0.14.6"
+version = "0.14.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
 dependencies = [
  "typenum",
  "version_check",
@@ -465,9 +420,9 @@ dependencies = [
 
 [[package]]
 name = "gimli"
-version = "0.26.2"
+version = "0.27.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
+checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
 
 [[package]]
 name = "hashbrown"
@@ -510,26 +465,25 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
 
 [[package]]
 name = "iana-time-zone"
-version = "0.1.53"
+version = "0.1.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
+checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c"
 dependencies = [
  "android_system_properties",
  "core-foundation-sys",
  "iana-time-zone-haiku",
  "js-sys",
  "wasm-bindgen",
- "winapi",
+ "windows",
 ]
 
 [[package]]
 name = "iana-time-zone-haiku"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
 dependencies = [
- "cxx",
- "cxx-build",
+ "cc",
 ]
 
 [[package]]
@@ -538,11 +492,21 @@ version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
 
+[[package]]
+name = "idna"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
 [[package]]
 name = "indexmap"
-version = "1.9.1"
+version = "1.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
 dependencies = [
  "autocfg",
  "hashbrown",
@@ -573,7 +537,7 @@ dependencies = [
  "proc-macro-crate",
  "proc-macro2",
  "quote",
- "syn 1.0.104",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -587,15 +551,15 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "1.0.4"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
+checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
 
 [[package]]
 name = "js-sys"
-version = "0.3.60"
+version = "0.3.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
+checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790"
 dependencies = [
  "wasm-bindgen",
 ]
@@ -614,24 +578,15 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
 
 [[package]]
 name = "libc"
-version = "0.2.132"
+version = "0.2.144"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
+checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
 
 [[package]]
 name = "libm"
-version = "0.2.5"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565"
-
-[[package]]
-name = "link-cplusplus"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369"
-dependencies = [
- "cc",
-]
+checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
 
 [[package]]
 name = "linregress"
@@ -653,10 +608,11 @@ dependencies = [
 
 [[package]]
 name = "matrixmultiply"
-version = "0.3.2"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "add85d4dd35074e6fedc608f8c8f513a3548619a9024b751949ef0e8e45a4d84"
+checksum = "090126dc04f95dc0d1c1c91f61bdd474b3930ca064c1edc8a849da2c6cbe1e77"
 dependencies = [
+ "autocfg",
  "rawpointer",
 ]
 
@@ -684,9 +640,9 @@ dependencies = [
 
 [[package]]
 name = "miniz_oxide"
-version = "0.5.3"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
 dependencies = [
  "adler",
 ]
@@ -721,7 +677,7 @@ checksum = "d232c68884c0c99810a5a4d333ef7e47689cfd0edc85efc9e54e1e6bf5212766"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.104",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -758,7 +714,7 @@ checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.104",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -792,29 +748,20 @@ dependencies = [
  "autocfg",
 ]
 
-[[package]]
-name = "num_threads"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
-dependencies = [
- "libc",
-]
-
 [[package]]
 name = "object"
-version = "0.29.0"
+version = "0.30.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
+checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "once_cell"
-version = "1.13.1"
+version = "1.17.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e"
+checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
 
 [[package]]
 name = "opaque-debug"
@@ -828,11 +775,17 @@ version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
 
+[[package]]
+name = "percent-encoding"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
+
 [[package]]
 name = "perf-event"
-version = "0.4.7"
+version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5396562cd2eaa828445d6d34258ae21ee1eb9d40fe626ca7f51c8dccb4af9d66"
+checksum = "b4d6393d9238342159080d79b78cb59c67399a8e7ecfa5d410bd614169e4e823"
 dependencies = [
  "libc",
  "perf-event-open-sys",
@@ -840,9 +793,9 @@ dependencies = [
 
 [[package]]
 name = "perf-event-open-sys"
-version = "1.0.1"
+version = "4.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce9bedf5da2c234fdf2391ede2b90fabf585355f33100689bc364a3ea558561a"
+checksum = "7c44fb1c7651a45a3652c4afc6e754e40b3d6e6556f1487e2b230bfc4f33c2a8"
 dependencies = [
  "libc",
 ]
@@ -855,9 +808,9 @@ checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.16"
+version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
 
 [[package]]
 name = "proc-macro-crate"
@@ -878,7 +831,7 @@ dependencies = [
  "proc-macro-error-attr",
  "proc-macro2",
  "quote",
- "syn 1.0.104",
+ "syn 1.0.109",
  "version_check",
 ]
 
@@ -895,18 +848,18 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.56"
+version = "1.0.58"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
+checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.26"
+version = "1.0.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
+checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
 dependencies = [
  "proc-macro2",
 ]
@@ -960,9 +913,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
 
 [[package]]
 name = "regex"
-version = "1.6.0"
+version = "1.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
+checksum = "d1a59b5d8e97dee33696bf13c5ba8ab85341c002922fba050069326b9c498974"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -971,30 +924,30 @@ dependencies = [
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.27"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
 
 [[package]]
 name = "rgb"
-version = "0.8.34"
+version = "0.8.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3603b7d71ca82644f79b5a06d1220e9a58ede60bd32255f698cb1af8838b8db3"
+checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59"
 dependencies = [
  "bytemuck",
 ]
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.21"
+version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
+checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
 
 [[package]]
 name = "ryu"
-version = "1.0.11"
+version = "1.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
 
 [[package]]
 name = "safe_arch"
@@ -1005,37 +958,31 @@ dependencies = [
  "bytemuck",
 ]
 
-[[package]]
-name = "scratch"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898"
-
 [[package]]
 name = "serde"
-version = "1.0.160"
+version = "1.0.163"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
+checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.160"
+version = "1.0.163"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
+checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.87"
+version = "1.0.96"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45"
+checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
 dependencies = [
  "itoa",
  "ryu",
@@ -1048,7 +995,7 @@ version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9f02d8aa6e3c385bf084924f660ce2a3a6bd333ba55b35e8590b321f35d88513"
 dependencies = [
- "base64 0.21.0",
+ "base64 0.21.1",
  "chrono",
  "hex",
  "indexmap",
@@ -1067,7 +1014,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -1091,9 +1038,9 @@ checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
 
 [[package]]
 name = "simba"
-version = "0.8.0"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50582927ed6f77e4ac020c057f37a268fc6aebc29225050365aacbb9deeeddc4"
+checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae"
 dependencies = [
  "approx",
  "num-complex",
@@ -1170,7 +1117,7 @@ dependencies = [
  "serde",
  "serde_json",
  "stellar-xdr",
- "syn 2.0.15",
+ "syn 2.0.16",
  "thiserror",
 ]
 
@@ -1181,7 +1128,7 @@ dependencies = [
  "itertools",
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -1236,10 +1183,10 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
 [[package]]
 name = "stellar-xdr"
 version = "0.0.16"
-source = "git+https://github.com/stellar/rs-stellar-xdr?rev=eda841f3c08a023bb50f7f79b8b8b8d6083aad83#eda841f3c08a023bb50f7f79b8b8b8d6083aad83"
+source = "git+https://github.com/stellar/rs-stellar-xdr?rev=979c0a5dbae204a2efe7bf52c1229081f685c2a0#979c0a5dbae204a2efe7bf52c1229081f685c2a0"
 dependencies = [
  "arbitrary",
- "base64 0.13.0",
+ "base64 0.13.1",
  "crate-git-revision",
  "hex",
  "serde",
@@ -1279,20 +1226,20 @@ dependencies = [
  "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn 1.0.104",
+ "syn 1.0.109",
 ]
 
 [[package]]
 name = "subtle"
-version = "2.4.1"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
 
 [[package]]
 name = "syn"
-version = "1.0.104"
+version = "1.0.109"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1301,27 +1248,15 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.15"
+version = "2.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01"
 dependencies = [
  "proc-macro2",
  "quote",
  "unicode-ident",
 ]
 
-[[package]]
-name = "synstructure"
-version = "0.12.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.104",
- "unicode-xid",
-]
-
 [[package]]
 name = "tabwriter"
 version = "1.2.1"
@@ -1333,9 +1268,9 @@ dependencies = [
 
 [[package]]
 name = "termcolor"
-version = "1.1.3"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
+checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
 dependencies = [
  "winapi-util",
 ]
@@ -1385,7 +1320,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -1396,13 +1331,11 @@ checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820"
 
 [[package]]
 name = "time"
-version = "0.3.16"
+version = "0.3.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca"
+checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc"
 dependencies = [
  "itoa",
- "libc",
- "num_threads",
  "serde",
  "time-core",
  "time-macros",
@@ -1410,30 +1343,45 @@ dependencies = [
 
 [[package]]
 name = "time-core"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
+checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
 
 [[package]]
 name = "time-macros"
-version = "0.2.5"
+version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b"
+checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
 dependencies = [
  "time-core",
 ]
 
+[[package]]
+name = "tinyvec"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
 [[package]]
 name = "toml_datetime"
-version = "0.6.1"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
+checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f"
 
 [[package]]
 name = "toml_edit"
-version = "0.19.8"
+version = "0.19.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
+checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739"
 dependencies = [
  "indexmap",
  "toml_datetime",
@@ -1442,9 +1390,9 @@ dependencies = [
 
 [[package]]
 name = "tracing"
-version = "0.1.36"
+version = "0.1.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307"
+checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
 dependencies = [
  "cfg-if",
  "pin-project-lite",
@@ -1453,18 +1401,18 @@ dependencies = [
 
 [[package]]
 name = "tracing-core"
-version = "0.1.29"
+version = "0.1.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7"
+checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
 dependencies = [
  "once_cell",
 ]
 
 [[package]]
 name = "tracing-subscriber"
-version = "0.3.15"
+version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b"
+checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
 dependencies = [
  "tracing-core",
 ]
@@ -1481,33 +1429,53 @@ dependencies = [
 
 [[package]]
 name = "typenum"
-version = "1.15.0"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
+checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.3"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
+checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+dependencies = [
+ "tinyvec",
+]
 
 [[package]]
 name = "unicode-segmentation"
-version = "1.10.0"
+version = "1.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
+checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
 
 [[package]]
 name = "unicode-width"
-version = "0.1.9"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
 
 [[package]]
-name = "unicode-xid"
-version = "0.2.3"
+name = "url"
+version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
+checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+]
 
 [[package]]
 name = "vec_map"
@@ -1529,9 +1497,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.83"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
+checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73"
 dependencies = [
  "cfg-if",
  "wasm-bindgen-macro",
@@ -1539,24 +1507,24 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.83"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
+checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb"
 dependencies = [
  "bumpalo",
  "log",
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 1.0.104",
+ "syn 2.0.16",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.83"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
+checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -1564,22 +1532,22 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.83"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
+checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.104",
+ "syn 2.0.16",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.83"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
+checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93"
 
 [[package]]
 name = "wasm-encoder"
@@ -1592,11 +1560,12 @@ dependencies = [
 
 [[package]]
 name = "wasmparser"
-version = "0.92.0"
+version = "0.106.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7da34cec2a8c23db906cdf8b26e988d7a7f0d549eb5d51299129647af61a1b37"
+checksum = "d014e33793cab91655fa6349b0bc974984de106b2e0f6b0dfe6f6594b260624d"
 dependencies = [
  "indexmap",
+ "url",
 ]
 
 [[package]]
@@ -1610,9 +1579,9 @@ dependencies = [
 
 [[package]]
 name = "wasmprinter"
-version = "0.2.41"
+version = "0.2.58"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca4374ec27194a12b85aa0e1681a42d5800e97f11c036fa85dea8087c8ccb10b"
+checksum = "3c520299a0b5999adef4f063add9689e4559b3e4eb2688dbd63cc36ebb595841"
 dependencies = [
  "anyhow",
  "wasmparser",
@@ -1620,9 +1589,9 @@ dependencies = [
 
 [[package]]
 name = "wide"
-version = "0.7.8"
+version = "0.7.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b689b6c49d6549434bf944e6b0f39238cf63693cb7a147e9d887507fffa3b223"
+checksum = "5cd0496a71f3cc6bc4bf0ed91346426a5099e93d89807e663162dc5a1069ff65"
 dependencies = [
  "bytemuck",
  "safe_arch",
@@ -1659,11 +1628,77 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
+[[package]]
+name = "windows"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+
 [[package]]
 name = "winnow"
-version = "0.4.1"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28"
+checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699"
 dependencies = [
  "memchr",
 ]
@@ -1679,12 +1714,11 @@ dependencies = [
 
 [[package]]
 name = "zeroize_derive"
-version = "1.3.2"
+version = "1.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17"
+checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.104",
- "synstructure",
+ "syn 2.0.16",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index 18fe61a7..9db0ac0b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -27,7 +27,7 @@ soroban-native-sdk-macros = { version = "0.0.16", path = "soroban-native-sdk-mac
 [workspace.dependencies.stellar-xdr]
 version = "0.0.16"
 git = "https://github.com/stellar/rs-stellar-xdr"
-rev = "eda841f3c08a023bb50f7f79b8b8b8d6083aad83"
+rev = "979c0a5dbae204a2efe7bf52c1229081f685c2a0"
 default-features = false
 
 [workspace.dependencies.wasmi]
diff --git a/soroban-env-common/env.json b/soroban-env-common/env.json
index 3eafe0ed..bdd1a826 100644
--- a/soroban-env-common/env.json
+++ b/soroban-env-common/env.json
@@ -981,8 +981,12 @@
                 },
                 {
                     "export": "3",
-                    "name": "create_contract_from_contract",
+                    "name": "create_contract",
                     "args": [
+                        {
+                            "name": "deployer",
+                            "type": "AddressObject"
+                        },
                         {
                             "name": "wasm_hash",
                             "type": "BytesObject"
@@ -992,11 +996,35 @@
                             "type": "BytesObject"
                         }
                     ],
-                    "return": "BytesObject",
-                    "docs": "Deploys a contract from the current contract. `wasm_hash` must be a hash of the contract code that has already been installed on this network. `salt` is used to create a unique contract id."
+                    "return": "AddressObject",
+                    "docs": "Creates the contract instance on behalf of `deployer`. `deployer` must authorize this call via Soroban auth framework, i.e. this calls `deployer.require_auth` with respective arguments. `wasm_hash` must be a hash of the contract code that has already been uploaded on this network. `salt` is used to create a unique contract id. Returns the address of the created contract."
                 },
                 {
                     "export": "4",
+                    "name": "create_asset_contract",
+                    "args": [
+                        {
+                            "name": "serialized_asset",
+                            "type": "BytesObject"
+                        }                        
+                    ],
+                    "return": "AddressObject",
+                    "docs": "Creates the instance of Stellar Asset contract corresponding to the provided asset. `serialized_asset` is `stellar::Asset` XDR serialized to bytes format. Returns the address of the created contract."
+                },
+                {
+                    "export": "5",
+                    "name": "upload_wasm",
+                    "args": [
+                        {
+                            "name": "wasm",
+                            "type": "BytesObject"
+                        }
+                    ],
+                    "return": "BytesObject",
+                    "docs": "Uploads provided `wasm` bytecode to the network and returns its identifier (SHA-256 hash). No-op in case if the same Wasm object already exists."
+                },
+                {
+                    "export": "6",
                     "name": "update_current_contract_wasm",
                     "args": [
                         {
@@ -1019,7 +1047,7 @@
                     "args": [
                         {
                             "name": "contract",
-                            "type": "BytesObject"
+                            "type": "AddressObject"
                         },
                         {
                             "name": "func",
@@ -1039,7 +1067,7 @@
                     "args": [
                         {
                             "name": "contract",
-                            "type": "BytesObject"
+                            "type": "AddressObject"
                         },
                         {
                             "name": "func",
diff --git a/soroban-env-common/src/meta.rs b/soroban-env-common/src/meta.rs
index addb1779..622eecef 100644
--- a/soroban-env-common/src/meta.rs
+++ b/soroban-env-common/src/meta.rs
@@ -42,7 +42,7 @@ pub const ENV_META_V0_SECTION_NAME: &str = "contractenvmetav0";
 
 soroban_env_macros::generate_env_meta_consts!(
     ledger_protocol_version: 20,
-    pre_release_version: 40,
+    pre_release_version: 41,
 );
 
 pub fn get_ledger_protocol_version(interface_version: u64) -> u32 {
diff --git a/soroban-env-host/src/auth.rs b/soroban-env-host/src/auth.rs
index ec5fc684..83a7075d 100644
--- a/soroban-env-host/src/auth.rs
+++ b/soroban-env-host/src/auth.rs
@@ -2,9 +2,10 @@ use std::collections::HashMap;
 use std::rc::Rc;
 
 use soroban_env_common::xdr::{
-    ContractAuth, ContractDataEntry, HashIdPreimage, HashIdPreimageContractAuth, LedgerEntry,
-    LedgerEntryData, LedgerEntryExt, ScAddress, ScErrorCode, ScErrorType, ScNonceKey, ScSymbol,
-    ScVal,
+    ContractDataEntry, CreateContractArgs, HashIdPreimage, HashIdPreimageSorobanAuthorization,
+    LedgerEntry, LedgerEntryData, LedgerEntryExt, ScAddress, ScErrorCode, ScErrorType, ScNonceKey,
+    ScSymbol, ScVal, SorobanAuthorizationEntry, SorobanAuthorizedContractFunction,
+    SorobanAuthorizedFunction, SorobanCredentials,
 };
 use soroban_env_common::RawVal;
 
@@ -25,7 +26,7 @@ use super::xdr::{Hash, ScVec};
 // invocation trees as well as recording the authorization requirements in
 // simulated environments (such as tests or preflight).
 #[derive(Clone)]
-pub(crate) struct AuthorizationManager {
+pub struct AuthorizationManager {
     // Mode of operation of this AuthorizationManager. This can't be changed; in
     // order to switch the mode a new instance of AuthorizationManager has to
     // be created.
@@ -36,7 +37,7 @@ pub(crate) struct AuthorizationManager {
     trackers: Vec<AuthorizationTracker>,
     // Current call stack consisting only of the contract invocations (i.e. not
     // the host functions).
-    call_stack: Vec<ContractInvocation>,
+    call_stack: Vec<AuthStackFrame>,
     budget: Budget,
 }
 
@@ -46,7 +47,7 @@ pub(crate) struct AuthorizationManager {
 pub struct RecordedAuthPayload {
     pub address: Option<ScAddress>,
     pub nonce: Option<u64>,
-    pub invocation: xdr::AuthorizedInvocation,
+    pub invocation: xdr::SorobanAuthorizedInvocation,
 }
 
 // Snapshot of `AuthorizationManager` to use when performing the callstack
@@ -116,64 +117,144 @@ struct AuthorizationTracker {
     nonce: Option<u64>,
 }
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
-pub(crate) struct ContractInvocation {
-    pub(crate) contract_id: Hash,
+#[derive(Clone)]
+enum AuthStackFrame {
+    Contract(ContractInvocation),
+    CreateContractHostFn(CreateContractArgs),
+}
+
+#[derive(Clone)]
+struct ContractInvocation {
+    pub(crate) contract_address: ScAddress,
+    pub(crate) function_name: ScSymbol,
+}
+
+#[derive(Clone, Eq, PartialEq)]
+pub(crate) struct ContractFunction {
+    pub(crate) contract_address: ScAddress,
     pub(crate) function_name: ScSymbol,
+    pub(crate) args: ScVec,
+}
+
+#[derive(Clone, Eq, PartialEq)]
+pub(crate) enum AuthorizedFunction {
+    ContractFn(ContractFunction),
+    CreateContractHostFn(CreateContractArgs),
 }
 
 // A single node in the authorized invocation tree.
 // This represents an invocation and all it's authorized sub-invocations.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Clone)]
 pub(crate) struct AuthorizedInvocation {
-    pub(crate) contract_id: Hash,
-    pub(crate) function_name: ScSymbol,
-    pub(crate) args: ScVec,
+    pub(crate) function: AuthorizedFunction,
     pub(crate) sub_invocations: Vec<AuthorizedInvocation>,
     // Indicates that this invocation has been already used in the
     // enforcing mode. Exhausted authorizations can't be reused.
     // In the recording mode this is immediately set to `true` (as the
-    // authorizations are recorded when the actually happen).
+    // authorizations are recorded when they actually happen).
     is_exhausted: bool,
 }
 
+impl AuthStackFrame {
+    fn to_authorized_function(
+        &self,
+        args: ScVec,
+        budget: &Budget,
+    ) -> Result<AuthorizedFunction, HostError> {
+        match self {
+            AuthStackFrame::Contract(contract_frame) => {
+                Ok(AuthorizedFunction::ContractFn(ContractFunction {
+                    contract_address: contract_frame.contract_address.metered_clone(budget)?,
+                    function_name: contract_frame.function_name.metered_clone(budget)?,
+                    args,
+                }))
+            }
+            AuthStackFrame::CreateContractHostFn(args) => Ok(
+                AuthorizedFunction::CreateContractHostFn(args.metered_clone(budget)?),
+            ),
+        }
+    }
+}
+
+impl AuthorizedFunction {
+    fn from_xdr(xdr_fn: SorobanAuthorizedFunction) -> Self {
+        match xdr_fn {
+            SorobanAuthorizedFunction::ContractFn(xdr_contract_fn) => {
+                AuthorizedFunction::ContractFn(ContractFunction {
+                    contract_address: xdr_contract_fn.contract_address,
+                    function_name: xdr_contract_fn.function_name,
+                    args: xdr_contract_fn.args,
+                })
+            }
+            SorobanAuthorizedFunction::CreateContractHostFn(xdr_args) => {
+                AuthorizedFunction::CreateContractHostFn(xdr_args)
+            }
+        }
+    }
+
+    fn to_xdr(&self, budget: &Budget) -> Result<SorobanAuthorizedFunction, HostError> {
+        match self {
+            AuthorizedFunction::ContractFn(contract_fn) => Ok(
+                SorobanAuthorizedFunction::ContractFn(SorobanAuthorizedContractFunction {
+                    contract_address: contract_fn.contract_address.metered_clone(budget)?,
+                    function_name: contract_fn.function_name.metered_clone(budget)?,
+                    args: contract_fn.args.metered_clone(budget)?,
+                }),
+            ),
+            AuthorizedFunction::CreateContractHostFn(create_contract_args) => {
+                Ok(SorobanAuthorizedFunction::CreateContractHostFn(
+                    create_contract_args.metered_clone(budget)?,
+                ))
+            }
+        }
+    }
+
+    fn to_xdr_non_metered(&self) -> xdr::SorobanAuthorizedFunction {
+        match self {
+            AuthorizedFunction::ContractFn(contract_fn) => {
+                SorobanAuthorizedFunction::ContractFn(SorobanAuthorizedContractFunction {
+                    contract_address: contract_fn.contract_address.clone(),
+                    function_name: contract_fn.function_name.clone(),
+                    args: contract_fn.args.clone(),
+                })
+            }
+            AuthorizedFunction::CreateContractHostFn(create_contract_args) => {
+                SorobanAuthorizedFunction::CreateContractHostFn(create_contract_args.clone())
+            }
+        }
+    }
+}
+
 impl AuthorizedInvocation {
-    fn from_xdr(xdr_invocation: xdr::AuthorizedInvocation) -> Result<Self, HostError> {
+    fn from_xdr(xdr_invocation: xdr::SorobanAuthorizedInvocation) -> Result<Self, HostError> {
         let sub_invocations_xdr = xdr_invocation.sub_invocations.into_vec();
         let sub_invocations = sub_invocations_xdr
             .into_iter()
             .map(AuthorizedInvocation::from_xdr)
             .collect::<Result<Vec<_>, _>>()?;
         Ok(Self {
-            contract_id: xdr_invocation.contract_id,
-            function_name: xdr_invocation.function_name,
-            args: xdr_invocation.args,
+            function: AuthorizedFunction::from_xdr(xdr_invocation.function),
             sub_invocations,
             is_exhausted: false,
         })
     }
 
-    fn to_xdr(&self, budget: &Budget) -> Result<xdr::AuthorizedInvocation, HostError> {
-        Ok(xdr::AuthorizedInvocation {
-            contract_id: self.contract_id.metered_clone(budget)?,
-            // This ideally should be infallible
-            function_name: self.function_name.clone(),
-            args: self.args.metered_clone(budget)?,
+    fn to_xdr(&self, budget: &Budget) -> Result<xdr::SorobanAuthorizedInvocation, HostError> {
+        Ok(xdr::SorobanAuthorizedInvocation {
+            function: self.function.to_xdr(budget)?,
             sub_invocations: self
                 .sub_invocations
                 .iter()
                 .map(|i| i.to_xdr(budget))
-                .collect::<Result<Vec<xdr::AuthorizedInvocation>, HostError>>()?
+                .collect::<Result<Vec<xdr::SorobanAuthorizedInvocation>, HostError>>()?
                 .try_into()
                 .map_err(|_| HostError::from((ScErrorType::Auth, ScErrorCode::InternalError)))?,
         })
     }
 
-    fn new_recording(contract_id: &Hash, function_name: &ScSymbol, args: ScVec) -> Self {
+    fn new_recording(function: AuthorizedFunction) -> Self {
         Self {
-            contract_id: contract_id.clone(),
-            function_name: function_name.clone(),
-            args,
+            function,
             sub_invocations: vec![],
             is_exhausted: true,
         }
@@ -181,17 +262,14 @@ impl AuthorizedInvocation {
 
     // Non-metered conversion should only be used for the recording preflight
     // runs.
-    fn to_xdr_non_metered(&self) -> Result<xdr::AuthorizedInvocation, HostError> {
-        Ok(xdr::AuthorizedInvocation {
-            contract_id: self.contract_id.clone(),
-            // This ideally should be infallible
-            function_name: self.function_name.clone(),
-            args: self.args.clone(),
+    fn to_xdr_non_metered(&self) -> Result<xdr::SorobanAuthorizedInvocation, HostError> {
+        Ok(xdr::SorobanAuthorizedInvocation {
+            function: self.function.to_xdr_non_metered(),
             sub_invocations: self
                 .sub_invocations
                 .iter()
                 .map(|i| i.to_xdr_non_metered())
-                .collect::<Result<Vec<xdr::AuthorizedInvocation>, HostError>>()?
+                .collect::<Result<Vec<xdr::SorobanAuthorizedInvocation>, HostError>>()?
                 .try_into()
                 .map_err(|_| HostError::from((ScErrorType::Auth, ScErrorCode::InternalError)))?,
         })
@@ -230,10 +308,10 @@ impl Default for AuthorizationManager {
 impl AuthorizationManager {
     // Creates a new enforcing `AuthorizationManager` from the given
     // authorization entries.
-    // This should be created once per top-level contract invocation.
+    // This should be created once per top-level invocation.
     pub(crate) fn new_enforcing(
         host: &Host,
-        auth_entries: Vec<ContractAuth>,
+        auth_entries: Vec<SorobanAuthorizationEntry>,
     ) -> Result<Self, HostError> {
         let mut trackers = vec![];
         for auth_entry in auth_entries {
@@ -275,10 +353,6 @@ impl AuthorizationManager {
         }
     }
 
-    pub(crate) fn is_recording(&self) -> bool {
-        matches!(self.mode, AuthorizationMode::Recording(_))
-    }
-
     // Require the `address` to have authorized the current contract invocation
     // with provided args and within the current context (i.e. the current
     // authorized call stack and for the current network).
@@ -291,115 +365,135 @@ impl AuthorizationManager {
         address: ScAddress,
         args: ScVec,
     ) -> Result<(), HostError> {
-        if let ScAddress::Contract(contract_addr) = &address {
-            // For now we give a blanket approval of the invoker contract to any
-            // calls it made, but never to the deeper calls. It's possible
-            // to eventually add a capability to pre-authorize arbitrary call
-            // stacks on behalf of the contract.
-            if let Ok(invoker_contract) = host.get_invoking_contract_internal() {
-                if &invoker_contract == contract_addr {
-                    return Ok(());
-                }
-            }
+        let curr_invocation = self.call_stack.last().ok_or_else(|| {
+            host.err(
+                ScErrorType::Auth,
+                ScErrorCode::InternalError,
+                "unexpected require_auth outside of contract",
+                &[],
+            )
+        })?;
+        self.require_auth_internal(
+            host,
+            address_obj_handle,
+            address,
+            curr_invocation.to_authorized_function(args, &self.budget)?,
+        )
+    }
+
+    fn verify_contract_invoker_auth(&self, contract_id: &ScAddress) -> bool {
+        if self.call_stack.len() < 2 {
+            return false;
+        }
+        let invoker_frame = &self.call_stack[self.call_stack.len() - 2];
+        if let AuthStackFrame::Contract(invoker_contract) = invoker_frame {
+            return contract_id == &invoker_contract.contract_address;
         }
+        return false;
+    }
 
-        if let Some(curr_invocation) = self.call_stack.last() {
-            match &mut self.mode {
-                AuthorizationMode::Enforcing => {
-                    // Iterate all the trackers and try to find one that
-                    // fullfills the authorization requirement.
-                    for tracker in &mut self.trackers {
-                        let address_matches = if let Some(addr) = &tracker.address {
-                            addr == &address
-                        } else {
-                            // Lazily fill the address for the invoker trackers,
-                            // so that it's possible to create the auth manager
-                            // without knowing the invoker beforehand and also
-                            // to not keep calling into `source_account` function.
-                            let source_addr =
-                                ScAddress::Account(host.source_account().ok_or_else(|| {
-                                    host.err(
-                                        ScErrorType::Auth,
-                                        ScErrorCode::InternalError,
-                                        "unexpected missing invoker in auth manager",
-                                        &[],
-                                    )
-                                })?);
-                            let source_matches = source_addr == address;
-                            tracker.address = Some(source_addr);
-                            source_matches
-                        };
-                        // If address doesn't match, just skip the tracker.
-                        if address_matches {
-                            match tracker.maybe_authorize_invocation(
-                                host,
-                                &curr_invocation.contract_id,
-                                &curr_invocation.function_name,
-                                &args,
-                            ) {
-                                // If tracker doesn't have a matching invocation,
-                                // just skip it (there could still be another
-                                // tracker  that matches it).
-                                Ok(false) => continue,
-                                // Found a matching authorization.
-                                Ok(true) => return Ok(()),
-                                // Found a matching authorization, but another
-                                // requirement hasn't been fullfilled (for
-                                // example, incorrect authentication or nonce).
-                                Err(e) => return Err(e),
-                            }
-                        }
-                    }
-                    // No matching tracker found, hence the invocation isn't
-                    // authorized.
-                    Err(HostError::from((
+    fn require_auth_enforcing(
+        &mut self,
+        host: &Host,
+        address: &ScAddress,
+        function: &AuthorizedFunction,
+    ) -> Result<(), HostError> {
+        // Iterate all the trackers and try to find one that
+        // fullfills the authorization requirement.
+        for tracker in &mut self.trackers {
+            let address_matches = if let Some(addr) = &tracker.address {
+                addr == address
+            } else {
+                // Lazily fill the address for the invoker trackers,
+                // so that it's possible to create the auth manager
+                // without knowing the invoker beforehand and also
+                // to not keep calling into `source_account` function.
+                let source_addr = ScAddress::Account(host.source_account().ok_or_else(|| {
+                    host.err(
                         ScErrorType::Auth,
-                        ScErrorCode::InvalidAction,
-                    )))
-                }
-                AuthorizationMode::Recording(recording_info) => {
-                    if let Some(tracker_id) = recording_info
-                        .tracker_by_address_handle
-                        .get(&address_obj_handle)
-                    {
-                        let tracker = &mut self.trackers[*tracker_id];
-                        // The recording invariant is that trackers are created
-                        // with the first authorized invocation, which means
-                        // that when their stack no longer has authorized
-                        // invocation, then we've popped frames past its root
-                        // and hence need to create a new tracker.
-                        if !tracker.has_authorized_invocations_in_stack() {
-                            recording_info
-                                .tracker_by_address_handle
-                                .remove(&address_obj_handle);
-                        } else {
-                            return self.trackers[*tracker_id].record_invocation(
-                                host,
-                                &curr_invocation.contract_id,
-                                &curr_invocation.function_name,
-                                args,
-                            );
-                        }
+                        ScErrorCode::InternalError,
+                        "unexpected missing invoker in auth manager",
+                        &[],
+                    )
+                })?);
+                let source_matches = &source_addr == address;
+                tracker.address = Some(source_addr);
+                source_matches
+            };
+            // If address doesn't match, just skip the tracker.
+            if !address_matches {
+                continue;
+            }
+            match tracker.maybe_authorize_invocation(host, function) {
+                // If tracker doesn't have a matching invocation,
+                // just skip it (there could still be another
+                // tracker  that matches it).
+                Ok(false) => continue,
+                // Found a matching authorization.
+                Ok(true) => return Ok(()),
+                // Found a matching authorization, but another
+                // requirement hasn't been fullfilled (for
+                // example, incorrect authentication or nonce).
+                Err(e) => return Err(e),
+            }
+        }
+        // No matching tracker found, hence the invocation isn't
+        // authorized.
+        Err(HostError::from((
+            ScErrorType::Auth,
+            ScErrorCode::InvalidAction,
+        )))
+    }
+
+    fn require_auth_internal(
+        &mut self,
+        host: &Host,
+        address_obj_handle: u32,
+        address: ScAddress,
+        function: AuthorizedFunction,
+    ) -> Result<(), HostError> {
+        // For now we give a blanket approval of the invoker contract to any
+        // calls it made, but never to the deeper calls. It's possible
+        // to eventually add a capability to pre-authorize arbitrary call
+        // stacks on behalf of the contract.
+        if self.verify_contract_invoker_auth(&address) {
+            return Ok(());
+        }
+
+        match &mut self.mode {
+            AuthorizationMode::Enforcing => self.require_auth_enforcing(host, &address, &function),
+            AuthorizationMode::Recording(recording_info) => {
+                if let Some(tracker_id) = recording_info
+                    .tracker_by_address_handle
+                    .get(&address_obj_handle)
+                {
+                    let tracker = &mut self.trackers[*tracker_id];
+                    // The recording invariant is that trackers are created
+                    // with the first authorized invocation, which means
+                    // that when their stack no longer has authorized
+                    // invocation, then we've popped frames past its root
+                    // and hence need to create a new tracker.
+                    if !tracker.has_authorized_invocations_in_stack() {
+                        recording_info
+                            .tracker_by_address_handle
+                            .remove(&address_obj_handle);
+                    } else {
+                        return self.trackers[*tracker_id].record_invocation(host, function);
                     }
-                    // If a tracker for the new tree doesn't exist yet, create
-                    // it and initialize with the current invocation.
-                    self.trackers.push(AuthorizationTracker::new_recording(
-                        host,
-                        address,
-                        &curr_invocation.contract_id,
-                        &curr_invocation.function_name,
-                        args,
-                        self.call_stack.len(),
-                    )?);
-                    recording_info
-                        .tracker_by_address_handle
-                        .insert(address_obj_handle, self.trackers.len() - 1);
-                    Ok(())
                 }
+                // If a tracker for the new tree doesn't exist yet, create
+                // it and initialize with the current invocation.
+                self.trackers.push(AuthorizationTracker::new_recording(
+                    host,
+                    address,
+                    function,
+                    self.call_stack.len(),
+                )?);
+                recording_info
+                    .tracker_by_address_handle
+                    .insert(address_obj_handle, self.trackers.len() - 1);
+                Ok(())
             }
-        } else {
-            // This would be a bug
-            Err((ScErrorType::Auth, ScErrorCode::InternalError).into())
         }
     }
 
@@ -430,6 +524,14 @@ impl AuthorizationManager {
         }
     }
 
+    pub(crate) fn push_create_contract_host_fn_frame(&mut self, args: CreateContractArgs) {
+        self.call_stack
+            .push(AuthStackFrame::CreateContractHostFn(args));
+        for tracker in &mut self.trackers {
+            tracker.push_frame();
+        }
+    }
+
     // Records a new call stack frame.
     // This should be called for every `Host` `push_frame`.
     pub(crate) fn push_frame(&mut self, host: &Host, frame: &Frame) -> Result<(), HostError> {
@@ -437,21 +539,26 @@ impl AuthorizationManager {
             Frame::ContractVM(vm, fn_name, _) => {
                 (vm.contract_id.metered_clone(&self.budget)?, *fn_name)
             }
-            // Just skip the host function stack frames for now.
-            // We could also make this included into the authorized stack to
-            // generalize all the host function invocations.
+            // Skip the top-level host function stack frames as they don't
+            // contain all the necessary information.
+            // Use the respective push (like
+            // `push_create_contract_host_fn_frame`) functions instead to push
+            // the frame with the required info.
             Frame::HostFunction(_) => return Ok(()),
             Frame::Token(id, fn_name, _) => (id.metered_clone(&self.budget)?, *fn_name),
             #[cfg(any(test, feature = "testutils"))]
             Frame::TestContract(tc) => (tc.id.clone(), tc.func),
         };
+        // Currently only contracts might appear in the call stack.
+        let contract_address = ScAddress::Contract(contract_id);
         let Ok(ScVal::Symbol(function_name)) = host.from_host_val(function_name.to_raw()) else {
             return Err(host.err(ScErrorType::Auth, ScErrorCode::InternalError, "frame function name conversion failed", &[]))
         };
-        self.call_stack.push(ContractInvocation {
-            contract_id,
-            function_name,
-        });
+        self.call_stack
+            .push(AuthStackFrame::Contract(ContractInvocation {
+                contract_address,
+                function_name,
+            }));
         for tracker in &mut self.trackers {
             tracker.push_frame();
         }
@@ -523,35 +630,12 @@ impl AuthorizationManager {
         }
     }
 
-    // Returns the top-level authorizations that have been authenticated for the
-    // last contract invocation.
-    #[cfg(any(test, feature = "testutils"))]
-    pub(crate) fn get_authenticated_top_authorizations(
-        &self,
-    ) -> Vec<(ScAddress, Hash, ScSymbol, ScVec)> {
-        self.trackers
-            .iter()
-            .filter(|t| t.authenticated)
-            .filter_map(|t| {
-                // Ignore authorizations without an address as they are implied,
-                // less useful as a test utility, and not succinctly capturable
-                // in the list of tuples. This is a tradeoff between offering up
-                // all authorizations vs the authorizations developers will
-                // mostly care about at the benefit of making this list easier
-                // to use.
-                t.address.as_ref().map(|a| {
-                    AuthorizationManager::invocation_to_tuple(a, &t.root_authorized_invocation)
-                })
-            })
-            .collect()
-    }
-
     // Returns all authorizations that have been authenticated for the
     // last contract invocation.
     #[cfg(any(test, feature = "testutils"))]
     pub(crate) fn get_authenticated_authorizations(
         &self,
-    ) -> Vec<(ScAddress, Hash, ScSymbol, ScVec)> {
+    ) -> Vec<(ScAddress, xdr::SorobanAuthorizedInvocation)> {
         self.trackers
             .iter()
             .filter(|t| t.authenticated)
@@ -565,13 +649,13 @@ impl AuthorizationManager {
                 t.address.as_ref().map(|a| {
                     fn add_recursively_to_auths(
                         a: &ScAddress,
-                        auths: &mut Vec<(ScAddress, Hash, ScSymbol, ScVec)>,
+                        auths: &mut Vec<(ScAddress, xdr::SorobanAuthorizedInvocation)>,
                         i: &AuthorizedInvocation,
                     ) {
                         // Is exhausted indicates if the auth was in fact
                         // consumed by a call to require_auth.
                         if i.is_exhausted {
-                            auths.push(AuthorizationManager::invocation_to_tuple(a, i));
+                            auths.push((a.clone(), i.to_xdr_non_metered().unwrap()));
                         }
                         for sub in &i.sub_invocations {
                             add_recursively_to_auths(a, auths, sub);
@@ -585,38 +669,26 @@ impl AuthorizationManager {
             .flatten()
             .collect()
     }
-
-    #[cfg(any(test, feature = "testutils"))]
-    // Builds a tuple containing the common details exposed from the
-    // AuthorizationManager about authenticated authorizations.
-    fn invocation_to_tuple(
-        address: &ScAddress,
-        authorized_invocation: &AuthorizedInvocation,
-    ) -> (ScAddress, Hash, ScSymbol, ScVec) {
-        (
-            address.clone(),
-            authorized_invocation.contract_id.clone(),
-            authorized_invocation.function_name.clone(),
-            authorized_invocation.args.clone(),
-        )
-    }
 }
 
 impl AuthorizationTracker {
-    fn from_authorization_entry(host: &Host, auth_entry: ContractAuth) -> Result<Self, HostError> {
-        let is_invoker = auth_entry.address_with_nonce.is_none();
-        let (address, nonce) = if let Some(address_with_nonce) = auth_entry.address_with_nonce {
-            (
-                Some(address_with_nonce.address),
-                Some(address_with_nonce.nonce),
-            )
-        } else {
-            (None, None)
+    fn from_authorization_entry(
+        host: &Host,
+        auth_entry: SorobanAuthorizationEntry,
+    ) -> Result<Self, HostError> {
+        let (address, nonce, signature_args) = match auth_entry.credentials {
+            SorobanCredentials::SourceAccount => (None, None, vec![]),
+            SorobanCredentials::Address(address_creds) => (
+                Some(address_creds.address),
+                Some(address_creds.nonce),
+                host.scvals_to_rawvals(address_creds.signature_args.0.as_slice())?,
+            ),
         };
+        let is_invoker = address.is_none();
         Ok(Self {
             address,
             root_authorized_invocation: AuthorizedInvocation::from_xdr(auth_entry.root_invocation)?,
-            signature_args: host.scvals_to_rawvals(auth_entry.signature_args.0.as_slice())?,
+            signature_args,
             authenticated: false,
             need_nonce: !is_invoker,
             is_invoker,
@@ -629,9 +701,7 @@ impl AuthorizationTracker {
     fn new_recording(
         host: &Host,
         address: ScAddress,
-        contract_id: &Hash,
-        function_name: &ScSymbol,
-        args: ScVec,
+        function: AuthorizedFunction,
         current_stack_len: usize,
     ) -> Result<Self, HostError> {
         if current_stack_len == 0 {
@@ -652,7 +722,7 @@ impl AuthorizationTracker {
             false
         };
         let nonce = if !is_invoker {
-            Some(host.read_and_consume_nonce(contract_id, &address)?)
+            Some(host.read_and_consume_nonce(address.metered_clone(host.budget_ref())?, &function)?)
         } else {
             None
         };
@@ -664,11 +734,7 @@ impl AuthorizationTracker {
         invocation_id_in_call_stack.push(Some(0));
         Ok(Self {
             address: Some(address),
-            root_authorized_invocation: AuthorizedInvocation::new_recording(
-                contract_id,
-                function_name,
-                args,
-            ),
+            root_authorized_invocation: AuthorizedInvocation::new_recording(function),
             invocation_id_in_call_stack,
             signature_args: Default::default(),
             is_valid: true,
@@ -690,9 +756,7 @@ impl AuthorizationTracker {
     fn maybe_authorize_invocation(
         &mut self,
         host: &Host,
-        contract_id: &Hash,
-        function_name: &ScSymbol,
-        args: &ScVec,
+        function: &AuthorizedFunction,
     ) -> Result<bool, HostError> {
         if !self.is_valid {
             return Ok(false);
@@ -701,9 +765,7 @@ impl AuthorizationTracker {
             Some(Some(_)) => true,
             _ => false,
         };
-        if frame_is_already_authorized
-            || !self.maybe_push_matching_invocation_frame(contract_id, function_name, args)
-        {
+        if frame_is_already_authorized || !self.maybe_push_matching_invocation_frame(function) {
             // The call isn't found in the currently tracked tree or is already
             // authorized in it.
             // That doesn't necessarily mean it's unauthorized (it can be
@@ -730,9 +792,7 @@ impl AuthorizationTracker {
     fn record_invocation(
         &mut self,
         host: &Host,
-        contract_id: &Hash,
-        function_name: &ScSymbol,
-        args: ScVec,
+        function: AuthorizedFunction,
     ) -> Result<(), HostError> {
         let frame_is_already_authorized = match self.invocation_id_in_call_stack.last() {
             Some(Some(_)) => true,
@@ -749,11 +809,7 @@ impl AuthorizationTracker {
         if let Some(curr_invocation) = self.last_authorized_invocation_mut() {
             curr_invocation
                 .sub_invocations
-                .push(AuthorizedInvocation::new_recording(
-                    contract_id,
-                    function_name,
-                    args,
-                ));
+                .push(AuthorizedInvocation::new_recording(function));
             *self.invocation_id_in_call_stack.last_mut().unwrap() =
                 Some(curr_invocation.sub_invocations.len() - 1);
         } else {
@@ -788,7 +844,10 @@ impl AuthorizationTracker {
         self.invocation_id_in_call_stack.iter().any(|i| i.is_some())
     }
 
-    fn invocation_to_xdr(&self, budget: &Budget) -> Result<xdr::AuthorizedInvocation, HostError> {
+    fn invocation_to_xdr(
+        &self,
+        budget: &Budget,
+    ) -> Result<xdr::SorobanAuthorizedInvocation, HostError> {
         self.root_authorized_invocation.to_xdr(budget)
     }
 
@@ -810,8 +869,8 @@ impl AuthorizationTracker {
         self.need_nonce = false;
         if let Some(addr) = &self.address {
             Ok(Some(host.read_and_consume_nonce(
-                &self.root_authorized_invocation.contract_id,
-                addr,
+                addr.metered_clone(host.budget_ref())?,
+                &self.root_authorized_invocation.function,
             )?))
         } else {
             Ok(None)
@@ -835,30 +894,21 @@ impl AuthorizationTracker {
     // Tries to match the provided invocation to the authorized sub-invocation
     // of the current tree and push it to the call stack.
     // Returns `true` if the match has been found.
-    fn maybe_push_matching_invocation_frame(
-        &mut self,
-        contract_id: &Hash,
-        function_name: &ScSymbol,
-        args: &ScVec,
-    ) -> bool {
+    fn maybe_push_matching_invocation_frame(&mut self, function: &AuthorizedFunction) -> bool {
         let mut frame_index = None;
         if let Some(curr_invocation) = self.last_authorized_invocation_mut() {
             for i in 0..curr_invocation.sub_invocations.len() {
                 let sub_invocation = &mut curr_invocation.sub_invocations[i];
-                if !sub_invocation.is_exhausted
-                    && &sub_invocation.contract_id == contract_id
-                    && &sub_invocation.function_name == function_name
-                    && &sub_invocation.args == args
-                {
+                // TODO: the equality comparison should be metered.
+                if !sub_invocation.is_exhausted && &sub_invocation.function == function {
                     frame_index = Some(i);
                     sub_invocation.is_exhausted = true;
                     break;
                 }
             }
         } else if !self.root_authorized_invocation.is_exhausted
-            && &self.root_authorized_invocation.contract_id == contract_id
-            && &self.root_authorized_invocation.function_name == function_name
-            && &self.root_authorized_invocation.args == args
+            // TODO: the equality comparison should be metered.
+            && &self.root_authorized_invocation.function == function
         {
             frame_index = Some(0);
             self.root_authorized_invocation.is_exhausted = true;
@@ -897,20 +947,21 @@ impl AuthorizationTracker {
     // Computes the payload that has to be signed in order to authenticate
     // the authorized invocation tree corresponding to this tracker.
     fn get_signature_payload(&self, host: &Host) -> Result<[u8; 32], HostError> {
-        let payload_preimage = HashIdPreimage::ContractAuth(HashIdPreimageContractAuth {
-            network_id: Hash(
-                host.with_ledger_info(|li| li.network_id.metered_clone(host.budget_ref()))?,
-            ),
-            invocation: self.invocation_to_xdr(host.budget_ref())?,
-            nonce: self.nonce.ok_or_else(|| {
-                host.err(
-                    ScErrorType::Auth,
-                    ScErrorCode::InternalError,
-                    "unexpected missing nonce",
-                    &[],
-                )
-            })?,
-        });
+        let payload_preimage =
+            HashIdPreimage::SorobanAuthorization(HashIdPreimageSorobanAuthorization {
+                network_id: Hash(
+                    host.with_ledger_info(|li| li.network_id.metered_clone(host.budget_ref()))?,
+                ),
+                invocation: self.invocation_to_xdr(host.budget_ref())?,
+                nonce: self.nonce.ok_or_else(|| {
+                    host.err(
+                        ScErrorType::Auth,
+                        ScErrorCode::InternalError,
+                        "unexpected missing nonce",
+                        &[],
+                    )
+                })?,
+            });
 
         host.metered_hash_xdr(&payload_preimage)
     }
@@ -980,15 +1031,28 @@ impl Host {
     #[cfg(test)]
     pub(crate) fn read_nonce(
         &self,
-        contract_id: &Hash,
-        address: &ScAddress,
+        address: ScAddress,
+        function: &AuthorizedFunction,
     ) -> Result<u64, HostError> {
         let nonce_key_scval = ScVal::LedgerKeyNonce(ScNonceKey {
-            nonce_address: address.metered_clone(self.budget_ref())?,
+            nonce_address: address,
         });
+        let contract_id = match function {
+            AuthorizedFunction::ContractFn(contract_fn) => self.contract_id_from_scaddress(
+                contract_fn
+                    .contract_address
+                    .metered_clone(self.budget_ref())?,
+            )?,
+            AuthorizedFunction::CreateContractHostFn(_) => {
+                // Use the special contract id for all the host fn nonces for
+                // now. This should soon be replaced by non-autoincrement nonce
+                // that is independent of the authorized function.
+                Hash([255; 32])
+            }
+        };
         let nonce_key = self.storage_key_for_contract(
-            contract_id.metered_clone(self.budget_ref())?,
-            nonce_key_scval,
+            contract_id,
+            nonce_key_scval.metered_clone(self.budget_ref())?,
         );
         let curr_nonce: u64 =
             if self.with_mut_storage(|storage| storage.has(&nonce_key, self.budget_ref()))? {
@@ -1023,15 +1087,28 @@ impl Host {
 
     fn read_and_consume_nonce(
         &self,
-        contract_id: &Hash,
-        address: &ScAddress,
+        address: ScAddress,
+        function: &AuthorizedFunction,
     ) -> Result<u64, HostError> {
         let nonce_key_scval = ScVal::LedgerKeyNonce(ScNonceKey {
-            nonce_address: address.metered_clone(self.budget_ref())?,
+            nonce_address: address,
         });
+        let contract_id = match function {
+            AuthorizedFunction::ContractFn(contract_fn) => self.contract_id_from_scaddress(
+                contract_fn
+                    .contract_address
+                    .metered_clone(self.budget_ref())?,
+            )?,
+            AuthorizedFunction::CreateContractHostFn(_) => {
+                // Use the special contract id for all the host fn nonces for
+                // now. This should soon be replaced by non-autoincrement nonce
+                // that is independent of the authorized function.
+                Hash([255; 32])
+            }
+        };
         let nonce_key = self.storage_key_for_contract(
             contract_id.metered_clone(self.budget_ref())?,
-            nonce_key_scval.clone(),
+            nonce_key_scval.metered_clone(self.budget_ref())?,
         );
         let curr_nonce: u64 =
             if self.with_mut_storage(|storage| storage.has(&nonce_key, self.budget_ref()))? {
@@ -1062,7 +1139,7 @@ impl Host {
                 0
             };
         let data = LedgerEntryData::ContractData(ContractDataEntry {
-            contract_id: contract_id.metered_clone(self.budget_ref())?,
+            contract_id,
             key: nonce_key_scval,
             val: ScVal::U64(curr_nonce + 1),
         });
diff --git a/soroban-env-host/src/host.rs b/soroban-env-host/src/host.rs
index 6c9f72ea..6f5fb938 100644
--- a/soroban-env-host/src/host.rs
+++ b/soroban-env-host/src/host.rs
@@ -14,9 +14,9 @@ use crate::{
     storage::Storage,
     xdr::{
         int128_helpers, AccountId, Asset, ContractCodeEntry, ContractCostType, ContractDataEntry,
-        ContractEventType, ContractId, CreateContractArgs, ExtensionPoint, Hash, HashIdPreimage,
-        LedgerEntryData, LedgerKey, LedgerKeyContractCode, PublicKey, ScAddress, ScBytes,
-        ScContractExecutable, ScErrorType, ScString, ScSymbol, ScVal, UploadContractWasmArgs,
+        ContractEventType, CreateContractArgs, ExtensionPoint, Hash, LedgerEntryData, LedgerKey,
+        LedgerKeyContractCode, PublicKey, ScAddress, ScBytes, ScContractExecutable, ScErrorType,
+        ScString, ScSymbol, ScVal,
     },
     AddressObject, Bool, BytesObject, Error, I128Object, I256Object, I64Object, MapObject,
     StringObject, SymbolObject, SymbolSmall, SymbolStr, TryFromVal, U128Object, U256Object, U32Val,
@@ -42,7 +42,7 @@ mod prng;
 pub use prng::{Seed, SEED_BYTES};
 mod validity;
 pub use error::HostError;
-use soroban_env_common::xdr::ScErrorCode;
+use soroban_env_common::xdr::{ContractIdPreimage, ContractIdPreimageFromAddress, ScErrorCode};
 
 use self::metered_clone::MeteredClone;
 use self::{
@@ -52,10 +52,12 @@ use self::{
 };
 use crate::Compare;
 #[cfg(any(test, feature = "testutils"))]
-use crate::{xdr::ScVec, TryIntoVal};
+use crate::TryIntoVal;
 pub(crate) use frame::Frame;
 #[cfg(any(test, feature = "testutils"))]
 pub use frame::{ContractFunctionSet, TestContractFrame};
+#[cfg(any(test, feature = "testutils"))]
+use soroban_env_common::xdr::SorobanAuthorizedInvocation;
 
 /// Temporary helper for denoting a slice of guest memory, as formed by
 /// various bytes operations.
@@ -100,8 +102,8 @@ pub(crate) struct HostImpl {
     // invocation. In order to emulate the production behavior in tests, we reset
     // authorization manager after every invocation (as it's not meant to be
     // shared between invocations).
-    // This enables test-only functions like `verify_top_authorization`
-    // that allow checking if the authorization has been recorded.
+    // This enables test-only functions that allow checking if the authorization
+    // has happened or has been recorded.
     #[cfg(any(test, feature = "testutils"))]
     previous_authorization_manager: RefCell<Option<AuthorizationManager>>,
 }
@@ -166,7 +168,7 @@ impl Host {
 
     pub fn set_authorization_entries(
         &self,
-        auth_entries: Vec<soroban_env_common::xdr::ContractAuth>,
+        auth_entries: Vec<soroban_env_common::xdr::SorobanAuthorizationEntry>,
     ) -> Result<(), HostError> {
         let new_auth_manager = AuthorizationManager::new_enforcing(self, auth_entries)?;
         *self.0.authorization_manager.borrow_mut() = new_auth_manager;
@@ -307,6 +309,26 @@ impl Host {
         res
     }
 
+    #[cfg(any(test, feature = "testutils"))]
+    /// Returns the current state of the authorization manager.
+    ///
+    /// Use this in conjunction with `set_auth_manager` to do authorized
+    /// operations without breaking the current authorization state (useful for
+    /// preserving the auth state while doing the generic test setup).
+    pub fn snapshot_auth_manager(&self) -> AuthorizationManager {
+        self.0.authorization_manager.borrow().clone()
+    }
+
+    /// Replaces authorization manager with the provided new instance.
+    ///
+    /// Use this in conjunction with `snapshot_auth_manager` to do authorized
+    /// operations without breaking the current authorization state (useful for
+    /// preserving the auth state while doing the generic test setup).
+    #[cfg(any(test, feature = "testutils"))]
+    pub fn set_auth_manager(&self, auth_manager: AuthorizationManager) {
+        *self.0.authorization_manager.borrow_mut() = auth_manager;
+    }
+
     // Testing interface to create values directly for later use via Env functions.
     // It needs to be a `pub` method because benches are considered a separate crate.
     pub fn inject_val(&self, v: &ScVal) -> Result<RawVal, HostError> {
@@ -316,11 +338,10 @@ impl Host {
     // Notes on metering: this is covered by the called components.
     fn create_contract_with_id(
         &self,
-        contract_id: BytesObject,
-        contract_source: ScContractExecutable,
+        contract_id: Hash,
+        contract_executable: ScContractExecutable,
     ) -> Result<(), HostError> {
-        let new_contract_id = self.hash_from_bytesobj_input("id_obj", contract_id)?;
-        let storage_key = self.contract_executable_ledger_key(&new_contract_id)?;
+        let storage_key = self.contract_executable_ledger_key(&contract_id)?;
         if self
             .0
             .storage
@@ -331,41 +352,44 @@ impl Host {
                 ScErrorType::Storage,
                 ScErrorCode::ExistingValue,
                 "contract already exists",
-                &[contract_id.to_raw()],
+                &[self
+                    .add_host_object(self.scbytes_from_hash(&contract_id)?)?
+                    .into()],
             ));
         }
         // Make sure the contract code exists. Without this check it would be
         // possible to accidentally create a contract that never may be invoked
         // (just by providing a bad hash).
-        if let ScContractExecutable::WasmRef(wasm_hash) = &contract_source {
+        if let ScContractExecutable::WasmRef(wasm_hash) = &contract_executable {
             if !self.contract_code_exists(wasm_hash)? {
                 return Err(err!(
                     self,
                     (ScErrorType::Storage, ScErrorCode::MissingValue),
-                    "WASM does not exist",
+                    "Wasm does not exist",
                     *wasm_hash
                 ));
             }
         }
-        self.store_contract_executable(contract_source, new_contract_id, &storage_key)?;
+        self.store_contract_executable(contract_executable, contract_id, &storage_key)?;
         Ok(())
     }
 
     fn maybe_initialize_asset_token(
         &self,
-        contract_id: BytesObject,
-        id_preimage: HashIdPreimage,
+        contract_id: &Hash,
+        id_preimage: &ContractIdPreimage,
     ) -> Result<(), HostError> {
-        if let HashIdPreimage::ContractIdFromAsset(asset_preimage) = id_preimage {
+        if let ContractIdPreimage::Asset(asset) = id_preimage {
             let mut asset_bytes: Vec<u8> = Default::default();
-            self.metered_write_xdr(&asset_preimage.asset, &mut asset_bytes)?;
-            self.call_n(
+            self.metered_write_xdr(asset, &mut asset_bytes)?;
+            self.call_n_internal(
                 contract_id,
                 Symbol::try_from_val(self, &"init_asset")?,
                 &[self
                     .add_host_object(self.scbytes_from_vec(asset_bytes)?)?
                     .into()],
                 ContractReentryMode::Prohibited,
+                false,
             )?;
             Ok(())
         } else {
@@ -373,20 +397,59 @@ impl Host {
         }
     }
 
-    fn create_contract_with_id_preimage(
+    fn create_contract_internal(
         &self,
-        contract_source: ScContractExecutable,
-        id_preimage: HashIdPreimage,
-    ) -> Result<BytesObject, HostError> {
-        let id_arr: [u8; 32] = self.metered_hash_xdr(&id_preimage)?;
-        let id_obj = self.add_host_object(self.scbytes_from_hash(&Hash(id_arr))?)?;
-        self.create_contract_with_id(id_obj, contract_source.metered_clone(self.budget_ref())?)?;
-        self.maybe_initialize_asset_token(id_obj, id_preimage)?;
-        Ok(id_obj)
+        deployer: Option<AddressObject>,
+        args: CreateContractArgs,
+    ) -> Result<AddressObject, HostError> {
+        let has_deployer = deployer.is_some();
+        if has_deployer {
+            self.0
+                .authorization_manager
+                .borrow_mut()
+                .push_create_contract_host_fn_frame(args.metered_clone(self.budget_ref())?);
+        }
+        // Make sure that even in case of operation failure we still pop the
+        // stack frame.
+        // This is hacky, but currently this is the only instance where we need
+        // to manually manage auth manager frames (we don't need to authorize
+        // any other host fns and it doesn't seem useful to create extra frames
+        // for them just to make auth work in a single case).
+        let res = self.create_contract_with_optional_auth(deployer, args);
+        if has_deployer {
+            self.0.authorization_manager.borrow_mut().pop_frame();
+        }
+        res
+    }
+
+    fn create_contract_with_optional_auth(
+        &self,
+        deployer: Option<AddressObject>,
+        args: CreateContractArgs,
+    ) -> Result<AddressObject, HostError> {
+        if let Some(deployer_address) = deployer {
+            let sc_addr = self.visit_obj(deployer_address, |addr: &ScAddress| {
+                addr.metered_clone(self.budget_ref())
+            })?;
+            self.0.authorization_manager.borrow_mut().require_auth(
+                self,
+                deployer_address.get_handle(),
+                sc_addr,
+                Default::default(),
+            )?;
+        }
+
+        let id_preimage = self.get_full_contract_id_preimage(
+            args.contract_id_preimage.metered_clone(self.budget_ref())?,
+        )?;
+        let hash_id = Hash(self.metered_hash_xdr(&id_preimage)?);
+        self.create_contract_with_id(hash_id.metered_clone(self.budget_ref())?, args.executable)?;
+        self.maybe_initialize_asset_token(&hash_id, &args.contract_id_preimage)?;
+        self.add_host_object(ScAddress::Contract(hash_id))
     }
 
     pub(crate) fn get_contract_id_from_asset(&self, asset: Asset) -> Result<Hash, HostError> {
-        let id_preimage = self.id_preimage_from_asset(asset)?;
+        let id_preimage = self.get_full_contract_id_preimage(ContractIdPreimage::Asset(asset))?;
         let id_arr: [u8; 32] = self.metered_hash_xdr(&id_preimage)?;
         Ok(Hash(id_arr))
     }
@@ -395,10 +458,10 @@ impl Host {
     #[cfg(any(test, feature = "testutils"))]
     pub fn register_test_contract(
         &self,
-        contract_id: BytesObject,
+        contract_address: AddressObject,
         contract_fns: Rc<dyn ContractFunctionSet>,
     ) -> Result<(), HostError> {
-        let hash = self.hash_from_bytesobj_input("contract_id", contract_id)?;
+        let hash = self.contract_id_from_address(contract_address)?;
         let mut contracts = self.0.contracts.borrow_mut();
         contracts.insert(hash, contract_fns);
         Ok(())
@@ -415,37 +478,6 @@ impl Host {
         self.with_mut_storage(|storage| storage.put(key, val, self.as_budget()))
     }
 
-    // Returns the top-level authorizations that have been authenticated for the
-    // last contract invocation.
-    //
-    // Authenticated means that either the authorization was authenticated using
-    // the actual authorization logic for that authorization in enforced mode,
-    // or that it was recorded in recording mode and authorization was assumed
-    // successful.
-    //
-    // More technically, 'top-level' means that these invocations were the first
-    // in the call tree to have called `require_auth` (i.e. they're not
-    // necessarily invocations of the top-level contract that has been invoked).
-    #[cfg(any(test, feature = "testutils"))]
-    pub fn get_authenticated_top_authorizations(
-        &self,
-    ) -> Result<Vec<(ScAddress, Hash, ScSymbol, ScVec)>, HostError> {
-        Ok(self
-            .0
-            .previous_authorization_manager
-            .borrow_mut()
-            .as_mut()
-            .ok_or_else(|| {
-                self.err(
-                    ScErrorType::Auth,
-                    ScErrorCode::InternalError,
-                    "previous invocation is missing - no auth data to get",
-                    &[],
-                )
-            })?
-            .get_authenticated_top_authorizations())
-    }
-
     // Returns the authorizations that have been authenticated for the last
     // contract invocation.
     //
@@ -456,7 +488,7 @@ impl Host {
     #[cfg(any(test, feature = "testutils"))]
     pub fn get_authenticated_authorizations(
         &self,
-    ) -> Result<Vec<(ScAddress, Hash, ScSymbol, ScVec)>, HostError> {
+    ) -> Result<Vec<(ScAddress, SorobanAuthorizedInvocation)>, HostError> {
         Ok(self
             .0
             .previous_authorization_manager
@@ -473,33 +505,19 @@ impl Host {
             .get_authenticated_authorizations())
     }
 
-    fn create_contract(&self, args: CreateContractArgs) -> Result<BytesObject, HostError> {
-        let id_preimage = match args.contract_id {
-            ContractId::Asset(asset) => self.id_preimage_from_asset(asset)?,
-            ContractId::SourceAccount(salt) => self.id_preimage_from_source_account(salt)?,
-            ContractId::Ed25519PublicKey(key_with_signature) => {
-                let signature_payload_preimage = self.create_contract_args_hash_preimage(
-                    args.executable.metered_clone(self.budget_ref())?,
-                    key_with_signature.salt.metered_clone(self.budget_ref())?,
-                )?;
-                let signature_payload = self.metered_hash_xdr(&signature_payload_preimage)?;
-                self.verify_sig_ed25519_internal(
-                    &signature_payload,
-                    &self.ed25519_pub_key_from_bytes(&key_with_signature.key.0)?,
-                    &self.signature_from_bytes(
-                        "create_contract_sig",
-                        &key_with_signature.signature.0,
-                    )?,
-                )?;
-                self.id_preimage_from_ed25519(key_with_signature.key, key_with_signature.salt)?
-            }
-        };
-        self.create_contract_with_id_preimage(args.executable, id_preimage)
-    }
-
-    fn install_contract(&self, args: UploadContractWasmArgs) -> Result<BytesObject, HostError> {
-        let hash_bytes = self.metered_hash_xdr(&args)?;
-        let hash_obj = self.add_host_object(self.scbytes_from_hash(&Hash(hash_bytes))?)?;
+    fn upload_contract_wasm(&self, wasm: Vec<u8>) -> Result<BytesObject, HostError> {
+        let hash_bytes: [u8; 32] = self
+            .sha256_hash_from_bytes(wasm.as_slice())?
+            .try_into()
+            .map_err(|_| {
+                self.err(
+                    ScErrorType::Value,
+                    ScErrorCode::InternalError,
+                    "unexpected hash length",
+                    &[],
+                )
+            })?;
+        let hash_obj = self.add_host_object(self.scbytes_from_slice(hash_bytes.as_slice())?)?;
         let code_key = Rc::new(LedgerKey::ContractCode(LedgerKeyContractCode {
             hash: Hash(hash_bytes.metered_clone(self.budget_ref())?),
         }));
@@ -512,7 +530,14 @@ impl Host {
             self.with_mut_storage(|storage| {
                 let data = LedgerEntryData::ContractCode(ContractCodeEntry {
                     hash: Hash(hash_bytes),
-                    code: args.code,
+                    code: wasm.try_into().map_err(|_| {
+                        self.err(
+                            ScErrorType::Value,
+                            ScErrorCode::ExceededLimit,
+                            "Wasm code is too large",
+                            &[],
+                        )
+                    })?,
                     ext: ExtensionPoint::V0,
                 });
                 storage.put(
@@ -1720,19 +1745,55 @@ impl VmCallerEnv for Host {
     }
 
     // Notes on metering: covered by the components.
-    fn create_contract_from_contract(
+    fn create_contract(
         &self,
         _vmcaller: &mut VmCaller<Host>,
+        deployer: AddressObject,
         wasm_hash: BytesObject,
         salt: BytesObject,
-    ) -> Result<BytesObject, HostError> {
-        let contract_id = self.get_current_contract_id_internal()?;
-        let salt = self.uint256_from_bytesobj_input("salt", salt)?;
-
-        let code =
+    ) -> Result<AddressObject, HostError> {
+        let contract_id_preimage = ContractIdPreimage::Address(ContractIdPreimageFromAddress {
+            address: self.visit_obj(deployer, |addr: &ScAddress| {
+                addr.metered_clone(self.budget_ref())
+            })?,
+            salt: self.uint256_from_bytesobj_input("contract_id_salt", salt)?,
+        });
+        let executable =
             ScContractExecutable::WasmRef(self.hash_from_bytesobj_input("wasm_hash", wasm_hash)?);
-        let id_preimage = self.id_preimage_from_contract(contract_id, salt)?;
-        self.create_contract_with_id_preimage(code, id_preimage)
+        let args = CreateContractArgs {
+            contract_id_preimage,
+            executable,
+        };
+        self.create_contract_internal(Some(deployer), args)
+    }
+
+    // Notes on metering: covered by the components.
+    fn create_asset_contract(
+        &self,
+        _vmcaller: &mut VmCaller<Host>,
+        serialized_asset: BytesObject,
+    ) -> Result<AddressObject, HostError> {
+        let asset: Asset = self.metered_from_xdr_obj(serialized_asset)?;
+        let contract_id_preimage = ContractIdPreimage::Asset(asset);
+        let executable = ScContractExecutable::Token;
+        let args = CreateContractArgs {
+            contract_id_preimage,
+            executable,
+        };
+        // Asset contracts don't need any deployer authorization (they're tied
+        // to the asset issuers instead).
+        self.create_contract_internal(None, args)
+    }
+
+    fn upload_wasm(
+        &self,
+        _vmcaller: &mut VmCaller<Host>,
+        wasm: BytesObject,
+    ) -> Result<BytesObject, HostError> {
+        let wasm_vec = self.visit_obj(wasm, |bytes: &ScBytes| {
+            bytes.as_vec().metered_clone(self.budget_ref())
+        })?;
+        self.upload_contract_wasm(wasm_vec)
     }
 
     fn update_current_contract_wasm(
@@ -1762,18 +1823,19 @@ impl VmCallerEnv for Host {
     fn call(
         &self,
         _vmcaller: &mut VmCaller<Host>,
-        contract: BytesObject,
+        contract_address: AddressObject,
         func: Symbol,
         args: VecObject,
     ) -> Result<RawVal, HostError> {
         let argvec = self.call_args_from_obj(args)?;
         // this is the recommended path of calling a contract, with `reentry`
         // always set `ContractReentryMode::Prohibited`
-        let res = self.call_n(
-            contract,
+        let res = self.call_n_internal(
+            &self.contract_id_from_address(contract_address)?,
             func,
             argvec.as_slice(),
             ContractReentryMode::Prohibited,
+            false,
         );
         if let Err(e) = &res {
             self.with_events_mut(|events| {
@@ -1792,7 +1854,7 @@ impl VmCallerEnv for Host {
     fn try_call(
         &self,
         vmcaller: &mut VmCaller<Host>,
-        contract: BytesObject,
+        contract_address: AddressObject,
         func: Symbol,
         args: VecObject,
     ) -> Result<RawVal, HostError> {
@@ -1801,11 +1863,12 @@ impl VmCallerEnv for Host {
         // TODO: A `reentry` flag will be passed from `try_call` into here.
         // For now, we are passing in `ContractReentryMode::Prohibited` to disable
         // reentry.
-        let res = self.call_n(
-            contract,
+        let res = self.call_n_internal(
+            &self.contract_id_from_address(contract_address)?,
             func,
             argvec.as_slice(),
             ContractReentryMode::Prohibited,
+            false,
         );
         match res {
             Ok(rv) => Ok(rv),
@@ -2324,7 +2387,9 @@ impl VmCallerEnv for Host {
         address: AddressObject,
         args: VecObject,
     ) -> Result<RawVal, Self::Error> {
-        let addr = self.visit_obj(address, |addr: &ScAddress| Ok(addr.clone()))?;
+        let sc_addr = self.visit_obj(address, |addr: &ScAddress| {
+            addr.metered_clone(self.budget_ref())
+        })?;
 
         Ok(self
             .0
@@ -2333,7 +2398,7 @@ impl VmCallerEnv for Host {
             .require_auth(
                 self,
                 address.get_handle(),
-                addr,
+                sc_addr,
                 self.call_args_to_scvec(args)?,
             )?
             .into())
diff --git a/soroban-env-host/src/host/comparison.rs b/soroban-env-host/src/host/comparison.rs
index 1b1d8619..7ce90955 100644
--- a/soroban-env-host/src/host/comparison.rs
+++ b/soroban-env-host/src/host/comparison.rs
@@ -3,10 +3,10 @@ use core::cmp::{min, Ordering};
 use soroban_env_common::{
     xdr::{
         AccountEntry, AccountId, ClaimableBalanceEntry, ConfigSettingEntry, ContractCodeEntry,
-        ContractCostType, DataEntry, Duration, Hash, LedgerEntry, LedgerEntryData, LedgerEntryExt,
-        LedgerKey, LedgerKeyAccount, LedgerKeyClaimableBalance, LedgerKeyConfigSetting,
-        LedgerKeyContractCode, LedgerKeyData, LedgerKeyLiquidityPool, LedgerKeyOffer,
-        LedgerKeyTrustLine, LiquidityPoolEntry, OfferEntry, PublicKey, ScAddress,
+        ContractCostType, CreateContractArgs, DataEntry, Duration, Hash, LedgerEntry,
+        LedgerEntryData, LedgerEntryExt, LedgerKey, LedgerKeyAccount, LedgerKeyClaimableBalance,
+        LedgerKeyConfigSetting, LedgerKeyContractCode, LedgerKeyData, LedgerKeyLiquidityPool,
+        LedgerKeyOffer, LedgerKeyTrustLine, LiquidityPoolEntry, OfferEntry, PublicKey, ScAddress,
         ScContractExecutable, ScErrorCode, ScErrorType, ScMap, ScMapEntry, ScNonceKey, ScVal,
         ScVec, TimePoint, TrustLineAsset, TrustLineEntry, Uint256,
     },
@@ -142,7 +142,10 @@ impl<T: Ord + DeclaredSizeForMetering> Compare<FixedSizeOrdType<'_, T>> for Budg
         // Here we make a runtime assertion that the type's size is below its promised element
         // size for budget charging.
         debug_assert!(
-            std::mem::size_of::<T>() as u64 <= <T as DeclaredSizeForMetering>::DECLARED_SIZE
+            std::mem::size_of::<T>() as u64 <= <T as DeclaredSizeForMetering>::DECLARED_SIZE,
+            "mem size: {}, declared: {}",
+            std::mem::size_of::<T>(),
+            <T as DeclaredSizeForMetering>::DECLARED_SIZE
         );
         self.charge(
             ContractCostType::HostMemCmp,
@@ -210,6 +213,8 @@ impl_compare_fixed_size_ord_type!(LiquidityPoolEntry);
 impl_compare_fixed_size_ord_type!(ContractCodeEntry);
 impl_compare_fixed_size_ord_type!(ConfigSettingEntry);
 
+impl_compare_fixed_size_ord_type!(CreateContractArgs);
+
 impl Compare<SymbolStr> for Budget {
     type Error = HostError;
 
diff --git a/soroban-env-host/src/host/data_helper.rs b/soroban-env-host/src/host/data_helper.rs
index b6986286..29a25f1c 100644
--- a/soroban-env-host/src/host/data_helper.rs
+++ b/soroban-env-host/src/host/data_helper.rs
@@ -1,21 +1,20 @@
 use core::cmp::min;
 use std::rc::Rc;
 
-use soroban_env_common::xdr::{ScErrorCode, ScErrorType};
-use soroban_env_common::{Env, U32Val};
+use soroban_env_common::xdr::{
+    ContractIdPreimage, HashIdPreimageContractId, ScAddress, ScErrorCode, ScErrorType,
+};
+use soroban_env_common::{AddressObject, Env, U32Val};
 
 use crate::budget::AsBudget;
 use crate::xdr::{
-    AccountEntry, AccountId, Asset, ContractCodeEntry, ContractDataEntry, Hash, HashIdPreimage,
-    HashIdPreimageContractId, HashIdPreimageCreateContractArgs, HashIdPreimageEd25519ContractId,
-    HashIdPreimageFromAsset, HashIdPreimageSourceAccountContractId, LedgerEntry, LedgerEntryData,
-    LedgerEntryExt, LedgerKey, LedgerKeyAccount, LedgerKeyContractCode, LedgerKeyContractData,
-    LedgerKeyTrustLine, PublicKey, ScContractExecutable, ScVal, Signer, SignerKey,
-    ThresholdIndexes, TrustLineAsset, Uint256,
+    AccountEntry, AccountId, ContractCodeEntry, ContractDataEntry, Hash, HashIdPreimage,
+    LedgerEntry, LedgerEntryData, LedgerEntryExt, LedgerKey, LedgerKeyAccount,
+    LedgerKeyContractCode, LedgerKeyContractData, LedgerKeyTrustLine, PublicKey,
+    ScContractExecutable, ScVal, Signer, SignerKey, ThresholdIndexes, TrustLineAsset, Uint256,
 };
 use crate::{err, Host, HostError};
 
-use super::invoker_type::InvokerType;
 use super::metered_clone::MeteredClone;
 
 impl Host {
@@ -110,95 +109,16 @@ impl Host {
         Ok(())
     }
 
-    // notes on metering: covers the key and salt. Rest are free.
-    pub fn id_preimage_from_ed25519(
-        &self,
-        key: Uint256,
-        salt: Uint256,
-    ) -> Result<HashIdPreimage, HostError> {
-        Ok(HashIdPreimage::ContractIdFromEd25519(
-            HashIdPreimageEd25519ContractId {
-                network_id: self
-                    .hash_from_bytesobj_input("network_id", self.get_ledger_network_id()?)?,
-                ed25519: key,
-                salt,
-            },
-        ))
-    }
-
-    // metering: covered by components
-    pub fn id_preimage_from_contract(
-        &self,
-        contract_id: Hash,
-        salt: Uint256,
-    ) -> Result<HashIdPreimage, HostError> {
-        Ok(HashIdPreimage::ContractIdFromContract(
-            HashIdPreimageContractId {
-                network_id: self
-                    .hash_from_bytesobj_input("network_id", self.get_ledger_network_id()?)?,
-                contract_id,
-                salt,
-            },
-        ))
-    }
-
-    // metering: covered by components
-    pub fn id_preimage_from_asset(&self, asset: Asset) -> Result<HashIdPreimage, HostError> {
-        Ok(HashIdPreimage::ContractIdFromAsset(
-            HashIdPreimageFromAsset {
-                network_id: self
-                    .hash_from_bytesobj_input("network_id", self.get_ledger_network_id()?)?,
-                asset,
-            },
-        ))
-    }
-
-    // metering: covered by components
-    pub fn id_preimage_from_source_account(
-        &self,
-        salt: Uint256,
-    ) -> Result<HashIdPreimage, HostError> {
-        if self.get_invoker_type()? != InvokerType::Account as u64 {
-            return Err(self.err(
-                ScErrorType::Context,
-                ScErrorCode::UnexpectedType,
-                "invoker is not an account",
-                &[],
-            ));
-        }
-
-        let source_account = self.source_account().ok_or_else(|| {
-            self.err(
-                ScErrorType::Context,
-                ScErrorCode::MissingValue,
-                "unexpected missing invoker in id preimage",
-                &[],
-            )
-        })?;
-        Ok(HashIdPreimage::ContractIdFromSourceAccount(
-            HashIdPreimageSourceAccountContractId {
-                network_id: self
-                    .hash_from_bytesobj_input("network_id", self.get_ledger_network_id()?)?,
-                source_account,
-                salt,
-            },
-        ))
-    }
-
     // metering: covered by components
-    pub fn create_contract_args_hash_preimage(
+    pub fn get_full_contract_id_preimage(
         &self,
-        executable: ScContractExecutable,
-        salt: Uint256,
+        init_preimage: ContractIdPreimage,
     ) -> Result<HashIdPreimage, HostError> {
-        Ok(HashIdPreimage::CreateContractArgs(
-            HashIdPreimageCreateContractArgs {
-                network_id: self
-                    .hash_from_bytesobj_input("network_id", self.get_ledger_network_id()?)?,
-                executable,
-                salt,
-            },
-        ))
+        Ok(HashIdPreimage::ContractId(HashIdPreimageContractId {
+            network_id: self
+                .hash_from_bytesobj_input("network_id", self.get_ledger_network_id()?)?,
+            contract_id_preimage: init_preimage,
+        }))
     }
 
     // notes on metering: `get` from storage is covered. Rest are free.
@@ -300,4 +220,25 @@ impl Host {
             ext: LedgerEntryExt::V0,
         })
     }
+
+    pub(crate) fn contract_id_from_scaddress(&self, address: ScAddress) -> Result<Hash, HostError> {
+        match address {
+            ScAddress::Account(_) => Err(self.err(
+                ScErrorType::Object,
+                ScErrorCode::InvalidInput,
+                "not a contract address",
+                &[],
+            )),
+            ScAddress::Contract(contract_id) => Ok(contract_id),
+        }
+    }
+
+    pub(crate) fn contract_id_from_address(
+        &self,
+        address: AddressObject,
+    ) -> Result<Hash, HostError> {
+        self.visit_obj(address, |addr: &ScAddress| {
+            self.contract_id_from_scaddress(addr.metered_clone(self.budget_ref())?)
+        })
+    }
 }
diff --git a/soroban-env-host/src/host/declared_size.rs b/soroban-env-host/src/host/declared_size.rs
index f997a71a..a717112e 100644
--- a/soroban-env-host/src/host/declared_size.rs
+++ b/soroban-env-host/src/host/declared_size.rs
@@ -1,5 +1,7 @@
 use std::rc::Rc;
 
+use soroban_env_common::xdr::{ContractIdPreimage, CreateContractArgs};
+
 use crate::{
     events::{HostEvent, InternalContractEvent, InternalEvent},
     host::Events,
@@ -94,7 +96,7 @@ impl_declared_size_type!(SymbolStr, SCSYMBOL_LIMIT);
 impl_declared_size_type!(SymbolSmallIter, 8);
 impl_declared_size_type!(U256, 32);
 impl_declared_size_type!(I256, 32);
-impl_declared_size_type!(HostObject, 48);
+impl_declared_size_type!(HostObject, 40);
 // xdr types
 impl_declared_size_type!(TimePoint, 8);
 impl_declared_size_type!(Duration, 8);
@@ -131,12 +133,14 @@ impl_declared_size_type!(ConfigSettingEntry, 104);
 impl_declared_size_type!(AccessType, 1);
 impl_declared_size_type!(InternalContractEvent, 40);
 impl_declared_size_type!(ContractEvent, 104);
-impl_declared_size_type!(HostEvent, 120);
+impl_declared_size_type!(HostEvent, 112);
 impl_declared_size_type!(Events, 24);
-impl_declared_size_type!(InternalEvent, 80);
+impl_declared_size_type!(InternalEvent, 40);
 impl_declared_size_type!(ScBytes, 24);
 impl_declared_size_type!(ScString, 24);
 impl_declared_size_type!(ScSymbol, 24);
+impl_declared_size_type!(CreateContractArgs, 99);
+impl_declared_size_type!(ContractIdPreimage, 66);
 
 // composite types
 
@@ -255,7 +259,7 @@ mod test {
         expect!["8"].assert_eq(size_of::<SymbolSmallIter>().to_string().as_str());
         expect!["32"].assert_eq(size_of::<U256>().to_string().as_str());
         expect!["32"].assert_eq(size_of::<I256>().to_string().as_str());
-        expect!["48"].assert_eq(size_of::<HostObject>().to_string().as_str());
+        expect!["40"].assert_eq(size_of::<HostObject>().to_string().as_str());
         // xdr types
         expect!["8"].assert_eq(size_of::<TimePoint>().to_string().as_str());
         expect!["8"].assert_eq(size_of::<Duration>().to_string().as_str());
@@ -288,16 +292,18 @@ mod test {
         expect!["120"].assert_eq(size_of::<ClaimableBalanceEntry>().to_string().as_str());
         expect!["160"].assert_eq(size_of::<LiquidityPoolEntry>().to_string().as_str());
         expect!["56"].assert_eq(size_of::<ContractCodeEntry>().to_string().as_str());
-        expect!["8"].assert_eq(size_of::<ConfigSettingEntry>().to_string().as_str());
+        expect!["104"].assert_eq(size_of::<ConfigSettingEntry>().to_string().as_str());
         expect!["1"].assert_eq(size_of::<AccessType>().to_string().as_str());
         expect!["40"].assert_eq(size_of::<InternalContractEvent>().to_string().as_str());
         expect!["104"].assert_eq(size_of::<ContractEvent>().to_string().as_str());
-        expect!["120"].assert_eq(size_of::<HostEvent>().to_string().as_str());
+        expect!["112"].assert_eq(size_of::<HostEvent>().to_string().as_str());
         expect!["24"].assert_eq(size_of::<Events>().to_string().as_str());
-        expect!["80"].assert_eq(size_of::<InternalEvent>().to_string().as_str());
+        expect!["40"].assert_eq(size_of::<InternalEvent>().to_string().as_str());
         expect!["24"].assert_eq(size_of::<ScBytes>().to_string().as_str());
         expect!["24"].assert_eq(size_of::<ScString>().to_string().as_str());
         expect!["24"].assert_eq(size_of::<ScSymbol>().to_string().as_str());
+        expect!["99"].assert_eq(size_of::<CreateContractArgs>().to_string().as_str());
+        expect!["66"].assert_eq(size_of::<ContractIdPreimage>().to_string().as_str());
         // composite types
         expect!["16"].assert_eq(size_of::<&[ScVal]>().to_string().as_str());
         expect!["48"].assert_eq(size_of::<(RawVal, ScVal)>().to_string().as_str());
@@ -425,6 +431,7 @@ mod test {
         assert_mem_size_le_declared_size!(ScBytes);
         assert_mem_size_le_declared_size!(ScString);
         assert_mem_size_le_declared_size!(ScSymbol);
+        assert_mem_size_le_declared_size!(CreateContractArgs);
         // composite types
         assert_mem_size_le_declared_size!(&[ScVal]);
         assert_mem_size_le_declared_size!((RawVal, ScVal));
diff --git a/soroban-env-host/src/host/frame.rs b/soroban-env-host/src/host/frame.rs
index 3a2b9780..55b911c6 100644
--- a/soroban-env-host/src/host/frame.rs
+++ b/soroban-env-host/src/host/frame.rs
@@ -1,15 +1,15 @@
-use soroban_env_common::xdr::{ScErrorCode, ScErrorType};
+use soroban_env_common::{
+    xdr::{ContractIdPreimage, ScAddress, ScErrorCode, ScErrorType},
+    AddressObject,
+};
 
 use crate::{
     auth::AuthorizationManagerSnapshot,
     budget::AsBudget,
     err,
     storage::StorageMap,
-    xdr::{
-        ContractCostType, Hash, HostFunction, HostFunctionArgs, HostFunctionType,
-        ScContractExecutable, ScVal,
-    },
-    BytesObject, Error, Host, HostError, RawVal, Symbol, SymbolStr, TryFromVal, TryIntoVal,
+    xdr::{ContractCostType, Hash, HostFunction, HostFunctionType, ScContractExecutable, ScVal},
+    Error, Host, HostError, RawVal, Symbol, SymbolStr, TryFromVal, TryIntoVal,
 };
 
 #[cfg(any(test, feature = "testutils"))]
@@ -449,17 +449,6 @@ impl Host {
         }
     }
 
-    pub(crate) fn call_n(
-        &self,
-        id: BytesObject,
-        func: Symbol,
-        args: &[RawVal],
-        reentry_mode: ContractReentryMode,
-    ) -> Result<RawVal, HostError> {
-        let id = self.hash_from_bytesobj_input("contract", id)?;
-        self.call_n_internal(&id, func, args, reentry_mode, false)
-    }
-
     // Notes on metering: this is covered by the called components.
     pub(crate) fn call_n_internal(
         &self,
@@ -616,22 +605,29 @@ impl Host {
     }
 
     // Notes on metering: covered by the called components.
-    fn invoke_function_raw(&self, hf: HostFunctionArgs) -> Result<RawVal, HostError> {
+    fn invoke_function_raw(&self, hf: HostFunction) -> Result<RawVal, HostError> {
         let hf_type = hf.discriminant();
-        //TODO: should the create_* methods below return a RawVal instead of Object to avoid this conversion?
         match hf {
-            HostFunctionArgs::InvokeContract(args) => {
-                if let [ScVal::Bytes(scbytes), ScVal::Symbol(scsym), rest @ ..] = args.as_slice() {
+            HostFunction::InvokeContract(args) => {
+                if let [ScVal::Address(ScAddress::Contract(contract_id)), ScVal::Symbol(scsym), rest @ ..] =
+                    args.as_slice()
+                {
                     self.with_frame(Frame::HostFunction(hf_type), || {
                         // Metering: conversions to host objects are covered. Cost of collecting
                         // RawVals into Vec is ignored. Since 1. RawVals are cheap to clone 2. the
                         // max number of args is fairly limited.
-                        let object = self.add_host_object(scbytes.clone())?;
+
                         let symbol: Symbol = scsym.as_slice().try_into_val(self)?;
                         let args = self.scvals_to_rawvals(rest)?;
                         // since the `HostFunction` frame must be the bottom of the call stack,
                         // reentry is irrelevant, we always pass in `ContractReentryMode::Prohibited`.
-                        self.call_n(object, symbol, &args[..], ContractReentryMode::Prohibited)
+                        self.call_n_internal(
+                            contract_id,
+                            symbol,
+                            &args[..],
+                            ContractReentryMode::Prohibited,
+                            false,
+                        )
                     })
                 } else {
                     Err(err!(
@@ -642,28 +638,32 @@ impl Host {
                     ))
                 }
             }
-            HostFunctionArgs::CreateContract(args) => self
-                .with_frame(Frame::HostFunction(hf_type), || {
-                    self.create_contract(args).map(<RawVal>::from)
-                }),
-            HostFunctionArgs::UploadContractWasm(args) => self
+            HostFunction::CreateContract(args) => {
+                self.with_frame(Frame::HostFunction(hf_type), || {
+                    let deployer: Option<AddressObject> = match &args.contract_id_preimage {
+                        ContractIdPreimage::Address(preimage_from_addr) => Some(
+                            self.add_host_object(
+                                preimage_from_addr
+                                    .address
+                                    .metered_clone(self.budget_ref())?,
+                            )?,
+                        ),
+                        ContractIdPreimage::Asset(_) => None,
+                    };
+                    self.create_contract_internal(deployer, args)
+                        .map(<RawVal>::from)
+                })
+            }
+            HostFunction::UploadContractWasm(wasm) => self
                 .with_frame(Frame::HostFunction(hf_type), || {
-                    self.install_contract(args).map(<RawVal>::from)
+                    self.upload_contract_wasm(wasm.to_vec()).map(<RawVal>::from)
                 }),
         }
     }
 
     // Notes on metering: covered by the called components.
-    pub fn invoke_functions(&self, host_fns: Vec<HostFunction>) -> Result<Vec<ScVal>, HostError> {
-        let is_recording_auth = self.0.authorization_manager.borrow().is_recording();
-        let mut res = vec![];
-        for hf in host_fns {
-            if !is_recording_auth {
-                self.set_authorization_entries(hf.auth.to_vec())?;
-            }
-            let rv = self.invoke_function_raw(hf.args)?;
-            res.push(self.from_host_val(rv)?);
-        }
-        Ok(res)
+    pub fn invoke_function(&self, hf: HostFunction) -> Result<ScVal, HostError> {
+        let rv = self.invoke_function_raw(hf)?;
+        self.from_host_val(rv)
     }
 }
diff --git a/soroban-env-host/src/host/metered_clone.rs b/soroban-env-host/src/host/metered_clone.rs
index 333302e4..3d9afdde 100644
--- a/soroban-env-host/src/host/metered_clone.rs
+++ b/soroban-env-host/src/host/metered_clone.rs
@@ -1,6 +1,6 @@
 use std::{mem, rc::Rc};
 
-use soroban_env_common::xdr::{ContractEventType, ScErrorCode, ScErrorType};
+use soroban_env_common::xdr::{ContractEventType, ContractIdPreimage, ScErrorCode, ScErrorType};
 
 use crate::{
     budget::Budget,
@@ -10,12 +10,12 @@ use crate::{
     storage::AccessType,
     xdr::{
         AccountEntry, AccountId, BytesM, ClaimableBalanceEntry, ConfigSettingEntry,
-        ContractCodeEntry, ContractCostType, ContractEvent, ContractEventBody, DataEntry, Duration,
-        Hash, LedgerEntryExt, LedgerKeyAccount, LedgerKeyClaimableBalance, LedgerKeyConfigSetting,
-        LedgerKeyContractCode, LedgerKeyData, LedgerKeyLiquidityPool, LedgerKeyOffer,
-        LedgerKeyTrustLine, LiquidityPoolEntry, OfferEntry, PublicKey, ScAddress, ScBytes,
-        ScContractExecutable, ScMap, ScMapEntry, ScNonceKey, ScString, ScSymbol, ScVal, ScVec,
-        StringM, TimePoint, TrustLineAsset, TrustLineEntry, Uint256,
+        ContractCodeEntry, ContractCostType, ContractEvent, ContractEventBody, CreateContractArgs,
+        DataEntry, Duration, Hash, LedgerEntryExt, LedgerKeyAccount, LedgerKeyClaimableBalance,
+        LedgerKeyConfigSetting, LedgerKeyContractCode, LedgerKeyData, LedgerKeyLiquidityPool,
+        LedgerKeyOffer, LedgerKeyTrustLine, LiquidityPoolEntry, OfferEntry, PublicKey, ScAddress,
+        ScBytes, ScContractExecutable, ScMap, ScMapEntry, ScNonceKey, ScString, ScSymbol, ScVal,
+        ScVec, StringM, TimePoint, TrustLineAsset, TrustLineEntry, Uint256,
     },
     AddressObject, Bool, BytesObject, ContractExecutableObject, DurationObject, DurationSmall,
     DurationVal, Error, HostError, I128Object, I128Small, I128Val, I256Object, I256Small, I256Val,
@@ -40,7 +40,12 @@ pub(crate) fn charge_shallow_copy<T: MeteredClone>(
     // that the type's size is below its promised element size for budget charging. This assertion
     // only happens in debug build. In optimized build, not satisfying the asserted condition just
     // means an underestimation of the cost.
-    debug_assert!(mem::size_of::<T>() as u64 <= T::DECLARED_SIZE);
+    debug_assert!(
+        mem::size_of::<T>() as u64 <= T::DECLARED_SIZE,
+        "mem size: {}, declared: {}",
+        std::mem::size_of::<T>(),
+        T::DECLARED_SIZE
+    );
     budget.charge(
         ContractCostType::HostMemCpy,
         Some(n_elts.saturating_mul(T::DECLARED_SIZE)),
@@ -212,6 +217,8 @@ impl MeteredClone for ContractCodeEntry {}
 impl MeteredClone for ConfigSettingEntry {}
 impl MeteredClone for AccessType {}
 impl MeteredClone for InternalContractEvent {}
+impl MeteredClone for CreateContractArgs {}
+impl MeteredClone for ContractIdPreimage {}
 // composite types
 impl<T> MeteredClone for Rc<T> {}
 impl<T> MeteredClone for &[T] {}
diff --git a/soroban-env-host/src/native_contract/account_contract.rs b/soroban-env-host/src/native_contract/account_contract.rs
index a4804418..767176ce 100644
--- a/soroban-env-host/src/native_contract/account_contract.rs
+++ b/soroban-env-host/src/native_contract/account_contract.rs
@@ -1,4 +1,4 @@
-use crate::auth::AuthorizedInvocation;
+use crate::auth::{AuthorizedFunction, AuthorizedInvocation};
 // This is a built-in account 'contract'. This is not actually a contract, as
 // it doesn't need to be directly invoked. But semantically this is analagous
 // to a generic smart wallet contract that supports authentication and blanket
@@ -8,7 +8,10 @@ use crate::host::{frame::ContractReentryMode, Host};
 use crate::native_contract::{base_types::BytesN, contract_error::ContractError};
 use crate::{err, HostError};
 use core::cmp::Ordering;
-use soroban_env_common::xdr::{Hash, ThresholdIndexes, Uint256};
+use soroban_env_common::xdr::{
+    ContractIdPreimage, Hash, ScContractExecutable, ScErrorCode, ScErrorType, ThresholdIndexes,
+    Uint256,
+};
 use soroban_env_common::{Env, EnvBase, RawVal, Symbol, TryFromVal, TryIntoVal};
 
 use crate::native_contract::base_types::Vec as HostVec;
@@ -18,16 +21,38 @@ const MAX_ACCOUNT_SIGNATURES: u32 = 20;
 use soroban_env_common::xdr::{AccountId, ScVal};
 use soroban_native_sdk_macros::contracttype;
 
+use super::base_types::Address;
+
 pub const ACCOUNT_CONTRACT_CHECK_AUTH_FN_NAME: &str = "__check_auth";
 
 #[derive(Clone)]
 #[contracttype]
-pub struct AuthorizationContext {
-    pub contract: BytesN<32>,
+pub struct ContractAuthorizationContext {
+    pub contract: Address,
     pub fn_name: Symbol,
     pub args: HostVec,
 }
 
+#[derive(Clone)]
+#[contracttype]
+pub enum ContractExecutable {
+    Wasm(BytesN<32>),
+}
+
+#[derive(Clone)]
+#[contracttype]
+pub struct CreateContractHostFnContext {
+    pub executable: ContractExecutable,
+    pub salt: BytesN<32>,
+}
+
+#[derive(Clone)]
+#[contracttype]
+enum AuthorizationContext {
+    Contract(ContractAuthorizationContext),
+    CreateContractHostFn(CreateContractHostFnContext),
+}
+
 #[derive(Clone)]
 #[contracttype]
 pub struct AccountEd25519Signature {
@@ -36,19 +61,66 @@ pub struct AccountEd25519Signature {
 }
 
 impl AuthorizationContext {
-    fn from_invocation(host: &Host, invocation: &AuthorizedInvocation) -> Result<Self, HostError> {
-        let args =
-            HostVec::try_from_val(host, &host.scvals_to_rawvals(invocation.args.0.as_slice())?)?;
-        let fn_name =
-            Symbol::try_from(host.to_host_val(&ScVal::Symbol(invocation.function_name.clone()))?)?;
-        Ok(Self {
-            contract: BytesN::try_from_val(
-                host,
-                &host.bytes_new_from_slice(invocation.contract_id.0.as_slice())?,
-            )?,
-            fn_name,
-            args,
-        })
+    fn from_authorized_fn(host: &Host, function: &AuthorizedFunction) -> Result<Self, HostError> {
+        match function {
+            AuthorizedFunction::ContractFn(contract_fn) => {
+                let fn_name = Symbol::try_from(host.to_host_val(&ScVal::Symbol(
+                    contract_fn.function_name.metered_clone(host.budget_ref())?,
+                ))?)?;
+                let args = HostVec::try_from_val(
+                    host,
+                    &host.scvals_to_rawvals(contract_fn.args.0.as_slice())?,
+                )?;
+                Ok(AuthorizationContext::Contract(
+                    ContractAuthorizationContext {
+                        contract: Address::try_from_val(
+                            host,
+                            &host.add_host_object(
+                                contract_fn
+                                    .contract_address
+                                    .metered_clone(host.budget_ref())?,
+                            )?,
+                        )?,
+                        fn_name,
+                        args,
+                    },
+                ))
+            }
+            AuthorizedFunction::CreateContractHostFn(args) => {
+                let wasm_hash = match &args.executable {
+                    ScContractExecutable::WasmRef(wasm_hash) => {
+                        BytesN::<32>::from_slice(host, wasm_hash.as_slice())?
+                    }
+                    ScContractExecutable::Token => {
+                        return Err(host.err(
+                            ScErrorType::Auth,
+                            ScErrorCode::InternalError,
+                            "unexpected auth context for create contract host fn",
+                            &[],
+                        ))
+                    }
+                };
+                let salt = match &args.contract_id_preimage {
+                    ContractIdPreimage::Address(id_from_addr) => {
+                        BytesN::<32>::from_slice(host, id_from_addr.salt.as_slice())?
+                    }
+                    ContractIdPreimage::Asset(_) => {
+                        return Err(host.err(
+                            ScErrorType::Auth,
+                            ScErrorCode::InternalError,
+                            "unexpected auth context for create contract host fn",
+                            &[],
+                        ))
+                    }
+                };
+                Ok(AuthorizationContext::CreateContractHostFn(
+                    CreateContractHostFnContext {
+                        executable: ContractExecutable::Wasm(wasm_hash),
+                        salt,
+                    },
+                ))
+            }
+        }
     }
 }
 
@@ -57,7 +129,10 @@ fn invocation_tree_to_auth_contexts(
     invocation: &AuthorizedInvocation,
     out_contexts: &mut HostVec,
 ) -> Result<(), HostError> {
-    out_contexts.push(&AuthorizationContext::from_invocation(host, invocation)?)?;
+    out_contexts.push(&AuthorizationContext::from_authorized_fn(
+        host,
+        &invocation.function,
+    )?)?;
     for sub_invocation in &invocation.sub_invocations {
         invocation_tree_to_auth_contexts(host, sub_invocation, out_contexts)?;
     }
diff --git a/soroban-env-host/src/native_contract/base_types.rs b/soroban-env-host/src/native_contract/base_types.rs
index 0b937a2e..b8bfd816 100644
--- a/soroban-env-host/src/native_contract/base_types.rs
+++ b/soroban-env-host/src/native_contract/base_types.rs
@@ -1,3 +1,4 @@
+use crate::host::metered_clone::MeteredClone;
 use crate::host::{Host, HostError};
 
 use core::cmp::Ordering;
@@ -77,6 +78,14 @@ impl Bytes {
         Ok(())
     }
 
+    #[inline(always)]
+    pub fn from_slice(env: &Host, items: &[u8]) -> Result<Bytes, HostError> {
+        Ok(Bytes {
+            host: env.clone(),
+            object: env.bytes_new_from_slice(items)?,
+        })
+    }
+
     #[cfg(test)]
     pub(crate) fn to_vec(&self) -> std::vec::Vec<u8> {
         let mut res = std::vec::Vec::<u8>::new();
@@ -173,11 +182,6 @@ impl<const N: usize> BytesN<N> {
             object: env.bytes_new_from_slice(items)?,
         })
     }
-
-    #[cfg(test)]
-    pub(crate) fn to_vec(&self) -> std::vec::Vec<u8> {
-        Bytes::from(self.clone()).to_vec()
-    }
 }
 
 #[derive(Clone)]
@@ -438,13 +442,16 @@ impl Address {
     pub(crate) fn from_account(env: &Host, account_id: &AccountId) -> Result<Self, HostError> {
         Address::try_from_val(
             env,
-            &env.add_host_object(ScAddress::Account(account_id.clone()))?,
+            &env.add_host_object(ScAddress::Account(
+                account_id.metered_clone(env.budget_ref())?,
+            ))?,
         )
     }
 
     pub(crate) fn to_sc_address(&self) -> Result<ScAddress, HostError> {
-        self.host
-            .visit_obj(self.object, |addr: &ScAddress| Ok(addr.clone()))
+        self.host.visit_obj(self.object, |addr: &ScAddress| {
+            addr.metered_clone(self.host.budget_ref())
+        })
     }
 
     pub(crate) fn require_auth(&self) -> Result<(), HostError> {
diff --git a/soroban-synth-wasm/Cargo.toml b/soroban-synth-wasm/Cargo.toml
index d8ed3919..238dde1f 100644
--- a/soroban-synth-wasm/Cargo.toml
+++ b/soroban-synth-wasm/Cargo.toml
@@ -12,7 +12,7 @@ publish = false
 
 [dependencies]
 wasm-encoder = "0.18.0"
-wasmparser = "0.92.0"
+wasmparser = "0.106.0"
 soroban-env-common = { workspace = true }
 
 [dev-dependencies]


Test patch:
diff --git a/soroban-env-host/src/native_contract/testutils.rs b/soroban-env-host/src/native_contract/testutils.rs
index 3d9edee9..ffb4e30a 100644
--- a/soroban-env-host/src/native_contract/testutils.rs
+++ b/soroban-env-host/src/native_contract/testutils.rs
@@ -1,12 +1,14 @@
+use crate::auth::{AuthorizedFunction, ContractFunction};
 use crate::{Host, LedgerInfo};
 use ed25519_dalek::{Keypair, Signer};
 use rand::thread_rng;
 use soroban_env_common::xdr::{
     AccountEntry, AccountEntryExt, AccountEntryExtensionV1, AccountEntryExtensionV1Ext,
-    AccountEntryExtensionV2, AccountEntryExtensionV2Ext, AccountId, AddressWithNonce,
-    AuthorizedInvocation, ContractAuth, Hash, HashIdPreimage, HashIdPreimageContractAuth,
-    LedgerEntryData, LedgerKey, Liabilities, PublicKey, ScAddress, ScVec, SequenceNumber,
-    SignerKey, Thresholds, Uint256,
+    AccountEntryExtensionV2, AccountEntryExtensionV2Ext, AccountId, Hash, HashIdPreimage,
+    HashIdPreimageSorobanAuthorization, LedgerEntryData, LedgerKey, Liabilities, PublicKey,
+    ScAddress, ScSymbol, ScVec, SequenceNumber, SignerKey, SorobanAddressCredentials,
+    SorobanAuthorizationEntry, SorobanAuthorizedContractFunction, SorobanAuthorizedFunction,
+    SorobanAuthorizedInvocation, SorobanCredentials, Thresholds, Uint256,
 };
 use soroban_env_common::{EnvBase, TryFromVal, TryIntoVal};
 
@@ -66,7 +68,7 @@ pub(crate) enum TestSigner<'a> {
 }
 
 pub(crate) struct AccountContractSigner<'a> {
-    pub(crate) id: Hash,
+    pub(crate) address: Address,
     #[allow(clippy::type_complexity)]
     pub(crate) sign: Box<dyn Fn(&[u8]) -> HostVec + 'a>,
 }
@@ -129,7 +131,7 @@ impl<'a> TestSigner<'a> {
         let sc_address = match self {
             TestSigner::AccountInvoker(acc_id) => ScAddress::Account(acc_id.clone()),
             TestSigner::Account(acc) => ScAddress::Account(acc.account_id.clone()),
-            TestSigner::AccountContract(signer) => ScAddress::Contract(signer.id.clone()),
+            TestSigner::AccountContract(signer) => signer.address.to_sc_address().unwrap(),
             TestSigner::ContractInvoker(contract_id) => ScAddress::Contract(contract_id.clone()),
         };
         Address::try_from_val(host, &host.add_host_object(sc_address).unwrap()).unwrap()
@@ -139,51 +141,53 @@ impl<'a> TestSigner<'a> {
 pub(crate) fn authorize_single_invocation_with_nonce(
     host: &Host,
     signer: &TestSigner,
-    contract_id: &BytesN<32>,
+    contract_address: &Address,
     function_name: &str,
     args: HostVec,
     nonce: Option<u64>,
 ) {
     let sc_address = signer.address(host).to_sc_address().unwrap();
-    let address_with_nonce = match signer {
-        TestSigner::AccountInvoker(_) => None,
-        TestSigner::Account(_) | TestSigner::AccountContract(_) => Some(AddressWithNonce {
-            address: sc_address,
-            nonce: nonce.unwrap(),
-        }),
+    let mut credentials = match signer {
+        TestSigner::AccountInvoker(_) => SorobanCredentials::SourceAccount,
+        TestSigner::Account(_) | TestSigner::AccountContract(_) => {
+            SorobanCredentials::Address(SorobanAddressCredentials {
+                address: sc_address,
+                nonce: nonce.unwrap(),
+                signature_args: Default::default(),
+            })
+        }
         TestSigner::ContractInvoker(_) => {
             // Nothing need to be authorized for contract invoker here.
             return;
         }
     };
 
-    let root_invocation = AuthorizedInvocation {
-        contract_id: contract_id.to_vec().try_into().unwrap(),
-        function_name: crate::xdr::ScSymbol(function_name.try_into().unwrap()),
-        args: host.call_args_to_scvec(args.into()).unwrap(),
+    let root_invocation = SorobanAuthorizedInvocation {
+        function: SorobanAuthorizedFunction::ContractFn(SorobanAuthorizedContractFunction {
+            contract_address: contract_address.to_sc_address().unwrap(),
+            function_name: ScSymbol(function_name.try_into().unwrap()),
+            args: host.call_args_to_scvec(args.into()).unwrap(),
+        }),
         sub_invocations: Default::default(),
     };
 
-    let signature_payload = if let Some(addr_with_nonce) = &address_with_nonce {
-        let signature_payload_preimage = HashIdPreimage::ContractAuth(HashIdPreimageContractAuth {
-            network_id: host
-                .with_ledger_info(|li: &LedgerInfo| Ok(li.network_id))
-                .unwrap()
-                .try_into()
-                .unwrap(),
-            invocation: root_invocation.clone(),
-            nonce: addr_with_nonce.nonce,
-        });
-        host.metered_hash_xdr(&signature_payload_preimage).unwrap()
-    } else {
-        [0; 32]
-    };
-
-    let signature_args = signer.sign(host, &signature_payload);
-    let auth_entry = ContractAuth {
-        address_with_nonce,
+    if let SorobanCredentials::Address(address_credentials) = &mut credentials {
+        let signature_payload_preimage =
+            HashIdPreimage::SorobanAuthorization(HashIdPreimageSorobanAuthorization {
+                network_id: host
+                    .with_ledger_info(|li: &LedgerInfo| Ok(li.network_id))
+                    .unwrap()
+                    .try_into()
+                    .unwrap(),
+                invocation: root_invocation.clone(),
+                nonce: address_credentials.nonce,
+            });
+        let signature_payload = host.metered_hash_xdr(&signature_payload_preimage).unwrap();
+        address_credentials.signature_args = signer.sign(host, &signature_payload);
+    }
+    let auth_entry = SorobanAuthorizationEntry {
+        credentials,
         root_invocation,
-        signature_args,
     };
 
     host.set_authorization_entries(vec![auth_entry]).unwrap();
@@ -192,7 +196,7 @@ pub(crate) fn authorize_single_invocation_with_nonce(
 pub(crate) fn authorize_single_invocation(
     host: &Host,
     signer: &TestSigner,
-    contract_id: &BytesN<32>,
+    contract_address: &Address,
     function_name: &str,
     args: HostVec,
 ) {
@@ -200,8 +204,12 @@ pub(crate) fn authorize_single_invocation(
         TestSigner::AccountInvoker(_) => None,
         TestSigner::Account(_) | TestSigner::AccountContract(_) => Some(
             host.read_nonce(
-                &Hash(contract_id.to_vec().try_into().unwrap()),
-                &signer.address(host).to_sc_address().unwrap(),
+                signer.address(host).to_sc_address().unwrap(),
+                &AuthorizedFunction::ContractFn(ContractFunction {
+                    contract_address: contract_address.to_sc_address().unwrap(),
+                    function_name: Default::default(),
+                    args: Default::default(),
+                }),
             )
             .unwrap(),
         ),
@@ -209,7 +217,14 @@ pub(crate) fn authorize_single_invocation(
             return;
         }
     };
-    authorize_single_invocation_with_nonce(host, signer, contract_id, function_name, args, nonce);
+    authorize_single_invocation_with_nonce(
+        host,
+        signer,
+        contract_address,
+        function_name,
+        args,
+        nonce,
+    );
 }
 
 pub(crate) fn sign_payload_for_account(
diff --git a/soroban-env-host/src/native_contract/token/test_token.rs b/soroban-env-host/src/native_contract/token/test_token.rs
index c7fed161..f226cdaa 100644
--- a/soroban-env-host/src/native_contract/token/test_token.rs
+++ b/soroban-env-host/src/native_contract/token/test_token.rs
@@ -7,35 +7,31 @@ use crate::{
     Host, HostError,
 };
 use soroban_env_common::{
-    xdr::{
-        Asset, ContractId, CreateContractArgs, HostFunction, HostFunctionArgs, ScContractExecutable,
-    },
-    Env, RawVal,
+    xdr::{Asset, WriteXdr},
+    Env,
 };
 use soroban_env_common::{Symbol, TryFromVal, TryIntoVal};
 
-use crate::native_contract::base_types::{Bytes, BytesN};
+use crate::native_contract::base_types::Bytes;
 
 pub(crate) struct TestToken<'a> {
-    pub(crate) id: BytesN<32>,
+    pub(crate) address: Address,
     host: &'a Host,
 }
 
 impl<'a> TestToken<'a> {
     pub(crate) fn new_from_asset(host: &'a Host, asset: Asset) -> Self {
-        let id_obj: RawVal = host
-            .invoke_functions(vec![HostFunction {
-                args: HostFunctionArgs::CreateContract(CreateContractArgs {
-                    contract_id: ContractId::Asset(asset),
-                    executable: ScContractExecutable::Token,
-                }),
-                auth: Default::default(),
-            }])
-            .unwrap()[0]
-            .try_into_val(host)
+        let mut asset_bytes_vec = vec![];
+        asset.write_xdr(&mut asset_bytes_vec).unwrap();
+        let address_obj = host
+            .create_asset_contract(
+                Bytes::from_slice(host, &asset_bytes_vec.as_slice())
+                    .unwrap()
+                    .into(),
+            )
             .unwrap();
         Self {
-            id: BytesN::<32>::try_from_val(host, &id_obj).unwrap(),
+            address: Address::try_from_val(host, &address_obj).unwrap(),
             host,
         }
     }
@@ -44,7 +40,7 @@ impl<'a> TestToken<'a> {
         Ok(self
             .host
             .call(
-                self.id.clone().into(),
+                self.address.clone().into(),
                 Symbol::try_from_val(self.host, &"allowance")?,
                 host_vec![self.host, from, spender].into(),
             )?
@@ -57,11 +53,17 @@ impl<'a> TestToken<'a> {
         function_name: &str,
         args: HostVec,
     ) -> Result<(), HostError> {
-        authorize_single_invocation(self.host, signer, &self.id, function_name, args.clone());
+        authorize_single_invocation(
+            self.host,
+            signer,
+            &self.address,
+            function_name,
+            args.clone(),
+        );
         Ok(self
             .host
             .call(
-                self.id.clone().into(),
+                self.address.clone().into(),
                 Symbol::try_from_val(self.host, &function_name)?,
                 args.into(),
             )?
@@ -98,7 +100,7 @@ impl<'a> TestToken<'a> {
         Ok(self
             .host
             .call(
-                self.id.clone().into(),
+                self.address.clone().into(),
                 Symbol::try_from_val(self.host, &"balance")?,
                 host_vec![self.host, addr].into(),
             )?
@@ -109,7 +111,7 @@ impl<'a> TestToken<'a> {
         Ok(self
             .host
             .call(
-                self.id.clone().into(),
+                self.address.clone().into(),
                 Symbol::try_from_val(self.host, &"spendable_balance")?,
                 host_vec![self.host, addr].into(),
             )?
@@ -120,7 +122,7 @@ impl<'a> TestToken<'a> {
         Ok(self
             .host
             .call(
-                self.id.clone().into(),
+                self.address.clone().into(),
                 Symbol::try_from_val(self.host, &"authorized")?,
                 host_vec![self.host, addr].into(),
             )?
@@ -218,7 +220,7 @@ impl<'a> TestToken<'a> {
         Ok(self
             .host
             .call(
-                self.id.clone().into(),
+                self.address.clone().into(),
                 Symbol::try_from_val(self.host, &"decimals")?,
                 host_vec![self.host].into(),
             )?
@@ -228,7 +230,7 @@ impl<'a> TestToken<'a> {
     pub(crate) fn name(&self) -> Result<Bytes, HostError> {
         self.host
             .call(
-                self.id.clone().into(),
+                self.address.clone().into(),
                 Symbol::try_from_val(self.host, &"name")?,
                 host_vec![self.host].into(),
             )?
@@ -238,7 +240,7 @@ impl<'a> TestToken<'a> {
     pub(crate) fn symbol(&self) -> Result<Bytes, HostError> {
         self.host
             .call(
-                self.id.clone().into(),
+                self.address.clone().into(),
                 Symbol::try_from_val(self.host, &"symbol")?,
                 host_vec![self.host].into(),
             )?
diff --git a/soroban-env-host/src/test/auth.rs b/soroban-env-host/src/test/auth.rs
index cd794427..5e1de3e8 100644
--- a/soroban-env-host/src/test/auth.rs
+++ b/soroban-env-host/src/test/auth.rs
@@ -2,19 +2,19 @@ use std::collections::HashMap;
 
 use ed25519_dalek::Keypair;
 use soroban_env_common::xdr::{
-    AccountId, AddressWithNonce, AuthorizedInvocation, ContractAuth, HashIdPreimage,
-    HashIdPreimageContractAuth, PublicKey, ScAddress, ScSymbol, ScVec, Uint256,
+    AccountId, HashIdPreimage, HashIdPreimageSorobanAuthorization, PublicKey, ScAddress, ScSymbol,
+    ScVec, SorobanAddressCredentials, SorobanAuthorizationEntry, SorobanAuthorizedContractFunction,
+    SorobanAuthorizedFunction, SorobanAuthorizedInvocation, SorobanCredentials, Uint256,
 };
 use soroban_native_sdk_macros::contracttype;
 use soroban_test_wasms::AUTH_TEST_CONTRACT;
 
-use crate::auth::RecordedAuthPayload;
+use crate::auth::{AuthorizedFunction, ContractFunction, RecordedAuthPayload};
 use crate::budget::AsBudget;
-use crate::native_contract::base_types::BytesN;
+use crate::native_contract::base_types::Address;
 use crate::native_contract::testutils::{
     create_account, generate_keypair, sign_payload_for_account,
 };
-use crate::xdr::Hash;
 use crate::{host_vec, Host, LedgerInfo};
 use soroban_env_common::{AddressObject, Env, Symbol, SymbolStr, TryIntoVal};
 
@@ -23,7 +23,7 @@ use crate::native_contract::base_types::Vec as HostVec;
 #[derive(Clone)]
 #[contracttype]
 pub struct ContractTreeNode {
-    pub id: BytesN<32>,
+    pub addr: Address,
     pub need_auth: HostVec,
     pub children: HostVec,
 }
@@ -31,27 +31,27 @@ pub struct ContractTreeNode {
 struct AuthTest {
     host: Host,
     keys: Vec<Keypair>,
-    contracts: Vec<BytesN<32>>,
-    last_nonces: HashMap<(Vec<u8>, Vec<u8>), u64>,
+    contracts: Vec<Address>,
+    last_nonces: HashMap<(ScAddress, Vec<u8>), u64>,
 }
 
 struct SetupNode {
-    contract_id: BytesN<32>,
+    contract_address: Address,
     need_auth: Vec<bool>,
     children: Vec<SetupNode>,
 }
 
 struct SignNode {
-    contract_id: BytesN<32>,
+    contract_address: Address,
     fn_name: Symbol,
     args: ScVec,
     children: Vec<SignNode>,
 }
 
 impl SetupNode {
-    fn new(contract_id: &BytesN<32>, need_auth: Vec<bool>, children: Vec<SetupNode>) -> Self {
+    fn new(contract_address: &Address, need_auth: Vec<bool>, children: Vec<SetupNode>) -> Self {
         Self {
-            contract_id: contract_id.clone(),
+            contract_address: contract_address.clone(),
             need_auth,
             children,
         }
@@ -60,22 +60,22 @@ impl SetupNode {
 
 impl SignNode {
     fn new(
-        contract_id: &BytesN<32>,
+        contract_address: &Address,
         fn_name: Symbol,
         args: ScVec,
         children: Vec<SignNode>,
     ) -> Self {
         Self {
-            contract_id: contract_id.clone(),
+            contract_address: contract_address.clone(),
             fn_name,
             args,
             children,
         }
     }
 
-    fn tree_fn(contract_id: &BytesN<32>, children: Vec<SignNode>) -> Self {
+    fn tree_fn(contract_id: &Address, children: Vec<SignNode>) -> Self {
         Self {
-            contract_id: contract_id.clone(),
+            contract_address: contract_id.clone(),
             children,
             fn_name: Symbol::try_from_small_str("tree_fn").unwrap(),
             args: ScVec::default(),
@@ -112,9 +112,7 @@ impl AuthTest {
         }
         let mut contracts = vec![];
         for _ in 0..contract_cnt {
-            let contract_id_obj = host
-                .register_test_contract_wasm(AUTH_TEST_CONTRACT)
-                .unwrap();
+            let contract_id_obj = host.register_test_contract_wasm(AUTH_TEST_CONTRACT);
             contracts.push(contract_id_obj.try_into_val(&host).unwrap());
         }
         Self {
@@ -127,7 +125,7 @@ impl AuthTest {
 
     // Runs the test for the given setup in enforcing mode. `sign_payloads`
     // contain should contain a vec of `SignNode` inputs for every signer in the
-    // setup. The nodes then are mapped to the respective `ContractAuth` entries.
+    // setup. The nodes then are mapped to the respective `SorobanAuthorizationEntry` entries.
     fn tree_test_enforcing(
         &mut self,
         root: &SetupNode,
@@ -135,7 +133,7 @@ impl AuthTest {
         success: bool,
     ) {
         self.test_enforcing(
-            root.contract_id.clone(),
+            root.contract_address.clone(),
             Symbol::try_from_small_str("tree_fn").unwrap(),
             host_vec![
                 &self.host,
@@ -149,7 +147,7 @@ impl AuthTest {
 
     fn test_enforcing(
         &mut self,
-        contract_id: BytesN<32>,
+        contract_address: Address,
         fn_name: Symbol,
         args: HostVec,
         sign_payloads: Vec<Vec<SignNode>>,
@@ -161,40 +159,45 @@ impl AuthTest {
 
         for address_id in 0..self.keys.len() {
             let sc_address = self.key_to_sc_address(&self.keys[address_id]);
-            let mut next_nonce = HashMap::<Vec<u8>, u64>::new();
+            let mut next_nonce = HashMap::<ScAddress, u64>::new();
             for sign_root in &sign_payloads[address_id] {
-                let contract_id_vec = sign_root.contract_id.to_vec();
-                let nonce = if let Some(nonce) = next_nonce.get(&contract_id_vec) {
+                let contract_address = sign_root.contract_address.to_sc_address().unwrap();
+                let nonce = if let Some(nonce) = next_nonce.get(&contract_address) {
                     *nonce
                 } else {
                     let nonce = self
                         .host
                         .read_nonce(
-                            &Hash(contract_id_vec.clone().try_into().unwrap()),
-                            &sc_address,
+                            sc_address.clone(),
+                            &AuthorizedFunction::ContractFn(ContractFunction {
+                                contract_address: contract_address.clone(),
+                                function_name: Default::default(),
+                                args: Default::default(),
+                            }),
                         )
                         .unwrap();
                     self.last_nonces.insert(
                         (
-                            contract_id_vec.clone(),
+                            contract_address.clone(),
                             self.keys[address_id].public.as_bytes().to_vec(),
                         ),
                         nonce,
                     );
                     nonce
                 };
-                next_nonce.insert(contract_id_vec, nonce + 1);
+                next_nonce.insert(contract_address, nonce + 1);
                 let root_invocation = self.convert_sign_node(sign_root);
-                let payload_preimage = HashIdPreimage::ContractAuth(HashIdPreimageContractAuth {
-                    network_id: self
-                        .host
-                        .with_ledger_info(|li: &LedgerInfo| Ok(li.network_id))
-                        .unwrap()
-                        .try_into()
-                        .unwrap(),
-                    invocation: root_invocation.clone(),
-                    nonce,
-                });
+                let payload_preimage =
+                    HashIdPreimage::SorobanAuthorization(HashIdPreimageSorobanAuthorization {
+                        network_id: self
+                            .host
+                            .with_ledger_info(|li: &LedgerInfo| Ok(li.network_id))
+                            .unwrap()
+                            .try_into()
+                            .unwrap(),
+                        invocation: root_invocation.clone(),
+                        nonce,
+                    });
                 let payload = self.host.metered_hash_xdr(&payload_preimage).unwrap();
                 let signature_args = host_vec![
                     &self.host,
@@ -203,13 +206,16 @@ impl AuthTest {
                         sign_payload_for_account(&self.host, &self.keys[address_id], &payload)
                     ]
                 ];
-                contract_auth.push(ContractAuth {
-                    address_with_nonce: Some(AddressWithNonce {
+                contract_auth.push(SorobanAuthorizationEntry {
+                    credentials: SorobanCredentials::Address(SorobanAddressCredentials {
                         address: sc_address.clone(),
                         nonce,
+                        signature_args: self
+                            .host
+                            .call_args_to_scvec(signature_args.into())
+                            .unwrap(),
                     }),
                     root_invocation,
-                    signature_args: self.host.call_args_to_scvec(signature_args.into()).unwrap(),
                 });
             }
         }
@@ -217,7 +223,7 @@ impl AuthTest {
         self.host.set_authorization_entries(contract_auth).unwrap();
         assert_eq!(
             self.host
-                .call(contract_id.into(), fn_name, args.into(),)
+                .call(contract_address.into(), fn_name, args.into(),)
                 .is_ok(),
             success
         );
@@ -225,17 +231,21 @@ impl AuthTest {
 
     // Verifies that nonces for the given contract_id+signer pairs are increased
     // by the expected value.
-    fn verify_nonce_increments(&self, expected_increments: Vec<(&BytesN<32>, &Keypair, u64)>) {
-        for (contract_id, key, expected_increment) in expected_increments {
-            let nonce_increment = if let Some(last_nonce) = self
-                .last_nonces
-                .get(&(contract_id.to_vec().clone(), key.public.as_bytes().to_vec()))
-            {
+    fn verify_nonce_increments(&self, expected_increments: Vec<(&Address, &Keypair, u64)>) {
+        for (contract_address, key, expected_increment) in expected_increments {
+            let nonce_increment = if let Some(last_nonce) = self.last_nonces.get(&(
+                contract_address.to_sc_address().unwrap(),
+                key.public.as_bytes().to_vec(),
+            )) {
                 let curr_nonce = self
                     .host
                     .read_nonce(
-                        &Hash(contract_id.to_vec().try_into().unwrap()),
-                        &self.key_to_sc_address(key),
+                        self.key_to_sc_address(key),
+                        &AuthorizedFunction::ContractFn(ContractFunction {
+                            contract_address: contract_address.to_sc_address().unwrap(),
+                            function_name: Default::default(),
+                            args: Default::default(),
+                        }),
                     )
                     .unwrap();
                 curr_nonce - last_nonce
@@ -252,7 +262,7 @@ impl AuthTest {
         let addresses = self.get_addresses();
         let tree = self.convert_setup_tree(&root);
         self.run_recording(
-            &root.contract_id,
+            &root.contract_address,
             Symbol::try_from_small_str("tree_fn").unwrap(),
             host_vec![&self.host, addresses, tree],
         )
@@ -260,13 +270,13 @@ impl AuthTest {
 
     fn run_recording(
         &self,
-        contract_id: &BytesN<32>,
+        contract_address: &Address,
         fn_name: Symbol,
         args: HostVec,
     ) -> Vec<RecordedAuthPayload> {
         self.host.switch_to_recording_auth();
         self.host
-            .call(contract_id.clone().into(), fn_name, args.into())
+            .call(contract_address.clone().into(), fn_name, args.into())
             .unwrap();
         self.host.get_recorded_auth_payloads().unwrap()
     }
@@ -293,20 +303,22 @@ impl AuthTest {
         addresses
     }
 
-    fn convert_sign_node(&self, root: &SignNode) -> AuthorizedInvocation {
+    fn convert_sign_node(&self, root: &SignNode) -> SorobanAuthorizedInvocation {
         let mut sub_invocations = vec![];
         for c in &root.children {
             sub_invocations.push(self.convert_sign_node(c));
         }
 
-        // FIXME: more and better Symbol<->SymbolStr<->ScSymbol conversions.
+        // TODO: more and better Symbol<->SymbolStr<->ScSymbol conversions.
         let function_name: SymbolStr = root.fn_name.try_into_val(&self.host).unwrap();
         let function_name: ScSymbol = ScSymbol(function_name.to_string().try_into().unwrap());
 
-        AuthorizedInvocation {
-            contract_id: root.contract_id.to_vec().try_into().unwrap(),
-            function_name,
-            args: root.args.clone(),
+        SorobanAuthorizedInvocation {
+            function: SorobanAuthorizedFunction::ContractFn(SorobanAuthorizedContractFunction {
+                contract_address: root.contract_address.to_sc_address().unwrap(),
+                function_name,
+                args: root.args.clone(),
+            }),
             sub_invocations: sub_invocations.try_into().unwrap(),
         }
     }
@@ -321,7 +333,7 @@ impl AuthTest {
             need_auth.push(n).unwrap();
         }
         ContractTreeNode {
-            id: root.contract_id.clone(),
+            addr: root.contract_address.clone(),
             need_auth,
             children,
         }
@@ -346,6 +358,15 @@ fn test_single_authorized_call() {
     test.tree_test_enforcing(&setup, expected_sign_payloads, true);
     test.verify_nonce_increments(vec![(&test.contracts[0], &test.keys[0], 1)]);
 
+    assert_eq!(
+        test.tree_run_recording(&setup),
+        vec![RecordedAuthPayload {
+            address: Some(test.key_to_sc_address(&test.keys[0])),
+            nonce: Some(2),
+            invocation: test.convert_sign_node(&SignNode::tree_fn(&test.contracts[0], vec![]))
+        }]
+    );
+
     // Correct call with an extra top-level payload
     test.tree_test_enforcing(
         &setup,
diff --git a/soroban-env-host/src/test/budget_metering.rs b/soroban-env-host/src/test/budget_metering.rs
index 99fa5772..6cdf0a26 100644
--- a/soroban-env-host/src/test/budget_metering.rs
+++ b/soroban-env-host/src/test/budget_metering.rs
@@ -44,7 +44,7 @@ fn xdr_object_conversion() -> Result<(), HostError> {
 #[test]
 fn vm_hostfn_invocation() -> Result<(), HostError> {
     let host = Host::test_host_with_recording_footprint();
-    let id_obj = host.register_test_contract_wasm(VEC)?;
+    let id_obj = host.register_test_contract_wasm(VEC);
     let host = host
         .test_budget(100_000, 100_000)
         .enable_model(ContractCostType::InvokeVmFunction, 10, 0, 1, 0)
diff --git a/soroban-env-host/src/test/bytes.rs b/soroban-env-host/src/test/bytes.rs
index 78bd1dd9..b66974e2 100644
--- a/soroban-env-host/src/test/bytes.rs
+++ b/soroban-env-host/src/test/bytes.rs
@@ -144,7 +144,7 @@ fn linear_memory_operations() -> Result<(), HostError> {
     use soroban_env_common::BytesObject;
 
     let host = Host::test_host_with_recording_footprint();
-    let id_obj = host.register_test_contract_wasm(LINEAR_MEMORY)?;
+    let id_obj = host.register_test_contract_wasm(LINEAR_MEMORY);
     // tests bytes_new_from_linear_memory
     {
         let args = host.test_vec_obj::<u32>(&[0xaabbccdd])?;
diff --git a/soroban-env-host/src/test/event.rs b/soroban-env-host/src/test/event.rs
index f4f8c521..680cae1e 100644
--- a/soroban-env-host/src/test/event.rs
+++ b/soroban-env-host/src/test/event.rs
@@ -3,9 +3,10 @@ use crate::{
         ContractEvent, ContractEventBody, ContractEventType, ContractEventV0, ExtensionPoint, Hash,
         ScMap, ScMapEntry, ScVal,
     },
-    ContractFunctionSet, Env, EnvBase, Host, HostError, RawVal, Symbol,
+    ContractFunctionSet, Env, Host, HostError, RawVal, Symbol,
 };
 use expect_test::expect;
+use soroban_env_common::xdr::ScAddress;
 use std::rc::Rc;
 
 pub struct ContractWithSingleEvent;
@@ -26,7 +27,8 @@ impl ContractFunctionSet for ContractWithSingleEvent {
 fn contract_event() -> Result<(), HostError> {
     let host = Host::default();
     let dummy_id = [0; 32];
-    let id = host.bytes_new_from_slice(&dummy_id)?;
+    let dummy_address = ScAddress::Contract(Hash(dummy_id.clone()));
+    let id = host.add_host_object(dummy_address)?;
     let test_contract = Rc::new(ContractWithSingleEvent {});
     let sym = Symbol::try_from_small_str("add").unwrap();
     let args = host.test_vec_obj::<i32>(&[1, 2])?;
@@ -79,8 +81,8 @@ impl ContractFunctionSet for ContractWithMultipleEvents {
 #[test]
 fn test_event_rollback() -> Result<(), HostError> {
     let host = Host::default();
-    let dummy_id = [0; 32];
-    let id = host.bytes_new_from_slice(&dummy_id)?;
+    let dummy_address = ScAddress::Contract(Hash([0; 32]));
+    let id = host.add_host_object(dummy_address)?;
     let test_contract = Rc::new(ContractWithMultipleEvents {});
     let sym = Symbol::try_from_small_str("add").unwrap();
     let args = host.test_vec_obj::<i32>(&[1, 2])?;
diff --git a/soroban-env-host/src/test/invocation.rs b/soroban-env-host/src/test/invocation.rs
index da671db1..f19768b9 100644
--- a/soroban-env-host/src/test/invocation.rs
+++ b/soroban-env-host/src/test/invocation.rs
@@ -37,7 +37,7 @@ fn invoke_cross_contract(diagnostics: bool) -> Result<(), HostError> {
         host.set_diagnostic_level(crate::DiagnosticLevel::Debug);
     }
 
-    let id_obj = host.register_test_contract_wasm(ADD_I32)?;
+    let id_obj = host.register_test_contract_wasm(ADD_I32);
     // prepare arguments
     let sym = Symbol::try_from_small_str("add").unwrap();
     let args = host.test_vec_obj::<i32>(&[1, 2])?;
@@ -63,7 +63,7 @@ fn invoke_cross_contract_with_diagnostics() -> Result<(), HostError> {
 fn invoke_cross_contract_with_err() -> Result<(), HostError> {
     let host = Host::test_host_with_recording_footprint();
     host.enable_debug();
-    let id_obj = host.register_test_contract_wasm(VEC)?;
+    let id_obj = host.register_test_contract_wasm(VEC);
     // prepare arguments
     let sym = Symbol::try_from_small_str("vec_err").unwrap();
     let args = host.test_vec_obj::<u32>(&[1])?;
@@ -105,8 +105,8 @@ fn invoke_cross_contract_with_err() -> Result<(), HostError> {
 #[test]
 fn invoke_cross_contract_indirect() -> Result<(), HostError> {
     let host = Host::test_host_with_recording_footprint();
-    let id0_obj = host.register_test_contract_wasm(INVOKE_CONTRACT)?;
-    let id1_obj = host.register_test_contract_wasm(ADD_I32)?;
+    let id0_obj = host.register_test_contract_wasm(INVOKE_CONTRACT);
+    let id1_obj = host.register_test_contract_wasm(ADD_I32);
     // prepare arguments
     let sym = Symbol::try_from_small_str("add_with").unwrap();
     let args = host.test_vec_obj::<i32>(&[5, 6])?;
@@ -122,7 +122,7 @@ fn invoke_cross_contract_indirect() -> Result<(), HostError> {
 fn invoke_cross_contract_indirect_err() -> Result<(), HostError> {
     let host = Host::test_host_with_recording_footprint();
     host.enable_debug();
-    let id0_obj = host.register_test_contract_wasm(INVOKE_CONTRACT)?;
+    let id0_obj = host.register_test_contract_wasm(INVOKE_CONTRACT);
     let sym = Symbol::try_from_small_str("add_with").unwrap();
     let args = host.test_vec_obj::<i32>(&[i32::MAX, 1])?;
     let args = host.vec_push_back(args, host.bytes_new()?.to_raw())?;
@@ -163,7 +163,7 @@ fn invoke_cross_contract_indirect_err() -> Result<(), HostError> {
 #[test]
 fn invoke_contract_with_reentry() -> Result<(), HostError> {
     let host = Host::test_host_with_recording_footprint();
-    let id0_obj = host.register_test_contract_wasm(INVOKE_CONTRACT)?;
+    let id0_obj = host.register_test_contract_wasm(INVOKE_CONTRACT);
     // prepare arguments
     let sym = Symbol::try_from_small_str("add_with").unwrap();
     let args = host.test_vec_obj::<i32>(&[i32::MAX, 1])?;
diff --git a/soroban-env-host/src/test/lifecycle.rs b/soroban-env-host/src/test/lifecycle.rs
index 5361bcf5..6d82ff8a 100644
--- a/soroban-env-host/src/test/lifecycle.rs
+++ b/soroban-env-host/src/test/lifecycle.rs
@@ -4,16 +4,20 @@ use crate::{
     host_vec,
     storage::{AccessType, Footprint, Storage, StorageMap},
     xdr::{
-        self, ContractEvent, ContractEventBody, ContractEventType, ContractEventV0, ContractId,
+        self, ContractEvent, ContractEventBody, ContractEventType, ContractEventV0,
         CreateContractArgs, ExtensionPoint, Hash, HashIdPreimage, HashIdPreimageContractId,
-        HashIdPreimageSourceAccountContractId, HostFunction, LedgerEntryData, ScContractExecutable,
-        ScSymbol, ScVal, ScVec, Uint256, UploadContractWasmArgs,
+        LedgerEntryData, ScContractExecutable, ScSymbol, ScVal, ScVec, Uint256,
     },
     Env, Host, LedgerInfo, Symbol,
 };
 use sha2::{Digest, Sha256};
-use soroban_env_common::xdr::HostFunctionArgs;
-use soroban_env_common::{xdr::ScBytes, RawVal, TryIntoVal, VecObject};
+use soroban_env_common::xdr::{
+    ContractIdPreimage, ContractIdPreimageFromAddress, HostFunction, ScAddress,
+    SorobanAuthorizationEntry, SorobanAuthorizedFunction, SorobanAuthorizedInvocation,
+    SorobanCredentials,
+};
+use soroban_env_common::VecObject;
+use soroban_env_common::{xdr::ScBytes, RawVal, TryIntoVal};
 use soroban_test_wasms::{ADD_I32, CREATE_CONTRACT, UPDATEABLE_CONTRACT};
 
 use super::util::{generate_account_id, generate_bytes_array};
@@ -67,27 +71,25 @@ fn test_host() -> Host {
     host
 }
 
-fn test_create_contract_from_source_account(host: &Host, code: &[u8]) -> Hash {
+fn test_create_contract_from_source_account(host: &Host, wasm: &[u8]) -> Hash {
     let source_account = generate_account_id();
     let salt = generate_bytes_array();
     host.set_source_account(source_account.clone());
+    let contract_id_preimage = ContractIdPreimage::Address(ContractIdPreimageFromAddress {
+        address: ScAddress::Account(source_account.clone()),
+        salt: Uint256(salt.to_vec().try_into().unwrap()),
+    });
     // Make contractID so we can include it in the footprint
-    let id_pre_image =
-        HashIdPreimage::ContractIdFromSourceAccount(HashIdPreimageSourceAccountContractId {
-            source_account: source_account,
-            salt: Uint256(salt.to_vec().try_into().unwrap()),
-            network_id: host
-                .hash_from_bytesobj_input("network_id", host.get_ledger_network_id().unwrap())
-                .unwrap(),
-        });
-
-    let contract_id = sha256_hash_id_preimage(id_pre_image);
+    let full_id_preimage = HashIdPreimage::ContractId(HashIdPreimageContractId {
+        network_id: host
+            .hash_from_bytesobj_input("network_id", host.get_ledger_network_id().unwrap())
+            .unwrap(),
+        contract_id_preimage: contract_id_preimage.clone(),
+    });
 
-    let upload_args = xdr::UploadContractWasmArgs {
-        code: code.to_vec().try_into().unwrap(),
-    };
+    let contract_id = sha256_hash_id_preimage(full_id_preimage);
 
-    let wasm_hash = sha256_hash_id_preimage(upload_args.clone());
+    let wasm_hash = Hash(Sha256::digest(wasm).try_into().unwrap());
 
     host.with_mut_storage(|s: &mut Storage| {
         s.footprint
@@ -108,39 +110,40 @@ fn test_create_contract_from_source_account(host: &Host, code: &[u8]) -> Hash {
     })
     .unwrap();
 
-    // Upload & create contract
-    let res = host
-        .invoke_functions(vec![
-            HostFunction {
-                args: HostFunctionArgs::UploadContractWasm(upload_args),
-                auth: Default::default(),
-            },
-            HostFunction {
-                args: HostFunctionArgs::CreateContract(CreateContractArgs {
-                    contract_id: ContractId::SourceAccount(Uint256(
-                        salt.to_vec().try_into().unwrap(),
-                    )),
-                    executable: ScContractExecutable::WasmRef(wasm_hash.clone()),
-                }),
-                auth: Default::default(),
-            },
-        ])
+    // Create contract
+    let created_wasm_hash: RawVal = host
+        .invoke_function(HostFunction::UploadContractWasm(wasm.try_into().unwrap()))
+        .unwrap()
+        .try_into_val(host)
+        .unwrap();
+    let created_wasm_hash = host
+        .hash_from_bytesobj_input("wasm_hash", created_wasm_hash.try_into().unwrap())
+        .unwrap();
+    let create_contract_args = CreateContractArgs {
+        contract_id_preimage,
+        executable: ScContractExecutable::WasmRef(created_wasm_hash.clone()),
+    };
+    host.set_authorization_entries(vec![SorobanAuthorizationEntry {
+        credentials: SorobanCredentials::SourceAccount,
+        root_invocation: SorobanAuthorizedInvocation {
+            function: SorobanAuthorizedFunction::CreateContractHostFn(create_contract_args.clone()),
+            sub_invocations: Default::default(),
+        },
+    }])
+    .unwrap();
+    let created_id_sc_val = host
+        .invoke_function(HostFunction::CreateContract(create_contract_args))
         .unwrap();
-    assert_eq!(res.len(), 2);
+
     assert_eq!(
-        wasm_hash.as_slice(),
-        get_bytes_from_sc_val(&res[0]).as_slice()
+        ScVal::Address(ScAddress::Contract(contract_id.clone())),
+        created_id_sc_val
     );
     assert_eq!(
-        wasm_hash.as_slice(),
+        created_wasm_hash.as_slice(),
         get_contract_wasm_ref(&host, contract_id.clone()).as_slice()
     );
-    assert_eq!(
-        contract_id.as_slice(),
-        get_bytes_from_sc_val(&res[1]).as_slice()
-    );
-
-    assert_eq!(code, get_contract_wasm(&host, wasm_hash));
+    assert_eq!(wasm, get_contract_wasm(&host, wasm_hash));
 
     contract_id
 }
@@ -150,23 +153,25 @@ fn test_create_contract_from_source_account(host: &Host, code: &[u8]) -> Hash {
 fn create_contract_using_parent_id_test() {
     let host = test_host();
     let parent_contract_id = test_create_contract_from_source_account(&host, CREATE_CONTRACT);
+    let parent_contract_address = host
+        .add_host_object(ScAddress::Contract(parent_contract_id.clone()))
+        .unwrap();
     let salt = generate_bytes_array();
-    let child_pre_image = HashIdPreimage::ContractIdFromContract(HashIdPreimageContractId {
-        contract_id: parent_contract_id.clone(),
-        salt: Uint256(salt),
+    let child_pre_image = HashIdPreimage::ContractId(HashIdPreimageContractId {
         network_id: host
             .hash_from_bytesobj_input("network_id", host.get_ledger_network_id().unwrap())
             .unwrap(),
+        contract_id_preimage: ContractIdPreimage::Address(ContractIdPreimageFromAddress {
+            address: ScAddress::Contract(parent_contract_id.clone()),
+            salt: Uint256(salt),
+        }),
     });
 
     let child_id = sha256_hash_id_preimage(child_pre_image);
     let child_wasm: &[u8] = b"70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4";
-    let upload_args = xdr::UploadContractWasmArgs {
-        code: child_wasm.to_vec().try_into().unwrap(),
-    };
 
     // Install the code for the child contract.
-    let wasm_hash = sha256_hash_id_preimage(upload_args);
+    let wasm_hash = xdr::Hash(Sha256::digest(&child_wasm).try_into().unwrap());
     // Add the contract code and code reference access to the footprint.
     host.with_mut_storage(|s: &mut Storage| {
         s.footprint
@@ -199,10 +204,10 @@ fn create_contract_using_parent_id_test() {
         .unwrap()
         .try_into()
         .unwrap();
-    // Can't create the contract yet, as the code hasn't been installed yet.
+    // Can't create the contract yet, as the code hasn't been uploaded yet.
     assert!(host
         .call(
-            host.test_bin_obj(&parent_contract_id.0).unwrap(),
+            parent_contract_address.clone(),
             Symbol::try_from_small_str("create").unwrap(),
             args,
         )
@@ -210,13 +215,10 @@ fn create_contract_using_parent_id_test() {
 
     // Install the code of the child contract.
     let wasm_hash_sc_val = host
-        .invoke_functions(vec![HostFunction {
-            args: HostFunctionArgs::UploadContractWasm(UploadContractWasmArgs {
-                code: child_wasm.try_into().unwrap(),
-            }),
-            auth: Default::default(),
-        }])
-        .unwrap()[0]
+        .invoke_function(HostFunction::UploadContractWasm(
+            child_wasm.try_into().unwrap(),
+        ))
+        .unwrap()
         .clone();
     assert_eq!(
         wasm_hash.as_slice(),
@@ -226,7 +228,7 @@ fn create_contract_using_parent_id_test() {
 
     // Now successfully create the child contract itself.
     host.call(
-        host.test_bin_obj(&parent_contract_id.0).unwrap(),
+        parent_contract_address,
         Symbol::try_from_small_str("create").unwrap(),
         args,
     )
@@ -257,40 +259,27 @@ pub(crate) fn sha256_hash_id_preimage<T: xdr::WriteXdr>(pre_image: T) -> xdr::Ha
 fn test_contract_wasm_update() {
     let host = Host::test_host_with_recording_footprint();
 
-    let old_upload_args = xdr::UploadContractWasmArgs {
-        code: UPDATEABLE_CONTRACT.to_vec().try_into().unwrap(),
-    };
     let old_wasm_hash_obj: RawVal = host
-        .invoke_functions(vec![HostFunction {
-            args: HostFunctionArgs::UploadContractWasm(old_upload_args),
-            auth: Default::default(),
-        }])
-        .unwrap()[0]
+        .invoke_function(HostFunction::UploadContractWasm(
+            UPDATEABLE_CONTRACT.to_vec().try_into().unwrap(),
+        ))
+        .unwrap()
         .try_into_val(&host)
         .unwrap();
 
-    let contract_id_obj = host
-        .register_test_contract_wasm(UPDATEABLE_CONTRACT)
-        .unwrap();
-    let contract_id = host
-        .hash_from_bytesobj_input("contract_id", contract_id_obj)
-        .unwrap();
+    let contract_addr_obj = host.register_test_contract_wasm(UPDATEABLE_CONTRACT);
     let updated_wasm = ADD_I32;
-    let upload_args = xdr::UploadContractWasmArgs {
-        code: updated_wasm.to_vec().try_into().unwrap(),
-    };
 
     let updated_wasm_hash_obj: RawVal = host
-        .invoke_functions(vec![HostFunction {
-            args: HostFunctionArgs::UploadContractWasm(upload_args),
-            auth: Default::default(),
-        }])
-        .unwrap()[0]
+        .invoke_function(HostFunction::UploadContractWasm(
+            updated_wasm.to_vec().try_into().unwrap(),
+        ))
+        .unwrap()
         .try_into_val(&host)
         .unwrap();
     let res: i32 = host
         .call(
-            contract_id_obj,
+            contract_addr_obj,
             Symbol::try_from_small_str("update").unwrap(),
             host_vec![&host, &updated_wasm_hash_obj].into(),
         )
@@ -318,7 +307,7 @@ fn test_contract_wasm_update() {
                 he.event,
                 ContractEvent {
                     ext: ExtensionPoint::V0,
-                    contract_id: Some(contract_id),
+                    contract_id: Some(host.contract_id_from_address(contract_addr_obj).unwrap()),
                     type_: ContractEventType::System,
                     body: ContractEventBody::V0(ContractEventV0 {
                         topics: vec![
@@ -354,7 +343,7 @@ fn test_contract_wasm_update() {
     // numbers.
     let updated_res: i32 = host
         .call(
-            contract_id_obj,
+            contract_addr_obj,
             Symbol::try_from_small_str("add").unwrap(),
             host_vec![&host, 10_i32, 20_i32].into(),
         )
diff --git a/soroban-env-host/src/test/prng.rs b/soroban-env-host/src/test/prng.rs
index af5be4d3..120fdf55 100644
--- a/soroban-env-host/src/test/prng.rs
+++ b/soroban-env-host/src/test/prng.rs
@@ -1,5 +1,5 @@
 use crate::{
-    xdr::{ScVal, ScVec},
+    xdr::{Hash, ScAddress, ScVal, ScVec},
     BytesObject, ContractFunctionSet, Env, EnvBase, Host, HostError, RawVal, Symbol, SymbolSmall,
     U32Val, U64Object, VecObject,
 };
@@ -64,7 +64,8 @@ fn prng_test() -> Result<(), HostError> {
     host.set_base_prng_seed([0; 32]);
 
     let dummy_id = [0; 32];
-    let id = host.bytes_new_from_slice(&dummy_id)?;
+    let dummy_address = ScAddress::Contract(Hash(dummy_id.clone()));
+    let id = host.add_host_object(dummy_address)?;
 
     host.register_test_contract(id, std::rc::Rc::new(PRNGUsingTest))?;
     let args = host.test_vec_obj::<i32>(&[1, 2])?;
diff --git a/soroban-env-host/src/test/storage.rs b/soroban-env-host/src/test/storage.rs
index 0ecf01eb..cc18d583 100644
--- a/soroban-env-host/src/test/storage.rs
+++ b/soroban-env-host/src/test/storage.rs
@@ -6,7 +6,7 @@ use soroban_test_wasms::CONTRACT_STORAGE;
 #[test]
 fn test_peristent_storage() {
     let host = Host::test_host_with_recording_footprint();
-    let contract_id = host.register_test_contract_wasm(CONTRACT_STORAGE).unwrap();
+    let contract_id = host.register_test_contract_wasm(CONTRACT_STORAGE);
     let key_1 = Symbol::try_from_small_str("key_1").unwrap();
     let key_2 = Symbol::try_from_val(&host, &"this_is_key_2").unwrap();
     // Check that the key is not in the storage yet
diff --git a/soroban-env-host/src/test/token.rs b/soroban-env-host/src/test/token.rs
index ca52878e..20c08bae 100644
--- a/soroban-env-host/src/test/token.rs
+++ b/soroban-env-host/src/test/token.rs
@@ -20,7 +20,10 @@ use crate::{
 };
 use ed25519_dalek::Keypair;
 use soroban_env_common::{
-    xdr::{self, AccountFlags, ScAddress, ScVal, ScVec},
+    xdr::{
+        self, AccountFlags, ScAddress, ScSymbol, ScVal, ScVec, SorobanAuthorizedContractFunction,
+        SorobanAuthorizedFunction, SorobanAuthorizedInvocation,
+    },
     xdr::{
         AccountId, AlphaNum12, AlphaNum4, Asset, AssetCode12, AssetCode4, Hash, HostFunctionType,
         LedgerEntryData, LedgerKey, Liabilities, PublicKey, ScErrorCode, ScErrorType,
@@ -317,9 +320,13 @@ fn test_native_token_smart_roundtrip() {
         0,
     );
     let token = TestToken::new_from_asset(&test.host, Asset::Native);
-    let expected_token_id = test.host.get_contract_id_from_asset(Asset::Native).unwrap();
+    let expected_token_address =
+        ScAddress::Contract(test.host.get_contract_id_from_asset(Asset::Native).unwrap());
 
-    assert_eq!(token.id.to_vec(), expected_token_id.0.to_vec());
+    assert_eq!(
+        token.address.to_sc_address().unwrap(),
+        expected_token_address
+    );
 
     assert_eq!(token.symbol().unwrap().to_vec(), b"native".to_vec());
     assert_eq!(token.decimals().unwrap(), 7);
@@ -379,8 +386,12 @@ fn test_asset_init(asset_code: &[u8]) {
         })
     };
     let token = TestToken::new_from_asset(&test.host, asset.clone());
-    let expected_token_id = test.host.get_contract_id_from_asset(asset).unwrap();
-    assert_eq!(token.id.to_vec(), expected_token_id.0.to_vec());
+    let expected_token_address =
+        ScAddress::Contract(test.host.get_contract_id_from_asset(asset).unwrap());
+    assert_eq!(
+        token.address.to_sc_address().unwrap(),
+        expected_token_address
+    );
 
     assert_eq!(token.symbol().unwrap().to_vec(), asset_code.to_vec());
     assert_eq!(token.decimals().unwrap(), 7);
@@ -1546,7 +1557,7 @@ fn test_auth_rejected_for_incorrect_nonce() {
     authorize_single_invocation_with_nonce(
         &test.host,
         &admin,
-        &token.id,
+        &token.address,
         "mint",
         args.clone(),
         Some(1),
@@ -1554,7 +1565,7 @@ fn test_auth_rejected_for_incorrect_nonce() {
     assert!(test
         .host
         .call(
-            token.id.clone().into(),
+            token.address.clone().into(),
             Symbol::try_from_small_str("mint").unwrap(),
             args.clone().into(),
         )
@@ -1564,14 +1575,14 @@ fn test_auth_rejected_for_incorrect_nonce() {
     authorize_single_invocation_with_nonce(
         &test.host,
         &admin,
-        &token.id,
+        &token.address,
         "mint",
         args.clone(),
         Some(0),
     );
     test.host
         .call(
-            token.id.clone().into(),
+            token.address.clone().into(),
             Symbol::try_from_small_str("mint").unwrap(),
             args.clone().into(),
         )
@@ -1581,7 +1592,7 @@ fn test_auth_rejected_for_incorrect_nonce() {
     authorize_single_invocation_with_nonce(
         &test.host,
         &admin,
-        &token.id,
+        &token.address,
         "mint",
         args.clone(),
         Some(0),
@@ -1589,7 +1600,7 @@ fn test_auth_rejected_for_incorrect_nonce() {
     assert!(test
         .host
         .call(
-            token.id.clone().into(),
+            token.address.clone().into(),
             Symbol::try_from_small_str("mint").unwrap(),
             args.clone().into(),
         )
@@ -1599,14 +1610,14 @@ fn test_auth_rejected_for_incorrect_nonce() {
     authorize_single_invocation_with_nonce(
         &test.host,
         &admin,
-        &token.id,
+        &token.address,
         "mint",
         args.clone(),
         Some(1),
     );
     test.host
         .call(
-            token.id.into(),
+            token.address.into(),
             Symbol::try_from_small_str("mint").unwrap(),
             args.into(),
         )
@@ -1625,22 +1636,22 @@ fn test_auth_rejected_for_incorrect_payload() {
     let args = host_vec![&test.host, user.address(&test.host), 100_i128];
 
     // Incorrect signer.
-    authorize_single_invocation(&test.host, &user, &token.id, "mint", args.clone());
+    authorize_single_invocation(&test.host, &user, &token.address, "mint", args.clone());
     assert!(test
         .host
         .call(
-            token.id.clone().into(),
+            token.address.clone().into(),
             Symbol::try_from_small_str("mint").unwrap(),
             args.clone().into(),
         )
         .is_err());
 
     // Incorrect function.
-    authorize_single_invocation(&test.host, &admin, &token.id, "burn", args.clone());
+    authorize_single_invocation(&test.host, &admin, &token.address, "burn", args.clone());
     assert!(test
         .host
         .call(
-            token.id.clone().into(),
+            token.address.clone().into(),
             Symbol::try_from_small_str("mint").unwrap(),
             args.clone().into(),
         )
@@ -1650,7 +1661,7 @@ fn test_auth_rejected_for_incorrect_payload() {
     authorize_single_invocation(
         &test.host,
         &admin,
-        &token.id,
+        &token.address,
         "mint",
         host_vec![
             &test.host,
@@ -1662,7 +1673,7 @@ fn test_auth_rejected_for_incorrect_payload() {
     assert!(test
         .host
         .call(
-            token.id.clone().into(),
+            token.address.clone().into(),
             Symbol::try_from_small_str("mint").unwrap(),
             args.clone().into(),
         )
@@ -1672,7 +1683,7 @@ fn test_auth_rejected_for_incorrect_payload() {
     authorize_single_invocation(
         &test.host,
         &admin,
-        &token.id,
+        &token.address,
         "mint",
         host_vec![
             &test.host,
@@ -1684,18 +1695,18 @@ fn test_auth_rejected_for_incorrect_payload() {
     assert!(test
         .host
         .call(
-            token.id.clone().into(),
+            token.address.clone().into(),
             Symbol::try_from_small_str("mint").unwrap(),
             args.clone().into(),
         )
         .is_err());
 
     // Correct signer and payload result in success.
-    authorize_single_invocation(&test.host, &admin, &token.id, "mint", args.clone());
+    authorize_single_invocation(&test.host, &admin, &token.address, "mint", args.clone());
 
     test.host
         .call(
-            token.id.into(),
+            token.address.into(),
             Symbol::try_from_small_str("mint").unwrap(),
             args.into(),
         )
@@ -2559,17 +2570,13 @@ fn test_custom_account_auth() {
 
     let test = TokenTest::setup();
     let admin_kp = generate_keypair();
-    let account_contract_id_obj = test
-        .host
-        .register_test_contract_wasm(SIMPLE_ACCOUNT_CONTRACT)
-        .unwrap();
-    let account_contract_id = test
+    let account_contract_addr_obj = test
         .host
-        .hash_from_bytesobj_input("account_contract_id", account_contract_id_obj)
-        .unwrap();
-
+        .register_test_contract_wasm(SIMPLE_ACCOUNT_CONTRACT);
+    let account_contract_addr: Address =
+        account_contract_addr_obj.try_into_val(&test.host).unwrap();
     let admin = TestSigner::AccountContract(AccountContractSigner {
-        id: account_contract_id.clone(),
+        address: account_contract_addr.clone(),
         sign: simple_account_sign_fn(&test.host, &admin_kp),
     });
 
@@ -2584,7 +2591,7 @@ fn test_custom_account_auth() {
     // Initialize the admin account
     test.host
         .call(
-            account_contract_id_obj,
+            account_contract_addr_obj,
             Symbol::try_from_small_str("init").unwrap(),
             host_vec![&test.host, admin_public_key].into(),
         )
@@ -2603,7 +2610,7 @@ fn test_custom_account_auth() {
     // owner.
     let new_admin_kp = generate_keypair();
     let new_admin = TestSigner::AccountContract(AccountContractSigner {
-        id: account_contract_id,
+        address: account_contract_addr,
         sign: simple_account_sign_fn(&test.host, &new_admin_kp),
     });
     let new_admin_public_key = BytesN::<32>::try_from_val(
@@ -2621,7 +2628,7 @@ fn test_custom_account_auth() {
     authorize_single_invocation(
         &test.host,
         &admin,
-        &account_contract_id_obj.try_into_val(&test.host).unwrap(),
+        &account_contract_addr_obj.try_into_val(&test.host).unwrap(),
         "set_owner",
         host_vec![&test.host, new_admin_public_key],
     );
@@ -2629,7 +2636,7 @@ fn test_custom_account_auth() {
     // Change the owner of the account.
     test.host
         .call(
-            account_contract_id_obj,
+            account_contract_addr_obj,
             Symbol::try_from_small_str("set_owner").unwrap(),
             host_vec![&test.host, new_admin_public_key].into(),
         )
@@ -2659,7 +2666,7 @@ fn test_recording_auth_for_token() {
     let args = host_vec![&test.host, user.address(&test.host), 100_i128];
     test.host
         .call(
-            token.id.clone().into(),
+            token.address.clone().into(),
             Symbol::try_from_small_str("mint").unwrap(),
             args.clone().into(),
         )
@@ -2671,24 +2678,29 @@ fn test_recording_auth_for_token() {
         vec![RecordedAuthPayload {
             address: Some(admin.address(&test.host).to_sc_address().unwrap()),
             nonce: Some(0),
-            invocation: xdr::AuthorizedInvocation {
-                contract_id: Hash(token.id.to_array().unwrap()),
-                function_name: xdr::ScSymbol("mint".try_into().unwrap()),
-                args: ScVec(
-                    vec![
-                        ScVal::try_from_val(
-                            &test.host,
-                            &RawVal::try_from_val(&test.host, &user.address(&test.host)).unwrap()
-                        )
-                        .unwrap(),
-                        ScVal::try_from_val(
-                            &test.host,
-                            &RawVal::try_from_val(&test.host, &100_i128).unwrap()
-                        )
-                        .unwrap()
-                    ]
-                    .try_into()
-                    .unwrap()
+            invocation: SorobanAuthorizedInvocation {
+                function: SorobanAuthorizedFunction::ContractFn(
+                    SorobanAuthorizedContractFunction {
+                        contract_address: token.address.to_sc_address().unwrap(),
+                        function_name: xdr::ScSymbol("mint".try_into().unwrap()),
+                        args: ScVec(
+                            vec![
+                                ScVal::try_from_val(
+                                    &test.host,
+                                    &RawVal::try_from_val(&test.host, &user.address(&test.host))
+                                        .unwrap()
+                                )
+                                .unwrap(),
+                                ScVal::try_from_val(
+                                    &test.host,
+                                    &RawVal::try_from_val(&test.host, &100_i128).unwrap()
+                                )
+                                .unwrap()
+                            ]
+                            .try_into()
+                            .unwrap()
+                        ),
+                    }
                 ),
                 sub_invocations: Default::default(),
             }
@@ -2696,16 +2708,23 @@ fn test_recording_auth_for_token() {
     );
 
     assert_eq!(
-        test.host.get_authenticated_top_authorizations().unwrap(),
+        test.host.get_authenticated_authorizations().unwrap(),
         vec![(
             test.host
                 .visit_obj(admin.address(&test.host).into(), |addr: &ScAddress| Ok(
                     addr.clone()
                 ))
                 .unwrap(),
-            Hash(token.id.to_array().unwrap()),
-            xdr::ScSymbol("mint".try_into().unwrap()),
-            test.host.call_args_to_scvec(args.into()).unwrap()
+            SorobanAuthorizedInvocation {
+                function: SorobanAuthorizedFunction::ContractFn(
+                    SorobanAuthorizedContractFunction {
+                        contract_address: token.address.to_sc_address().unwrap(),
+                        function_name: ScSymbol("mint".try_into().unwrap()),
+                        args: test.host.call_args_to_scvec(args.into()).unwrap()
+                    }
+                ),
+                sub_invocations: Default::default()
+            }
         )]
     );
 }
diff --git a/soroban-env-host/src/test/util.rs b/soroban-env-host/src/test/util.rs
index f748430f..7fb086f2 100644
--- a/soroban-env-host/src/test/util.rs
+++ b/soroban-env-host/src/test/util.rs
@@ -3,11 +3,12 @@ use std::rc::Rc;
 use rand::{thread_rng, RngCore};
 use soroban_env_common::{
     xdr::{
-        AccountEntry, AccountId, ContractCostType, ContractId, CreateContractArgs, HostFunction,
-        HostFunctionArgs, LedgerEntry, LedgerEntryData, LedgerKey, PublicKey, ScContractExecutable,
-        ScErrorCode, ScErrorType, ScVal, ScVec, Uint256, UploadContractWasmArgs,
+        AccountEntry, AccountId, ContractCostType, ContractIdPreimage,
+        ContractIdPreimageFromAddress, CreateContractArgs, HostFunction, LedgerEntry,
+        LedgerEntryData, LedgerKey, PublicKey, ScAddress, ScContractExecutable, ScVal, ScVec,
+        Uint256,
     },
-    BytesObject, RawVal, TryIntoVal, VecObject,
+    AddressObject, BytesObject, RawVal, TryIntoVal, VecObject,
 };
 
 use crate::{
@@ -167,39 +168,35 @@ impl Host {
     }
 
     // Registers a contract with provided WASM source and returns the registered
-    // contract ID.
+    // contract's address.
     // This relies on the host to have no footprint enforcement.
-    pub(crate) fn register_test_contract_wasm(
-        &self,
-        contract_wasm: &[u8],
-    ) -> Result<BytesObject, HostError> {
-        self.set_source_account(generate_account_id());
-
-        let wasm_id: RawVal = self.invoke_functions(vec![HostFunction {
-            args: HostFunctionArgs::UploadContractWasm(UploadContractWasmArgs {
-                code: contract_wasm.to_vec().try_into().map_err(|_| {
-                    self.err(
-                        ScErrorType::Context,
-                        ScErrorCode::ExceededLimit,
-                        "too large wasm",
-                        &[],
-                    )
-                })?,
-            }),
-            auth: Default::default(),
-        }])?[0]
-            .try_into_val(self)?;
-
-        let wasm_id = self.hash_from_bytesobj_input("wasm_hash", wasm_id.try_into()?)?;
-        let id_obj: RawVal = self.invoke_functions(vec![HostFunction {
-            args: HostFunctionArgs::CreateContract(CreateContractArgs {
-                contract_id: ContractId::SourceAccount(Uint256(generate_bytes_array())),
+    pub(crate) fn register_test_contract_wasm(&self, contract_wasm: &[u8]) -> AddressObject {
+        let prev_auth_manager = self.snapshot_auth_manager();
+        self.switch_to_recording_auth();
+
+        let wasm_id: RawVal = self
+            .invoke_function(HostFunction::UploadContractWasm(
+                contract_wasm.to_vec().try_into().unwrap(),
+            ))
+            .unwrap()
+            .try_into_val(self)
+            .unwrap();
+
+        let wasm_id = self
+            .hash_from_bytesobj_input("wasm_hash", wasm_id.try_into().unwrap())
+            .unwrap();
+        let address_obj: RawVal = self
+            .invoke_function(HostFunction::CreateContract(CreateContractArgs {
+                contract_id_preimage: ContractIdPreimage::Address(ContractIdPreimageFromAddress {
+                    address: ScAddress::Contract(xdr::Hash(generate_bytes_array())),
+                    salt: Uint256(generate_bytes_array()),
+                }),
                 executable: ScContractExecutable::WasmRef(wasm_id),
-            }),
-            auth: Default::default(),
-        }])?[0]
-            .try_into_val(self)?;
-        self.remove_source_account();
-        Ok(id_obj.try_into()?)
+            }))
+            .unwrap()
+            .try_into_val(self)
+            .unwrap();
+        self.set_auth_manager(prev_auth_manager);
+        address_obj.try_into().unwrap()
     }
 }
diff --git a/soroban-synth-wasm/src/test.rs b/soroban-synth-wasm/src/test.rs
index 8d863538..e3e1dc9e 100644
--- a/soroban-synth-wasm/src/test.rs
+++ b/soroban-synth-wasm/src/test.rs
@@ -46,7 +46,7 @@ fn test_synth_wasm() {
             i64.and
             i64.const 14
             i64.ne
-            if  ;; label = @1
+            if ;; label = @1
               unreachable
             end
             local.get 0
@@ -239,10 +239,10 @@ fn br() {
         (module
           (type (;0;) (func (result i64)))
           (func (;0;) (type 0) (result i64)
-            block  ;; label = @1
-              block  ;; label = @2
-                block  ;; label = @3
-                  block  ;; label = @4
+            block ;; label = @1
+              block ;; label = @2
+                block ;; label = @3
+                  block ;; label = @4
                     br 0 (;@4;)
                   end
                   br 0 (;@3;)
@@ -289,10 +289,10 @@ fn br_table() {
         (module
           (type (;0;) (func (result i64)))
           (func (;0;) (type 0) (result i64)
-            block  ;; label = @1
-              block  ;; label = @2
-                block  ;; label = @3
-                  block  ;; label = @4
+            block ;; label = @1
+              block ;; label = @2
+                block ;; label = @3
+                  block ;; label = @4
                     i32.const 10
                     br_table 0 (;@4;) 1 (;@3;) 2 (;@2;) 3 (;@1;) 3 (;@1;)
                   end
diff --git a/soroban-test-wasms/wasm-workspace/Cargo.lock b/soroban-test-wasms/wasm-workspace/Cargo.lock
index 3bfe8f42..86ce4e03 100644
--- a/soroban-test-wasms/wasm-workspace/Cargo.lock
+++ b/soroban-test-wasms/wasm-workspace/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
 
 [[package]]
 name = "addr2line"
-version = "0.17.0"
+version = "0.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
+checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
 dependencies = [
  "gimli",
 ]
@@ -39,7 +39,6 @@ dependencies = [
 name = "auth_test_contract"
 version = "0.0.0"
 dependencies = [
- "soroban-env-common",
  "soroban-sdk",
 ]
 
@@ -51,9 +50,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
 [[package]]
 name = "backtrace"
-version = "0.3.66"
+version = "0.3.67"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
+checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
 dependencies = [
  "addr2line",
  "cc",
@@ -78,9 +77,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
 
 [[package]]
 name = "base64"
-version = "0.21.0"
+version = "0.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
+checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105"
 
 [[package]]
 name = "block-buffer"
@@ -93,9 +92,9 @@ dependencies = [
 
 [[package]]
 name = "bumpalo"
-version = "3.11.1"
+version = "3.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
+checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
 
 [[package]]
 name = "byteorder"
@@ -112,14 +111,14 @@ dependencies = [
  "num-bigint",
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
 name = "cc"
-version = "1.0.76"
+version = "1.0.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
 
 [[package]]
 name = "cfg-if"
@@ -129,9 +128,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "chrono"
-version = "0.4.22"
+version = "0.4.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
+checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
 dependencies = [
  "iana-time-zone",
  "num-integer",
@@ -140,27 +139,17 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "codespan-reporting"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
-dependencies = [
- "termcolor",
- "unicode-width",
-]
-
 [[package]]
 name = "core-foundation-sys"
-version = "0.8.3"
+version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
 
 [[package]]
 name = "cpufeatures"
-version = "0.2.5"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
+checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58"
 dependencies = [
  "libc",
 ]
@@ -189,50 +178,6 @@ dependencies = [
  "zeroize",
 ]
 
-[[package]]
-name = "cxx"
-version = "1.0.81"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97abf9f0eca9e52b7f81b945524e76710e6cb2366aead23b7d4fbf72e281f888"
-dependencies = [
- "cc",
- "cxxbridge-flags",
- "cxxbridge-macro",
- "link-cplusplus",
-]
-
-[[package]]
-name = "cxx-build"
-version = "1.0.81"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cc32cc5fea1d894b77d269ddb9f192110069a8a9c1f1d441195fba90553dea3"
-dependencies = [
- "cc",
- "codespan-reporting",
- "once_cell",
- "proc-macro2",
- "quote",
- "scratch",
- "syn 1.0.103",
-]
-
-[[package]]
-name = "cxxbridge-flags"
-version = "1.0.81"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ca220e4794c934dc6b1207c3b42856ad4c302f2df1712e9f8d2eec5afaacf1f"
-
-[[package]]
-name = "cxxbridge-macro"
-version = "1.0.81"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b846f081361125bfc8dc9d3940c84e1fd83ba54bbca7b17cd29483c828be0704"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.103",
-]
-
 [[package]]
 name = "darling"
 version = "0.20.1"
@@ -254,7 +199,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "strsim",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -265,7 +210,7 @@ checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a"
 dependencies = [
  "darling_core",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -276,7 +221,7 @@ checksum = "f3cdeb9ec472d588e539a818b2dee436825730da08ad0017c4b1a17676bdc8b7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.103",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -296,9 +241,9 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
 
 [[package]]
 name = "ed25519"
-version = "1.5.2"
+version = "1.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369"
+checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7"
 dependencies = [
  "signature",
 ]
@@ -319,9 +264,9 @@ dependencies = [
 
 [[package]]
 name = "either"
-version = "1.8.0"
+version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
+checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
 
 [[package]]
 name = "ethnum"
@@ -382,7 +327,6 @@ dependencies = [
 name = "example_invoke_contract"
 version = "0.0.0"
 dependencies = [
- "soroban-env-common",
  "soroban-sdk",
 ]
 
@@ -422,9 +366,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 
 [[package]]
 name = "generic-array"
-version = "0.14.6"
+version = "0.14.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
 dependencies = [
  "typenum",
  "version_check",
@@ -443,9 +387,9 @@ dependencies = [
 
 [[package]]
 name = "gimli"
-version = "0.26.2"
+version = "0.27.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
+checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
 
 [[package]]
 name = "hashbrown"
@@ -464,26 +408,25 @@ dependencies = [
 
 [[package]]
 name = "iana-time-zone"
-version = "0.1.53"
+version = "0.1.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
+checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c"
 dependencies = [
  "android_system_properties",
  "core-foundation-sys",
  "iana-time-zone-haiku",
  "js-sys",
  "wasm-bindgen",
- "winapi",
+ "windows",
 ]
 
 [[package]]
 name = "iana-time-zone-haiku"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
 dependencies = [
- "cxx",
- "cxx-build",
+ "cc",
 ]
 
 [[package]]
@@ -494,9 +437,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
 
 [[package]]
 name = "indexmap"
-version = "1.9.1"
+version = "1.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
 dependencies = [
  "autocfg",
  "hashbrown",
@@ -520,39 +463,30 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "1.0.4"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
+checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
 
 [[package]]
 name = "js-sys"
-version = "0.3.60"
+version = "0.3.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
+checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790"
 dependencies = [
  "wasm-bindgen",
 ]
 
 [[package]]
 name = "libc"
-version = "0.2.137"
+version = "0.2.144"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
+checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
 
 [[package]]
 name = "libm"
-version = "0.2.6"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
-
-[[package]]
-name = "link-cplusplus"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369"
-dependencies = [
- "cc",
-]
+checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
 
 [[package]]
 name = "log"
@@ -577,9 +511,9 @@ checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
 
 [[package]]
 name = "miniz_oxide"
-version = "0.5.4"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
 dependencies = [
  "adler",
 ]
@@ -603,7 +537,7 @@ checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.103",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -639,18 +573,18 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.29.0"
+version = "0.30.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
+checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "once_cell"
-version = "1.16.0"
+version = "1.17.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
+checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
 
 [[package]]
 name = "opaque-debug"
@@ -666,28 +600,28 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
 
 [[package]]
 name = "prettyplease"
-version = "0.2.4"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ceca8aaf45b5c46ec7ed39fff75f57290368c1846d33d24a122ca81416ab058"
+checksum = "3b69d39aab54d069e7f2fe8cb970493e7834601ca2d8c65fd7bbd183578080d1"
 dependencies = [
  "proc-macro2",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.56"
+version = "1.0.58"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
+checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.26"
+version = "1.0.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
+checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
 dependencies = [
  "proc-macro2",
 ]
@@ -735,47 +669,41 @@ dependencies = [
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.21"
+version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
+checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
 
 [[package]]
 name = "ryu"
-version = "1.0.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
-
-[[package]]
-name = "scratch"
-version = "1.0.2"
+version = "1.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
 
 [[package]]
 name = "serde"
-version = "1.0.162"
+version = "1.0.163"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6"
+checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.162"
+version = "1.0.163"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6"
+checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.87"
+version = "1.0.96"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45"
+checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
 dependencies = [
  "itoa",
  "ryu",
@@ -788,7 +716,7 @@ version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9f02d8aa6e3c385bf084924f660ce2a3a6bd333ba55b35e8590b321f35d88513"
 dependencies = [
- "base64 0.21.0",
+ "base64 0.21.1",
  "chrono",
  "hex",
  "indexmap",
@@ -807,7 +735,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -840,7 +768,7 @@ dependencies = [
  "soroban-env-macros",
  "soroban-wasmi",
  "static_assertions",
- "stellar-xdr 0.0.16 (git+https://github.com/stellar/rs-stellar-xdr?rev=eda841f3c08a023bb50f7f79b8b8b8d6083aad83)",
+ "stellar-xdr 0.0.16 (git+https://github.com/stellar/rs-stellar-xdr?rev=979c0a5dbae204a2efe7bf52c1229081f685c2a0)",
 ]
 
 [[package]]
@@ -881,8 +809,8 @@ dependencies = [
  "quote",
  "serde",
  "serde_json",
- "stellar-xdr 0.0.16 (git+https://github.com/stellar/rs-stellar-xdr?rev=eda841f3c08a023bb50f7f79b8b8b8d6083aad83)",
- "syn 2.0.15",
+ "stellar-xdr 0.0.16 (git+https://github.com/stellar/rs-stellar-xdr?rev=979c0a5dbae204a2efe7bf52c1229081f685c2a0)",
+ "syn 2.0.16",
  "thiserror",
 ]
 
@@ -904,7 +832,7 @@ dependencies = [
  "itertools",
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -933,7 +861,7 @@ dependencies = [
  "soroban-env-common",
  "soroban-spec",
  "stellar-xdr 0.0.16 (git+https://github.com/stellar/rs-stellar-xdr?rev=b283ec0bcb791610013107b9eab7d7ff07a65db1)",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -951,7 +879,7 @@ dependencies = [
  "serde_json",
  "sha2",
  "stellar-xdr 0.0.16 (git+https://github.com/stellar/rs-stellar-xdr?rev=b283ec0bcb791610013107b9eab7d7ff07a65db1)",
- "syn 2.0.15",
+ "syn 2.0.16",
  "thiserror",
  "wasmparser",
 ]
@@ -980,9 +908,9 @@ dependencies = [
 
 [[package]]
 name = "spin"
-version = "0.9.4"
+version = "0.9.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
 
 [[package]]
 name = "static_assertions"
@@ -1002,8 +930,10 @@ dependencies = [
 [[package]]
 name = "stellar-xdr"
 version = "0.0.16"
-source = "git+https://github.com/stellar/rs-stellar-xdr?rev=b283ec0bcb791610013107b9eab7d7ff07a65db1#b283ec0bcb791610013107b9eab7d7ff07a65db1"
+source = "git+https://github.com/stellar/rs-stellar-xdr?rev=979c0a5dbae204a2efe7bf52c1229081f685c2a0#979c0a5dbae204a2efe7bf52c1229081f685c2a0"
 dependencies = [
+ "arbitrary",
+ "base64 0.13.1",
  "crate-git-revision",
  "hex",
  "serde",
@@ -1013,10 +943,8 @@ dependencies = [
 [[package]]
 name = "stellar-xdr"
 version = "0.0.16"
-source = "git+https://github.com/stellar/rs-stellar-xdr?rev=eda841f3c08a023bb50f7f79b8b8b8d6083aad83#eda841f3c08a023bb50f7f79b8b8b8d6083aad83"
+source = "git+https://github.com/stellar/rs-stellar-xdr?rev=b283ec0bcb791610013107b9eab7d7ff07a65db1#b283ec0bcb791610013107b9eab7d7ff07a65db1"
 dependencies = [
- "arbitrary",
- "base64 0.13.1",
  "crate-git-revision",
  "hex",
  "serde",
@@ -1031,15 +959,15 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
 [[package]]
 name = "subtle"
-version = "2.4.1"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
 
 [[package]]
 name = "syn"
-version = "1.0.103"
+version = "1.0.109"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1048,61 +976,40 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.15"
+version = "2.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01"
 dependencies = [
  "proc-macro2",
  "quote",
  "unicode-ident",
 ]
 
-[[package]]
-name = "synstructure"
-version = "0.12.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.103",
- "unicode-xid",
-]
-
-[[package]]
-name = "termcolor"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
-dependencies = [
- "winapi-util",
-]
-
 [[package]]
 name = "thiserror"
-version = "1.0.37"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.37"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.103",
+ "syn 2.0.16",
 ]
 
 [[package]]
 name = "time"
-version = "0.3.17"
+version = "0.3.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
+checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc"
 dependencies = [
  "itoa",
  "serde",
@@ -1112,42 +1019,30 @@ dependencies = [
 
 [[package]]
 name = "time-core"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
+checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
 
 [[package]]
 name = "time-macros"
-version = "0.2.6"
+version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2"
+checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
 dependencies = [
  "time-core",
 ]
 
 [[package]]
 name = "typenum"
-version = "1.15.0"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
-
-[[package]]
-name = "unicode-width"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.4"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
+checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
 
 [[package]]
 name = "version_check"
@@ -1163,9 +1058,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.83"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
+checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73"
 dependencies = [
  "cfg-if",
  "wasm-bindgen-macro",
@@ -1173,24 +1068,24 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.83"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
+checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb"
 dependencies = [
  "bumpalo",
  "log",
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 1.0.103",
+ "syn 2.0.16",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.83"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
+checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -1198,22 +1093,22 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.83"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
+checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.103",
+ "syn 2.0.16",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.83"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
+checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93"
 
 [[package]]
 name = "wasmparser"
@@ -1250,19 +1145,76 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 
 [[package]]
-name = "winapi-util"
-version = "0.1.5"
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows"
+version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
 dependencies = [
- "winapi",
+ "windows-targets",
 ]
 
 [[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
+name = "windows-targets"
+version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
 
 [[package]]
 name = "zeroize"
@@ -1275,12 +1227,11 @@ dependencies = [
 
 [[package]]
 name = "zeroize_derive"
-version = "1.3.2"
+version = "1.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17"
+checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.103",
- "synstructure",
+ "syn 2.0.16",
 ]
diff --git a/soroban-test-wasms/wasm-workspace/Cargo.toml b/soroban-test-wasms/wasm-workspace/Cargo.toml
index f1de7631..3e97f20e 100644
--- a/soroban-test-wasms/wasm-workspace/Cargo.toml
+++ b/soroban-test-wasms/wasm-workspace/Cargo.toml
@@ -49,10 +49,6 @@ soroban-env-common = { path = "../../soroban-env-common" }
 soroban-env-guest = { path = "../../soroban-env-guest" }
 soroban-env-host = { path = "../../soroban-env-host" }
 
-[workspace.dependencies.soroban-env-common]
-version = "0.0.16"
-git = "https://github.com/stellar/rs-soroban-env"
-
 [workspace.dependencies.soroban-sdk]
 version = "0.8.0"
 git = "https://github.com/stellar/rs-soroban-sdk"
@@ -62,5 +58,5 @@ git = "https://github.com/stellar/rs-soroban-sdk"
 [patch."https://github.com/stellar/rs-soroban-sdk"]
 soroban-sdk = { path = "../../../rs-soroban-sdk/soroban-sdk" }
 
-#[patch."https://github.com/stellar/rs-stellar-xdr"]
-#stellar-xdr = { path = "../../../rs-stellar-xdr/" }
+# [patch."https://github.com/stellar/rs-stellar-xdr"]
+# stellar-xdr = { path = "../../../rs-stellar-xdr/" }
diff --git a/soroban-test-wasms/wasm-workspace/auth/Cargo.toml b/soroban-test-wasms/wasm-workspace/auth/Cargo.toml
index ba99e83d..cd24e3b4 100644
--- a/soroban-test-wasms/wasm-workspace/auth/Cargo.toml
+++ b/soroban-test-wasms/wasm-workspace/auth/Cargo.toml
@@ -13,4 +13,3 @@ doctest = false
 
 [dependencies]
 soroban-sdk = { workspace = true }
-soroban-env-common = { workspace = true }
diff --git a/soroban-test-wasms/wasm-workspace/auth/src/lib.rs b/soroban-test-wasms/wasm-workspace/auth/src/lib.rs
index a0847ea9..e4cfe5ca 100644
--- a/soroban-test-wasms/wasm-workspace/auth/src/lib.rs
+++ b/soroban-test-wasms/wasm-workspace/auth/src/lib.rs
@@ -1,13 +1,12 @@
 #![no_std]
-use soroban_env_common::{AddressObject, Env as _, TryFromVal};
-use soroban_sdk::{contractimpl, contracttype, vec, Address, BytesN, Env, IntoVal, Symbol, Vec};
+use soroban_sdk::{contractimpl, contracttype, vec, Address, Env, IntoVal, Symbol, Vec};
 
 struct AuthContract;
 
 #[derive(Clone)]
 #[contracttype]
 pub struct TreeNode {
-    pub id: BytesN<32>,
+    pub addr: Address,
     pub need_auth: Vec<bool>,
     pub children: Vec<TreeNode>,
 }
@@ -30,19 +29,17 @@ impl AuthContract {
         }
         for child in tree.children.iter() {
             let child = child.unwrap();
-            let child_ao: AddressObject = env.contract_id_to_address(child.id.to_object()).unwrap();
             env.invoke_contract::<()>(
-                &Address::try_from_val(&env, &child_ao).unwrap(),
+                &child.addr.clone(),
                 &Symbol::short("tree_fn"),
                 (addresses.clone(), child).into_val(&env),
             );
         }
     }
 
-    pub fn order_fn(env: Env, addr: Address, child_id: BytesN<32>) {
-        let child_ao: AddressObject = env.contract_id_to_address(child_id.to_object()).unwrap();
+    pub fn order_fn(env: Env, addr: Address, child_id: Address) {
         env.invoke_contract::<()>(
-            &Address::try_from_val(&env, &child_ao).unwrap(),
+            &child_id,
             &Symbol::short("do_auth"),
             (&addr, 10_u32).into_val(&env),
         );
diff --git a/soroban-test-wasms/wasm-workspace/invoke_contract/Cargo.toml b/soroban-test-wasms/wasm-workspace/invoke_contract/Cargo.toml
index a681ba61..4e39942b 100644
--- a/soroban-test-wasms/wasm-workspace/invoke_contract/Cargo.toml
+++ b/soroban-test-wasms/wasm-workspace/invoke_contract/Cargo.toml
@@ -13,4 +13,3 @@ doctest = false
 
 [dependencies]
 soroban-sdk = { workspace = true }
-soroban-env-common = { workspace = true }
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 7ba1e299..a2db3efc 100644
--- a/soroban-test-wasms/wasm-workspace/invoke_contract/src/lib.rs
+++ b/soroban-test-wasms/wasm-workspace/invoke_contract/src/lib.rs
@@ -1,6 +1,5 @@
 #![no_std]
-use soroban_env_common::{AddressObject, Env as _, TryFromVal};
-use soroban_sdk::{contractimpl, vec, Address, BytesN, Env, IntoVal, Symbol};
+use soroban_sdk::{contractimpl, vec, Address, Env, IntoVal, Symbol};
 
 pub struct Contract;
 
@@ -11,12 +10,11 @@ impl Contract {
         a + b
     }
 
-    pub fn add_with(env: Env, x: i32, y: i32, contract_id: BytesN<32>) -> i32 {
+    pub fn add_with(env: Env, x: i32, y: i32, contract_id: Address) -> i32 {
         env.events()
             .publish((Symbol::short("add_with"),), (x, y, contract_id.clone()));
-        let ao: AddressObject = env.contract_id_to_address(contract_id.to_object()).unwrap();
         env.invoke_contract(
-            &Address::try_from_val(&env, &ao).unwrap(),
+            &contract_id,
             &Symbol::short("add"),
             vec![&env, x.into_val(&env), y.into_val(&env)],
         )