diff --git a/forc-plugins/forc-client/tests/deploy.rs b/forc-plugins/forc-client/tests/deploy.rs
index 3f786293792..04b5a261a86 100644
--- a/forc-plugins/forc-client/tests/deploy.rs
+++ b/forc-plugins/forc-client/tests/deploy.rs
@@ -107,7 +107,7 @@ async fn simple_deploy() {
     node.kill().unwrap();
     let expected = vec![DeployedContract {
         id: ContractId::from_str(
-            "428896412bda8530282a7b8fca5d20b2a73f30037612ca3a31750cf3bf0e976a",
+            "822c8d3672471f64f14f326447793c7377b6e430122db23b622880ccbd8a33ef",
         )
         .unwrap(),
     }];
diff --git a/sway-core/src/ir_generation/function.rs b/sway-core/src/ir_generation/function.rs
index c459a5cd6fa..b430929dcf8 100644
--- a/sway-core/src/ir_generation/function.rs
+++ b/sway-core/src/ir_generation/function.rs
@@ -1717,6 +1717,224 @@ impl<'eng> FnCompiler<'eng> {
                     Ok(increase_len(&mut s.current_block, context, len, 8 - offset))
                 }
 
+                fn grow_if_needed(
+                    s: &mut FnCompiler<'_>,
+                    context: &mut Context,
+                    ptr: Value,
+                    cap: Value,
+                    len: Value,
+                    needed_size: Value,
+                ) -> (Value, Value) {
+                    assert!(ptr.get_type(context).unwrap().is_ptr(context));
+                    assert!(cap.get_type(context).unwrap().is_uint64(context));
+
+                    let ptr_u8 = Type::new_ptr(context, Type::get_uint8(context));
+
+                    // merge block has two arguments: ptr, cap
+                    let merge_block = s.function.create_block(context, None);
+                    let merge_block_ptr = Value::new_argument(
+                        context,
+                        BlockArgument {
+                            block: merge_block,
+                            idx: 0,
+                            ty: ptr_u8,
+                        },
+                    );
+                    merge_block.add_arg(context, merge_block_ptr);
+                    let merge_block_cap = Value::new_argument(
+                        context,
+                        BlockArgument {
+                            block: merge_block,
+                            idx: 1,
+                            ty: Type::get_uint64(context),
+                        },
+                    );
+                    merge_block.add_arg(context, merge_block_cap);
+
+                    let true_block_begin = s.function.create_block(context, None);
+                    let false_block_begin = s.function.create_block(context, None);
+
+                    // if len + needed_size > cap
+                    let needed_cap = s.current_block.append(context).binary_op(
+                        BinaryOpKind::Add,
+                        len,
+                        needed_size,
+                    );
+                    let needs_realloc = s.current_block.append(context).cmp(
+                        Predicate::GreaterThan,
+                        needed_cap,
+                        cap,
+                    );
+                    s.current_block.append(context).conditional_branch(
+                        needs_realloc,
+                        true_block_begin,
+                        false_block_begin,
+                        vec![],
+                        vec![],
+                    );
+
+                    // needs realloc block
+                    // new_cap = cap * 2
+                    // aloc new_cap
+                    // mcp hp old_ptr len
+                    // hp: ptr u8
+                    s.current_block = true_block_begin;
+                    let u8 = Type::get_uint8(context);
+                    let ptr_u8 = Type::new_ptr(context, u8);
+
+                    let two = Constant::new_uint(context, 64, 2);
+                    let two = Value::new_constant(context, two);
+                    let new_cap =
+                        s.current_block
+                            .append(context)
+                            .binary_op(BinaryOpKind::Mul, cap, two);
+
+                    let new_ptr = s.current_block.append(context).asm_block(
+                        vec![
+                            AsmArg {
+                                name: Ident::new_no_span("new_cap".into()),
+                                initializer: Some(new_cap),
+                            },
+                            AsmArg {
+                                name: Ident::new_no_span("old_ptr".into()),
+                                initializer: Some(ptr),
+                            },
+                            AsmArg {
+                                name: Ident::new_no_span("len".into()),
+                                initializer: Some(len),
+                            },
+                        ],
+                        vec![
+                            AsmInstruction {
+                                op_name: Ident::new_no_span("aloc".into()),
+                                args: vec![Ident::new_no_span("new_cap".into())],
+                                immediate: None,
+                                metadata: None,
+                            },
+                            AsmInstruction {
+                                op_name: Ident::new_no_span("mcp".into()),
+                                args: vec![
+                                    Ident::new_no_span("hp".into()),
+                                    Ident::new_no_span("old_ptr".into()),
+                                    Ident::new_no_span("len".into()),
+                                ],
+                                immediate: None,
+                                metadata: None,
+                            },
+                        ],
+                        ptr_u8,
+                        Some(Ident::new_no_span("hp".into())),
+                    );
+
+                    s.current_block
+                        .append(context)
+                        .branch(merge_block, vec![new_ptr, new_cap]);
+
+                    // dont need realloc block
+                    s.current_block = false_block_begin;
+                    s.current_block
+                        .append(context)
+                        .branch(merge_block, vec![ptr, cap]);
+
+                    s.current_block = merge_block;
+
+                    assert!(merge_block_ptr.get_type(context).unwrap().is_ptr(context));
+                    assert!(merge_block_cap
+                        .get_type(context)
+                        .unwrap()
+                        .is_uint64(context));
+
+                    (merge_block_ptr, merge_block_cap)
+                }
+
+                fn to_constant(
+                    _s: &mut FnCompiler<'_>,
+                    context: &mut Context,
+                    needed_size: u64,
+                ) -> Value {
+                    let needed_size = Constant::new_uint(context, 64, needed_size);
+                    Value::new_constant(context, needed_size)
+                }
+
+                // Grow the buffer if needed
+                let (ptr, cap) = match &*item_type {
+                    TypeInfo::Boolean => {
+                        let needed_size = to_constant(self, context, 1);
+                        grow_if_needed(self, context, ptr, cap, len, needed_size)
+                    }
+                    TypeInfo::UnsignedInteger(IntegerBits::Eight) => {
+                        let needed_size = to_constant(self, context, 1);
+                        grow_if_needed(self, context, ptr, cap, len, needed_size)
+                    }
+                    TypeInfo::UnsignedInteger(IntegerBits::Sixteen) => {
+                        let needed_size = to_constant(self, context, 2);
+                        grow_if_needed(self, context, ptr, cap, len, needed_size)
+                    }
+                    TypeInfo::UnsignedInteger(IntegerBits::ThirtyTwo) => {
+                        let needed_size = to_constant(self, context, 4);
+                        grow_if_needed(self, context, ptr, cap, len, needed_size)
+                    }
+                    TypeInfo::UnsignedInteger(IntegerBits::SixtyFour) => {
+                        let needed_size = to_constant(self, context, 8);
+                        grow_if_needed(self, context, ptr, cap, len, needed_size)
+                    }
+                    TypeInfo::UnsignedInteger(IntegerBits::V256) | TypeInfo::B256 => {
+                        let needed_size = to_constant(self, context, 32);
+                        grow_if_needed(self, context, ptr, cap, len, needed_size)
+                    }
+                    TypeInfo::StringArray(string_len) => {
+                        let needed_size = to_constant(self, context, string_len.val() as u64);
+                        grow_if_needed(self, context, ptr, cap, len, needed_size)
+                    }
+                    TypeInfo::StringSlice | TypeInfo::RawUntypedSlice => {
+                        let uint64 = Type::get_uint64(context);
+                        let u64_u64_type = Type::new_struct(context, vec![uint64, uint64]);
+
+                        // convert "item" to { u64, u64 }
+                        let item = self.current_block.append(context).asm_block(
+                            vec![AsmArg {
+                                name: Ident::new_no_span("item".into()),
+                                initializer: Some(item),
+                            }],
+                            vec![],
+                            u64_u64_type,
+                            Some(Ident::new_no_span("item".into())),
+                        );
+
+                        // save item to local _anon
+                        let name = self.lexical_map.insert_anon();
+                        let item_local = self
+                            .function
+                            .new_local_var(context, name, u64_u64_type, None, false)
+                            .map_err(|ir_error| {
+                                CompileError::InternalOwned(ir_error.to_string(), Span::dummy())
+                            })?;
+                        let ptr_to_local_item =
+                            self.current_block.append(context).get_local(item_local);
+                        self.current_block
+                            .append(context)
+                            .store(ptr_to_local_item, item);
+
+                        // _anon.1 = len
+                        let needed_size = self.current_block.append(context).get_elem_ptr_with_idx(
+                            ptr_to_local_item,
+                            uint64,
+                            1,
+                        );
+                        let needed_size = self.current_block.append(context).load(needed_size);
+                        let eight = to_constant(self, context, 8);
+                        let needed_size = self.current_block.append(context).binary_op(
+                            BinaryOpKind::Add,
+                            needed_size,
+                            eight,
+                        );
+
+                        grow_if_needed(self, context, ptr, cap, len, needed_size)
+                    }
+                    _ => return Err(CompileError::EncodingUnsupportedType { span: item_span }),
+                };
+
+                // Append the value into the buffer
                 let new_len = match &*item_type {
                     TypeInfo::Boolean => {
                         assert!(item.get_type(context).unwrap().is_bool(context));
diff --git a/sway-core/src/language/ty/declaration/function.rs b/sway-core/src/language/ty/declaration/function.rs
index f2ff28b6331..c28d862846f 100644
--- a/sway-core/src/language/ty/declaration/function.rs
+++ b/sway-core/src/language/ty/declaration/function.rs
@@ -565,9 +565,15 @@ impl TyFunctionSig {
     }
 
     pub fn is_concrete(&self, engines: &Engines) -> bool {
-        self.return_type.is_concrete(engines)
-            && self.parameters.iter().all(|p| p.is_concrete(engines))
-            && self.type_parameters.iter().all(|p| p.is_concrete(engines))
+        self.return_type.is_concrete(engines, IncludeNumeric::No)
+            && self
+                .parameters
+                .iter()
+                .all(|p| p.is_concrete(engines, IncludeNumeric::No))
+            && self
+                .type_parameters
+                .iter()
+                .all(|p| p.is_concrete(engines, IncludeNumeric::No))
     }
 
     /// Returns a String representing the function.
diff --git a/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs b/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs
index 0a2ffbcc99f..9c324cf1289 100644
--- a/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs
+++ b/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs
@@ -247,21 +247,25 @@ fn type_check_encode_append(
     };
 
     // only supported types
-    match &*engines.te().get(item_type) {
-        TypeInfo::Boolean
-        | TypeInfo::UnsignedInteger(IntegerBits::Eight)
-        | TypeInfo::UnsignedInteger(IntegerBits::Sixteen)
-        | TypeInfo::UnsignedInteger(IntegerBits::ThirtyTwo)
-        | TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)
-        | TypeInfo::UnsignedInteger(IntegerBits::V256)
-        | TypeInfo::B256
-        | TypeInfo::StringArray(_)
-        | TypeInfo::StringSlice
-        | TypeInfo::RawUntypedSlice => {}
-        _ => {
-            return Err(handler.emit_err(CompileError::EncodingUnsupportedType { span: item_span }))
-        }
-    };
+    if item_type.is_concrete(engines, IncludeNumeric::Yes) {
+        match &*engines.te().get(item_type) {
+            TypeInfo::Boolean
+            | TypeInfo::UnsignedInteger(IntegerBits::Eight)
+            | TypeInfo::UnsignedInteger(IntegerBits::Sixteen)
+            | TypeInfo::UnsignedInteger(IntegerBits::ThirtyTwo)
+            | TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)
+            | TypeInfo::UnsignedInteger(IntegerBits::V256)
+            | TypeInfo::B256
+            | TypeInfo::StringArray(_)
+            | TypeInfo::StringSlice
+            | TypeInfo::RawUntypedSlice => {}
+            _ => {
+                return Err(
+                    handler.emit_err(CompileError::EncodingUnsupportedType { span: item_span })
+                )
+            }
+        };
+    }
 
     let kind = ty::TyIntrinsicFunctionKind {
         kind,
diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs
index f5cfc5c1ff3..7be712a0c00 100644
--- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs
+++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs
@@ -46,11 +46,25 @@ pub(crate) fn type_check_method_application(
             .by_ref()
             .with_help_text("")
             .with_type_annotation(type_engine.insert(engines, TypeInfo::Unknown, None));
+
         // Ignore errors in method parameters
         // On the second pass we will throw the errors if they persist.
         let arg_handler = Handler::default();
         let arg_opt = ty::TyExpression::type_check(&arg_handler, ctx, arg).ok();
+
+        // Check this type needs a second pass
         let has_errors = arg_handler.has_errors();
+        let is_not_concrete = arg_opt
+            .as_ref()
+            .map(|x| {
+                x.return_type
+                    .extract_inner_types(engines, IncludeSelf::Yes)
+                    .iter()
+                    .any(|x| !x.is_concrete(engines, IncludeNumeric::Yes))
+            })
+            .unwrap_or_default();
+        let needs_second_pass = has_errors || is_not_concrete;
+
         if index == 0 {
             // We want to emit errors in the self parameter and ignore TraitConstraintNotSatisfied with Placeholder
             // which may be recoverable on the second pass.
@@ -66,7 +80,8 @@ pub(crate) fn type_check_method_application(
             });
             handler.append(arg_handler);
         }
-        args_opt_buf.push_back((arg_opt, has_errors));
+
+        args_opt_buf.push_back((arg_opt, needs_second_pass));
     }
 
     // resolve the method name to a typed function declaration and type_check
@@ -115,6 +130,7 @@ pub(crate) fn type_check_method_application(
             } else {
                 index
             };
+
             let ctx = if let Some(param) = method.parameters.get(param_index) {
                 // We now try to type check it again, this time with the type annotation.
                 ctx.by_ref()
@@ -127,6 +143,7 @@ pub(crate) fn type_check_method_application(
                     .with_help_text("")
                     .with_type_annotation(type_engine.insert(engines, TypeInfo::Unknown, None))
             };
+
             args_buf.push_back(
                 ty::TyExpression::type_check(handler, ctx, arg)
                     .unwrap_or_else(|err| ty::TyExpression::error(err, span.clone(), engines)),
diff --git a/sway-core/src/type_system/id.rs b/sway-core/src/type_system/id.rs
index 9403fcb03ef..9410fd2d6ac 100644
--- a/sway-core/src/type_system/id.rs
+++ b/sway-core/src/type_system/id.rs
@@ -27,6 +27,11 @@ pub enum IncludeSelf {
     No,
 }
 
+pub enum IncludeNumeric {
+    Yes,
+    No,
+}
+
 /// A identifier to uniquely refer to our type terms
 #[derive(PartialEq, Eq, Hash, Clone, Copy, Ord, PartialOrd, Debug)]
 pub struct TypeId(usize);
@@ -456,17 +461,26 @@ impl TypeId {
         }))
     }
 
-    pub(crate) fn is_concrete(&self, engines: &Engines) -> bool {
+    pub(crate) fn is_concrete(&self, engines: &Engines, include_numeric: IncludeNumeric) -> bool {
         let nested_types = (*self).extract_nested_types(engines);
-        !nested_types.into_iter().any(|x| {
-            matches!(
+        !nested_types.into_iter().any(|x| match include_numeric {
+            IncludeNumeric::Yes => matches!(
+                x,
+                TypeInfo::UnknownGeneric { .. }
+                    | TypeInfo::Custom { .. }
+                    | TypeInfo::Placeholder(..)
+                    | TypeInfo::TraitType { .. }
+                    | TypeInfo::TypeParam(..)
+                    | TypeInfo::Numeric
+            ),
+            IncludeNumeric::No => matches!(
                 x,
                 TypeInfo::UnknownGeneric { .. }
                     | TypeInfo::Custom { .. }
                     | TypeInfo::Placeholder(..)
                     | TypeInfo::TraitType { .. }
                     | TypeInfo::TypeParam(..)
-            )
+            ),
         })
     }
 
diff --git a/sway-core/src/type_system/priv_prelude.rs b/sway-core/src/type_system/priv_prelude.rs
index bb40d738d00..b28ac22152d 100644
--- a/sway-core/src/type_system/priv_prelude.rs
+++ b/sway-core/src/type_system/priv_prelude.rs
@@ -16,6 +16,6 @@ pub use super::{
         type_parameter::TypeParameter,
     },
     engine::TypeEngine,
-    id::{IncludeSelf, TypeId},
+    id::{IncludeNumeric, IncludeSelf, TypeId},
     info::{AbiEncodeSizeHint, AbiName, TypeInfo, TypeSourceInfo},
 };
diff --git a/sway-lib-core/src/codec.sw b/sway-lib-core/src/codec.sw
index cc43cdbf2eb..9ab99efc188 100644
--- a/sway-lib-core/src/codec.sw
+++ b/sway-lib-core/src/codec.sw
@@ -12,6 +12,17 @@ impl Buffer {
             buffer: __encode_buffer_empty(),
         }
     }
+
+    fn with_capacity(cap: u64) -> Self {
+        let ptr = asm(cap: cap) {
+            aloc cap;
+            hp: raw_ptr
+        };
+
+        Buffer {
+            buffer: (ptr, cap, 0),
+        }
+    }
 }
 
 impl AsRawSlice for Buffer {
@@ -4984,6 +4995,85 @@ where
 // END TUPLES_DECODE
 use ::ops::*;
 
+pub fn contract_call<T, TArgs>(
+    contract_id: b256,
+    method_name: str,
+    args: TArgs,
+    coins: u64,
+    asset_id: b256,
+    gas: u64,
+) -> T
+where
+    T: AbiDecode,
+    TArgs: AbiEncode,
+{
+    let first_parameter = encode(method_name);
+    let second_parameter = encode(args);
+    let params = encode((
+        contract_id,
+        asm(a: first_parameter.ptr()) {
+            a: u64
+        },
+        asm(a: second_parameter.ptr()) {
+            a: u64
+        },
+    ));
+
+    __contract_call(params.ptr(), coins, asset_id, gas);
+    let ptr = asm() {
+        ret: raw_ptr
+    };
+    let len = asm() {
+        retl: u64
+    };
+
+    let mut buffer = BufferReader::from_parts(ptr, len);
+    T::abi_decode(buffer)
+}
+
+pub fn decode_script_data<T>() -> T
+where
+    T: AbiDecode,
+{
+    let mut buffer = BufferReader::from_script_data();
+    T::abi_decode(buffer)
+}
+
+pub fn decode_predicate_data<T>() -> T
+where
+    T: AbiDecode,
+{
+    let mut buffer = BufferReader::from_predicate_data();
+    T::abi_decode(buffer)
+}
+
+pub fn decode_predicate_data_by_index<T>(index: u64) -> T
+where
+    T: AbiDecode,
+{
+    let mut buffer = BufferReader::from_predicate_data_by_index(index);
+    T::abi_decode(buffer)
+}
+
+pub fn decode_first_param<T>() -> T
+where
+    T: AbiDecode,
+{
+    let mut buffer = BufferReader::from_first_parameter();
+    T::abi_decode(buffer)
+}
+
+pub fn decode_second_param<T>() -> T
+where
+    T: AbiDecode,
+{
+    let mut buffer = BufferReader::from_second_parameter();
+    T::abi_decode(buffer)
+}
+
+// Tests
+
+
 fn assert_encoding<T, SLICE>(value: T, expected: SLICE)
 where
     T: AbiEncode,
@@ -5062,15 +5152,99 @@ fn to_slice<T>(array: T) -> raw_slice {
     raw_slice::from_parts::<u8>(__addr_of(array), len)
 }
 
-fn assert_eq<T>(a: T, b: T)
+fn assert_eq<T>(a: T, b: T, revert_code: u64)
 where
     T: Eq,
 {
     if a != b {
-        __revert(0)
+        __revert(revert_code)
     }
 }
 
+fn assert_neq<T>(a: T, b: T, revert_code: u64)
+where
+    T: Eq,
+{
+    if a == b {
+        __revert(revert_code)
+    }
+}
+
+fn assert_no_write_after_buffer<T>(value_to_append: T, size_of_t: u64)
+where
+    T: AbiEncode,
+{
+    // This red zone should not be overwritten
+    let red_zone1 = asm(size: 1024) {
+        aloc size;
+        hp: raw_ptr
+    };
+    red_zone1.write(0xFFFFFFFFFFFFFFFF);
+
+    // Create encoding buffer with capacity for one item
+    let mut buffer = Buffer::with_capacity(size_of_t);
+    let ptr1 = buffer.buffer.0;
+
+    // Append one item
+    let buffer = value_to_append.abi_encode(buffer);
+    assert_eq(ptr1, buffer.buffer.0, 1); // no buffer grow is expected
+    assert_eq(buffer.buffer.1, size_of_t, 2); // capacity must be still be one item
+    assert_eq(buffer.buffer.2, size_of_t, 3); // buffer has one item
+
+    // This red zone should not be overwritten
+    let red_zone2 = asm(size: 1024) {
+        aloc size;
+        hp: raw_ptr
+    };
+    red_zone2.write(0xFFFFFFFFFFFFFFFF);
+
+    // Append another item
+    let buffer = value_to_append.abi_encode(buffer);
+    assert_neq(ptr1, buffer.buffer.0, 4); // must have allocated new buffer
+    assert_eq(buffer.buffer.1, size_of_t * 2, 5); // capacity for two items
+    assert_eq(buffer.buffer.2, size_of_t * 2, 6); // buffer has two items
+
+    // Check that red zones were not overwritten
+    assert_eq(red_zone1.read::<u64>(), 0xFFFFFFFFFFFFFFFF, 7);
+    assert_eq(red_zone2.read::<u64>(), 0xFFFFFFFFFFFFFFFF, 8);
+}
+
+#[test]
+fn ok_encoding_should_not_write_outside_buffer() {
+    assert_no_write_after_buffer::<bool>(true, 1);
+
+    // numbers
+    assert_no_write_after_buffer::<u8>(1, 1);
+    assert_no_write_after_buffer::<u16>(1, 2);
+    assert_no_write_after_buffer::<u32>(1, 4);
+    assert_no_write_after_buffer::<u64>(1, 8);
+    assert_no_write_after_buffer::<u256>(
+        0x0000000000000000000000000000000000000000000000000000000000000001u256,
+        32,
+    );
+    assert_no_write_after_buffer::<b256>(
+        0x0000000000000000000000000000000000000000000000000000000000000001,
+        32,
+    );
+
+    // arrays
+    assert_no_write_after_buffer::<[u8; 1]>([1], 1);
+    assert_no_write_after_buffer::<[u8; 2]>([1, 1], 2);
+    assert_no_write_after_buffer::<[u8; 3]>([1, 1, 1], 3);
+    assert_no_write_after_buffer::<[u8; 4]>([1, 1, 1, 1], 4);
+    assert_no_write_after_buffer::<[u8; 5]>([1, 1, 1, 1, 1], 5);
+
+    // string arrays
+    assert_no_write_after_buffer::<str[1]>(__to_str_array("h"), 1);
+    assert_no_write_after_buffer::<str[2]>(__to_str_array("he"), 2);
+    assert_no_write_after_buffer::<str[11]>(__to_str_array("hello world"), 11);
+
+    // string slices
+    assert_no_write_after_buffer::<str>("h", 9);
+    assert_no_write_after_buffer::<str>("he", 10);
+    assert_no_write_after_buffer::<str>("hello world", 19);
+}
+
 #[test]
 fn ok_abi_encoding() {
     // bool
@@ -5177,85 +5351,9 @@ fn ok_abi_encoding() {
     assert_encoding([255u8; 5], [255u8; 5]);
 
     let array = abi_decode::<[u8; 1]>(to_slice([255u8]));
-    assert_eq(array[0], 255u8);
+    assert_eq(array[0], 255u8, 0);
 
     let array = abi_decode::<[u8; 2]>(to_slice([255u8, 254u8]));
-    assert_eq(array[0], 255u8);
-    assert_eq(array[1], 254u8);
-}
-
-pub fn contract_call<T, TArgs>(
-    contract_id: b256,
-    method_name: str,
-    args: TArgs,
-    coins: u64,
-    asset_id: b256,
-    gas: u64,
-) -> T
-where
-    T: AbiDecode,
-    TArgs: AbiEncode,
-{
-    let first_parameter = encode(method_name);
-    let second_parameter = encode(args);
-    let params = encode((
-        contract_id,
-        asm(a: first_parameter.ptr()) {
-            a: u64
-        },
-        asm(a: second_parameter.ptr()) {
-            a: u64
-        },
-    ));
-
-    __contract_call(params.ptr(), coins, asset_id, gas);
-    let ptr = asm() {
-        ret: raw_ptr
-    };
-    let len = asm() {
-        retl: u64
-    };
-
-    let mut buffer = BufferReader::from_parts(ptr, len);
-    T::abi_decode(buffer)
-}
-
-pub fn decode_script_data<T>() -> T
-where
-    T: AbiDecode,
-{
-    let mut buffer = BufferReader::from_script_data();
-    T::abi_decode(buffer)
-}
-
-pub fn decode_predicate_data<T>() -> T
-where
-    T: AbiDecode,
-{
-    let mut buffer = BufferReader::from_predicate_data();
-    T::abi_decode(buffer)
-}
-
-pub fn decode_predicate_data_by_index<T>(index: u64) -> T
-where
-    T: AbiDecode,
-{
-    let mut buffer = BufferReader::from_predicate_data_by_index(index);
-    T::abi_decode(buffer)
-}
-
-pub fn decode_first_param<T>() -> T
-where
-    T: AbiDecode,
-{
-    let mut buffer = BufferReader::from_first_parameter();
-    T::abi_decode(buffer)
-}
-
-pub fn decode_second_param<T>() -> T
-where
-    T: AbiDecode,
-{
-    let mut buffer = BufferReader::from_second_parameter();
-    T::abi_decode(buffer)
+    assert_eq(array[0], 255u8, 0);
+    assert_eq(array[1], 254u8, 0);
 }
diff --git a/sway-lib-std/src/alloc.sw b/sway-lib-std/src/alloc.sw
index 9841fe5e1e1..bd3dd7cc095 100644
--- a/sway-lib-std/src/alloc.sw
+++ b/sway-lib-std/src/alloc.sw
@@ -112,10 +112,9 @@ pub fn realloc<T>(ptr: raw_ptr, count: u64, new_count: u64) -> raw_ptr {
 /// }
 /// ```
 pub fn alloc_bytes(count: u64) -> raw_ptr {
-    asm(size: count, ptr) {
+    asm(size: count) {
         aloc size;
-        move ptr hp;
-        ptr: raw_ptr
+        hp: raw_ptr
     }
 }
 
diff --git a/sway-lib-std/src/bytes.sw b/sway-lib-std/src/bytes.sw
index 0b3b99d9bf7..1887b46e41c 100644
--- a/sway-lib-std/src/bytes.sw
+++ b/sway-lib-std/src/bytes.sw
@@ -74,14 +74,16 @@ impl From<raw_slice> for RawBytes {
     /// assert(raw_bytes.capacity == 3);
     /// ```
     fn from(slice: raw_slice) -> Self {
-        Self {
-            ptr: slice.ptr(),
-            cap: slice.number_of_bytes(),
+        let cap = slice.number_of_bytes();
+        let ptr = alloc_bytes(cap);
+        if cap > 0 {
+            slice.ptr().copy_to::<u8>(ptr, cap);
         }
+        Self { ptr, cap }
     }
 }
 
-/// A type used to represent raw bytes.
+/// A type used to represent raw bytes. It has ownership over its buffer.
 pub struct Bytes {
     /// A barebones struct for the bytes.
     buf: RawBytes,
@@ -723,11 +725,11 @@ impl Bytes {
 
 impl core::ops::Eq for Bytes {
     fn eq(self, other: Self) -> bool {
-        if self.len != other.len() {
+        if self.len != other.len {
             return false;
         }
 
-        asm(result, r2: self.buf.ptr(), r3: other.ptr(), r4: self.len) {
+        asm(result, r2: self.buf.ptr, r3: other.buf.ptr, r4: self.len) {
             meq result r2 r3 r4;
             result: bool
         }
@@ -737,7 +739,7 @@ impl core::ops::Eq for Bytes {
 impl AsRawSlice for Bytes {
     /// Returns a raw slice of all of the elements in the type.
     fn as_raw_slice(self) -> raw_slice {
-        asm(ptr: (self.buf.ptr(), self.len)) {
+        asm(ptr: (self.buf.ptr, self.len)) {
             ptr: raw_slice
         }
     }
@@ -750,7 +752,7 @@ impl From<b256> for Bytes {
         let mut bytes = Self::with_capacity(32);
         bytes.len = 32;
         // Copy bytes from contract_id into the buffer of the target bytes
-        __addr_of(b).copy_bytes_to(bytes.buf.ptr(), 32);
+        __addr_of(b).copy_bytes_to(bytes.buf.ptr, 32);
 
         bytes
     }
@@ -826,9 +828,7 @@ impl From<Bytes> for raw_slice {
     /// assert(slice.number_of_bytes() == 3);
     /// ```
     fn from(bytes: Bytes) -> raw_slice {
-        asm(ptr: (bytes.buf.ptr(), bytes.len)) {
-            ptr: raw_slice
-        }
+        bytes.as_raw_slice()
     }
 }
 
@@ -906,38 +906,46 @@ impl From<Bytes> for Vec<u8> {
 impl Clone for Bytes {
     fn clone(self) -> Self {
         let len = self.len();
-        let mut c = Self::with_capacity(len);
-        c.len = len;
-        self.ptr().copy_bytes_to(c.ptr(), len);
-        c
+        let buf = RawBytes::with_capacity(len);
+        if len > 0 {
+            self.ptr().copy_bytes_to(buf.ptr(), len);
+        }
+        Bytes { buf, len }
     }
 }
 
 impl AbiEncode for Bytes {
     fn abi_encode(self, buffer: Buffer) -> Buffer {
-        let mut buffer = self.len.abi_encode(buffer);
-
-        let mut i = 0;
-        while i < self.len {
-            let item = self.get(i).unwrap();
-            buffer = item.abi_encode(buffer);
-            i += 1;
-        }
-
-        buffer
+        self.as_raw_slice().abi_encode(buffer)
     }
 }
 
 impl AbiDecode for Bytes {
     fn abi_decode(ref mut buffer: BufferReader) -> Bytes {
-        let len = u64::abi_decode(buffer);
-        let data = buffer.read_bytes(len);
-        Bytes {
-            buf: RawBytes {
-                ptr: data.ptr(),
-                cap: len,
-            },
-            len,
-        }
+        raw_slice::abi_decode(buffer).into()
     }
 }
+
+#[test]
+fn ok_bytes_buffer_ownership() {
+    let mut original_array = [1u8, 2u8, 3u8, 4u8];
+    let slice = raw_slice::from_parts::<u8>(__addr_of(original_array), 4);
+
+    // Check Bytes duplicates the original slice
+    let mut bytes = Bytes::from(slice);
+    bytes.set(0, 5);
+    assert(original_array[0] == 1);
+
+    // At this point, slice equals [5, 2, 3, 4]
+    let encoded_slice = encode(bytes);
+
+    // `Bytes` should duplicate the underlying buffer,
+    // so when we write to it, it should not change
+    // `encoded_slice` 
+    let mut bytes = abi_decode::<Bytes>(encoded_slice);
+    bytes.set(0, 6);
+    assert(bytes.get(0) == Some(6));
+
+    let mut bytes = abi_decode::<Bytes>(encoded_slice);
+    assert(bytes.get(0) == Some(5));
+}
diff --git a/sway-lib-std/src/string.sw b/sway-lib-std/src/string.sw
index 97b6cf76df3..abe9673dbdc 100644
--- a/sway-lib-std/src/string.sw
+++ b/sway-lib-std/src/string.sw
@@ -7,7 +7,7 @@ use ::convert::*;
 use ::hash::{Hash, Hasher};
 use ::option::Option;
 
-/// A UTF-8 encoded growable string.
+/// A UTF-8 encoded growable string. It has ownership over its buffer.
 ///
 /// # Additional Information
 ///
@@ -40,7 +40,7 @@ impl String {
     /// }
     /// ```
     pub fn as_bytes(self) -> Bytes {
-        self.bytes
+        self.bytes.clone()
     }
 
     /// Gets the amount of memory on the heap allocated to the `String`.
@@ -113,7 +113,9 @@ impl String {
     /// }
     /// ```
     pub fn from_ascii(bytes: Bytes) -> Self {
-        Self { bytes }
+        Self {
+            bytes: bytes.clone(),
+        }
     }
 
     /// Converts a string slice containing ASCII encoded bytes to a `String`
@@ -236,7 +238,9 @@ impl String {
 
 impl From<Bytes> for String {
     fn from(b: Bytes) -> Self {
-        Self { bytes: b }
+        Self {
+            bytes: b.clone(),
+        }
     }
 }
 
@@ -308,7 +312,7 @@ impl From<String> for raw_slice {
     /// }
     /// ```
     fn from(s: String) -> raw_slice {
-        raw_slice::from(s.as_bytes())
+        s.bytes.as_raw_slice()
     }
 }
 
@@ -326,29 +330,14 @@ impl Hash for String {
 
 impl AbiEncode for String {
     fn abi_encode(self, buffer: Buffer) -> Buffer {
-        // Encode the length
-        let mut buffer = self.bytes.len().abi_encode(buffer);
-
-        // Encode each byte of the string
-        let mut i = 0;
-        while i < self.bytes.len() {
-            let item = self.bytes.get(i).unwrap();
-            buffer = item.abi_encode(buffer);
-            i += 1;
-        }
-
-        buffer
+        self.bytes.abi_encode(buffer)
     }
 }
 
 impl AbiDecode for String {
     fn abi_decode(ref mut buffer: BufferReader) -> Self {
-        // Get length and string data
-        let len = u64::abi_decode(buffer);
-        let data = buffer.read_bytes(len);
-        // Create string from the ptr and len as parts of a raw_slice
         String {
-            bytes: Bytes::from(raw_slice::from_parts::<u8>(data.ptr(), len)),
+            bytes: Bytes::abi_decode(buffer),
         }
     }
 }
diff --git a/sway-lib-std/src/vec.sw b/sway-lib-std/src/vec.sw
index 9c585f45185..5b7830b848c 100644
--- a/sway-lib-std/src/vec.sw
+++ b/sway-lib-std/src/vec.sw
@@ -131,14 +131,16 @@ impl<T> RawVec<T> {
 
 impl<T> From<raw_slice> for RawVec<T> {
     fn from(slice: raw_slice) -> Self {
-        Self {
-            ptr: slice.ptr(),
-            cap: slice.len::<T>(),
+        let cap = slice.len::<T>();
+        let ptr = alloc::<T>(cap);
+        if cap > 0 {
+            slice.ptr().copy_to::<T>(ptr, cap);
         }
+        Self { ptr, cap }
     }
 }
 
-/// A contiguous growable array type, written as `Vec<T>`, short for 'vector'.
+/// A contiguous growable array type, written as `Vec<T>`, short for 'vector'. It has ownership over its buffer.
 pub struct Vec<T> {
     buf: RawVec<T>,
     len: u64,
@@ -702,3 +704,27 @@ impl<T> Iterator for VecIter<T> {
         self.values.get(self.index - 1)
     }
 }
+
+#[test]
+fn ok_vec_buffer_ownership() {
+    let mut original_array = [1u8, 2u8, 3u8, 4u8];
+    let slice = raw_slice::from_parts::<u8>(__addr_of(original_array), 4);
+
+    // Check Vec duplicates the original slice
+    let mut bytes = Vec::<u8>::from(slice);
+    bytes.set(0, 5);
+    assert(original_array[0] == 1);
+
+    // At this point, slice equals [5, 2, 3, 4]
+    let encoded_slice = encode(bytes);
+
+    // `Vec<u8>` should duplicate the underlying buffer,
+    // so when we write to it, it should not change
+    // `encoded_slice` 
+    let mut bytes = abi_decode::<Vec<u8>>(encoded_slice);
+    bytes.set(0, 6);
+    assert(bytes.get(0) == Some(6));
+
+    let mut bytes = abi_decode::<Vec<u8>>(encoded_slice);
+    assert(bytes.get(0) == Some(5));
+}
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_consts/json_abi_oracle_new_encoding.json b/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_consts/json_abi_oracle_new_encoding.json
index b76fb86d956..3f7bf138e5c 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_consts/json_abi_oracle_new_encoding.json
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_consts/json_abi_oracle_new_encoding.json
@@ -7,7 +7,7 @@
         "typeArguments": null
       },
       "name": "BOOL",
-      "offset": 6944
+      "offset": 6968
     },
     {
       "configurableType": {
@@ -16,7 +16,7 @@
         "typeArguments": null
       },
       "name": "U8",
-      "offset": 7088
+      "offset": 7112
     },
     {
       "configurableType": {
@@ -25,7 +25,7 @@
         "typeArguments": null
       },
       "name": "ANOTHER_U8",
-      "offset": 6872
+      "offset": 6896
     },
     {
       "configurableType": {
@@ -34,7 +34,7 @@
         "typeArguments": null
       },
       "name": "U16",
-      "offset": 7032
+      "offset": 7056
     },
     {
       "configurableType": {
@@ -43,7 +43,7 @@
         "typeArguments": null
       },
       "name": "U32",
-      "offset": 7072
+      "offset": 7096
     },
     {
       "configurableType": {
@@ -52,7 +52,7 @@
         "typeArguments": null
       },
       "name": "U64",
-      "offset": 7080
+      "offset": 7104
     },
     {
       "configurableType": {
@@ -61,7 +61,7 @@
         "typeArguments": null
       },
       "name": "U256",
-      "offset": 7040
+      "offset": 7064
     },
     {
       "configurableType": {
@@ -70,7 +70,7 @@
         "typeArguments": null
       },
       "name": "B256",
-      "offset": 6912
+      "offset": 6936
     },
     {
       "configurableType": {
@@ -79,7 +79,7 @@
         "typeArguments": []
       },
       "name": "CONFIGURABLE_STRUCT",
-      "offset": 6984
+      "offset": 7008
     },
     {
       "configurableType": {
@@ -88,7 +88,7 @@
         "typeArguments": []
       },
       "name": "CONFIGURABLE_ENUM_A",
-      "offset": 6952
+      "offset": 6976
     },
     {
       "configurableType": {
@@ -97,7 +97,7 @@
         "typeArguments": []
       },
       "name": "CONFIGURABLE_ENUM_B",
-      "offset": 6968
+      "offset": 6992
     },
     {
       "configurableType": {
@@ -106,7 +106,7 @@
         "typeArguments": null
       },
       "name": "ARRAY_BOOL",
-      "offset": 6880
+      "offset": 6904
     },
     {
       "configurableType": {
@@ -115,7 +115,7 @@
         "typeArguments": null
       },
       "name": "ARRAY_U64",
-      "offset": 6888
+      "offset": 6912
     },
     {
       "configurableType": {
@@ -124,7 +124,7 @@
         "typeArguments": null
       },
       "name": "TUPLE_BOOL_U64",
-      "offset": 7016
+      "offset": 7040
     },
     {
       "configurableType": {
@@ -133,7 +133,7 @@
         "typeArguments": null
       },
       "name": "STR_4",
-      "offset": 7008
+      "offset": 7032
     },
     {
       "configurableType": {
@@ -142,7 +142,7 @@
         "typeArguments": null
       },
       "name": "NOT_USED",
-      "offset": 7000
+      "offset": 7024
     }
   ],
   "encoding": "1",
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/slice/slice_contract/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/slice/slice_contract/src/main.sw
index c86ce974d88..070cff38a82 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/language/slice/slice_contract/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/slice/slice_contract/src/main.sw
@@ -12,7 +12,8 @@ impl MyContract for Contract {
 
 #[test]
 fn test_success() {
-    let caller = abi(MyContract, CONTRACT_ID);
+    let contract_id = 0x3a9a75a3dc04f160ec6e286144eeffb6dd73fc0b4235b1793aa656be02e69d9b; // AUTO-CONTRACT-ID .
+    let caller = abi(MyContract, contract_id);
 
     let data = 1u64;
     let slice = raw_slice::from_parts::<u64>(__addr_of(&data), 1);
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/string_slice/string_slice_contract/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/string_slice/string_slice_contract/src/main.sw
index 0a57dc67e6e..5e907a202b1 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/language/string_slice/string_slice_contract/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/string_slice/string_slice_contract/src/main.sw
@@ -12,7 +12,8 @@ impl MyContract for Contract {
 
 #[test]
 fn test_success() {
-    let caller = abi(MyContract, CONTRACT_ID);
+    let contract_id = 0xeea596d8fc4e55fb622fd36131eff0401ccfd9f2a211f7ce2d93f816ec0cb23f; // AUTO-CONTRACT-ID .
+    let caller = abi(MyContract, contract_id); 
     let result = caller.test_function("a");
     assert(result == "a")
 }
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/u256_abi/json_abi_oracle_new_encoding.json b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/u256_abi/json_abi_oracle_new_encoding.json
index 58d148218d5..95064cff5f6 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/u256_abi/json_abi_oracle_new_encoding.json
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256/u256_abi/json_abi_oracle_new_encoding.json
@@ -7,7 +7,7 @@
         "typeArguments": null
       },
       "name": "SOME_U256",
-      "offset": 672
+      "offset": 704
     }
   ],
   "encoding": "1",
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/src/main.sw
index 09d9a08f021..e81345968e4 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/array_of_structs_caller/src/main.sw
@@ -6,7 +6,7 @@ use std::hash::*;
 #[cfg(experimental_new_encoding = false)]
 const CONTRACT_ID = 0x14ed3cd06c2947248f69d54bfa681fe40d26267be84df7e19e253622b7921bbe;
 #[cfg(experimental_new_encoding = true)]
-const CONTRACT_ID = 0xfef18ef24b6cbfd66238fecc3c2704976fdf3177442712a3402b2ab666f12039;
+const CONTRACT_ID = 0xb6a63cfbfdef36702cbec327c15629ec88c1c4acc5a3a350b127de8aebc49293; // AUTO-CONTRACT-ID ../../test_contracts/array_of_structs_contract --release
 
 fn main() -> u64 {
     let addr = abi(TestContract, CONTRACT_ID);
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/asset_ops_test/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/asset_ops_test/src/main.sw
index 51a2c5dfbb8..c23eb640723 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/asset_ops_test/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/asset_ops_test/src/main.sw
@@ -9,12 +9,12 @@ use test_fuel_coin_abi::*;
 #[cfg(experimental_new_encoding = false)]
 const FUEL_COIN_CONTRACT_ID = 0xec2277ebe007ade87e3d797c3b1e070dcd542d5ef8f038b471f262ef9cebc87c;
 #[cfg(experimental_new_encoding = true)]
-const FUEL_COIN_CONTRACT_ID = 0x1a88d0982d216958d18378b6784614b75868a542dc05f8cc85cf3da44268c76c;
+const FUEL_COIN_CONTRACT_ID = 0x1a88d0982d216958d18378b6784614b75868a542dc05f8cc85cf3da44268c76c; // AUTO-CONTRACT-ID ../../test_contracts/test_fuel_coin_contract --release
 
 #[cfg(experimental_new_encoding = false)]
 const BALANCE_CONTRACT_ID = 0xf6cd545152ac83225e8e7df2efb5c6fa6e37bc9b9e977b5ea8103d28668925df;
 #[cfg(experimental_new_encoding = true)]
-const BALANCE_CONTRACT_ID = 0x04594851a2bd620dffc360f3976d747598b9184218dc55ff3e839f417ca345ac;
+const BALANCE_CONTRACT_ID = 0x0d5fb0c109082f5784f6cd5979d9d25cab2d7307baf4a7661dea7d285c970e9f; // AUTO-CONTRACT-ID ../../test_contracts/balance_test_contract --release
 
 fn main() -> bool {
     let default_gas = 1_000_000_000_000;
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/src/main.sw
index 34bec41ab32..db944a5f3f0 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/bal_opcode/src/main.sw
@@ -5,7 +5,7 @@ use balance_test_abi::BalanceTest;
 #[cfg(experimental_new_encoding = false)]
 const CONTRACT_ID = 0xf6cd545152ac83225e8e7df2efb5c6fa6e37bc9b9e977b5ea8103d28668925df;
 #[cfg(experimental_new_encoding = true)]
-const CONTRACT_ID = 0x04594851a2bd620dffc360f3976d747598b9184218dc55ff3e839f417ca345ac;
+const CONTRACT_ID = 0x0d5fb0c109082f5784f6cd5979d9d25cab2d7307baf4a7661dea7d285c970e9f; // AUTO-CONTRACT-ID ../../test_contracts/balance_test_contract --release
 
 fn main() -> bool {
     let balance_test_contract = abi(BalanceTest, CONTRACT_ID);
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/src/main.sw
index ef06da8933a..34b3e375761 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_abi_with_tuples/src/main.sw
@@ -6,7 +6,7 @@ use abi_with_tuples::{MyContract, Location, Person};
 #[cfg(experimental_new_encoding = false)]
 const CONTRACT_ID = 0xfdc14550c8aee742cd556d0ab7f378b7be0d3b1e6e086c097352e94590d4ed02;
 #[cfg(experimental_new_encoding = true)]
-const CONTRACT_ID = 0xfc32e1cb0635642004594eb3503279b3f4aee3d0b0de0e1aa78dcd7de2389239;
+const CONTRACT_ID = 0x5517b7a26c5cbd631796958996ab33708b05282e5e366037efc5ff914682c2d6; // AUTO-CONTRACT-ID ../../test_contracts/abi_with_tuples_contract --release
 
 fn main() -> bool {
     let the_abi = abi(MyContract, CONTRACT_ID);
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw
index 3bb81c8e7e4..42605631ca1 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_basic_storage/src/main.sw
@@ -4,7 +4,7 @@ use basic_storage_abi::{BasicStorage, Quad};
 #[cfg(experimental_new_encoding = false)]
 const CONTRACT_ID = 0x94db39f409a31b9f2ebcadeea44378e419208c20de90f5d8e1e33dc1523754cb;
 #[cfg(experimental_new_encoding = true)]
-const CONTRACT_ID = 0xa638dae2693fab5fc57f3b61af1a4aae594006f2846175b9954769e3fa243a23;
+const CONTRACT_ID = 0xe3e3a00062ed46de91902cda85348b27b371158bb1d5b9a6ccebe7307be59ff4; // AUTO-CONTRACT-ID ../../test_contracts/basic_storage --release
 
 fn main() -> u64 {
     let addr = abi(BasicStorage, CONTRACT_ID);
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_contract_with_type_aliases/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_contract_with_type_aliases/src/main.sw
index cbb435e9b52..08b24d73c5d 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_contract_with_type_aliases/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_contract_with_type_aliases/src/main.sw
@@ -5,7 +5,7 @@ use contract_with_type_aliases_abi::*;
 #[cfg(experimental_new_encoding = false)]
 const CONTRACT_ID = 0x0cbeb6efe3104b460be769bdc4ea101ebf16ccc16f2d7b667ec3e1c7f5ce35b5;
 #[cfg(experimental_new_encoding = true)]
-const CONTRACT_ID = 0x8bc9728375407f59c86f5b8da0660c414c9225a19e978bebe085a4b954ff29d1;
+const CONTRACT_ID = 0x0bd9f9710b0815ce83f1b81614027e3c1ef300ea579b30824b323147dd369ecf; // AUTO-CONTRACT-ID ../../test_contracts/contract_with_type_aliases --release
 
 fn main() {
     let caller = abi(MyContract, CONTRACT_ID);
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw
index 6fc782ec42f..15b7895f1d1 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_increment_contract/src/main.sw
@@ -6,7 +6,7 @@ use dynamic_contract_call::*;
 #[cfg(experimental_new_encoding = false)]
 const CONTRACT_ID = 0xd1b4047af7ef111c023ab71069e01dc2abfde487c0a0ce1268e4f447e6c6e4c2;
 #[cfg(experimental_new_encoding = true)]
-const CONTRACT_ID = 0x4b5acfce4ff139e32b4d5466cb85d30496d0c69593dbf8cf214dedda395ddc08;
+const CONTRACT_ID = 0xf9ff73e9e0ddc3517fd6fe493847b0572db0d8e7c3672c590103112b4a0d4e5a; // AUTO-CONTRACT-ID ../../test_contracts/increment_contract --release
 
 fn main() -> bool {
     let the_abi = abi(Incrementor, CONTRACT_ID);
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw
index 4c0d8e66f0f..85f714468c2 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/call_storage_enum/src/main.sw
@@ -5,7 +5,7 @@ use storage_enum_abi::*;
 #[cfg(experimental_new_encoding = false)]
 const CONTRACT_ID = 0xc601d11767195485a6654d566c67774134668863d8c797a8c69e8778fb1f89e9;
 #[cfg(experimental_new_encoding = true)]
-const CONTRACT_ID = 0xbb67310c9d6f3a1147583a4bf5a28c51299601c5fb09cb370724f2d490ec5c0c;
+const CONTRACT_ID = 0x7bd5d774e220fa89a3c1b38005f921eb3189a47e3a316175545b7413f6901ec4; // AUTO-CONTRACT-ID ../../test_contracts/storage_enum_contract --release
 
 fn main() -> u64 {
     let caller = abi(StorageEnum, CONTRACT_ID);
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/src/main.sw
index 6a054b04052..dc2ca052d0b 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_auth_test/src/main.sw
@@ -5,7 +5,7 @@ use auth_testing_abi::AuthTesting;
 #[cfg(experimental_new_encoding = false)]
 const CONTRACT_ID = 0xc2eec20491b53aab7232cbd27c31d15417b4e9daf0b89c74cc242ef1295f681f;
 #[cfg(experimental_new_encoding = true)]
-const CONTRACT_ID = 0xeb42a6ba3f230441d7ade26f54cfb9f64fe8dd6397cc685fefc7f3d082d4d2ce;
+const CONTRACT_ID = 0xf3b68b9e2ade5b886f4d2bd22bbfd928d418f9532a3a185956c1ca472a04dc0e; // AUTO-CONTRACT-ID ../../test_contracts/auth_testing_contract --release
 
 // should be false in the case of a script
 fn main() -> bool {
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw
index e70c006208e..94b86c30fdc 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/caller_context_test/src/main.sw
@@ -6,7 +6,7 @@ use context_testing_abi::*;
 #[cfg(experimental_new_encoding = false)]
 const CONTRACT_ID = 0x6054c11cda000f5990373a4d61929396165be4dfdd61d5b7bd26da60ab0d8577;
 #[cfg(experimental_new_encoding = true)]
-const CONTRACT_ID = 0x968479b51e9a6c210df98ba289f586331a502a5be2c2073ef65f82bada5695a9;
+const CONTRACT_ID = 0x73061043a4ada05fd79d45d33f4afe5a8e83726beda5310741008aa772512d97; // AUTO-CONTRACT-ID ../../test_contracts/context_testing_contract --release
 
 fn main() -> bool {
     let gas: u64 = u64::max();
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/src/main.sw
index ce6698c04ca..fd353f9c22d 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/nested_struct_args_caller/src/main.sw
@@ -5,7 +5,7 @@ use nested_struct_args_abi::*;
 #[cfg(experimental_new_encoding = false)]
 const CONTRACT_ID = 0xe63d33a1b3a6903808b379f6a41a72fa8a370e8b76626775e7d9d2f9c4c5da40;
 #[cfg(experimental_new_encoding = true)]
-const CONTRACT_ID = 0xbefd6660ae89502652b2ab4e536edf3403208e308a329c06af6017dec242cc37;
+const CONTRACT_ID = 0x35f286cf49aa8ecab05e8f41852cb461145ec6e39205dbd073726922a49803e1; // AUTO-CONTRACT-ID ../../test_contracts/nested_struct_args_contract --release
 
 fn main() -> bool {
     let caller = abi(NestedStructArgs, CONTRACT_ID);
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw
index 786e17542cf..f33caa545e1 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/require_contract_deployment/storage_access_caller/src/main.sw
@@ -6,7 +6,7 @@ use std::hash::*;
 #[cfg(experimental_new_encoding = false)]
 const CONTRACT_ID = 0x3bc28acd66d327b8c1b9624c1fabfc07e9ffa1b5d71c2832c3bfaaf8f4b805e9;
 #[cfg(experimental_new_encoding = true)]
-const CONTRACT_ID = 0xad4be8f8c517abaa781d488695e36f8dcaf4d609fc2723af4424ec78263163c1;
+const CONTRACT_ID = 0xe44ef1c461fec5318ddf2d4b93308ebe5c8a354134d85b08770c0da0ad939d82; // AUTO-CONTRACT-ID ../../test_contracts/storage_access_contract --release
 
 fn main() -> bool {
     let caller = abi(StorageAccess, CONTRACT_ID);
diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/unit_tests/workspace_test/contract_multi_test/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/unit_tests/workspace_test/contract_multi_test/src/main.sw
index 61e416f17bd..ced5fee81dd 100644
--- a/test/src/e2e_vm_tests/test_programs/should_pass/unit_tests/workspace_test/contract_multi_test/src/main.sw
+++ b/test/src/e2e_vm_tests/test_programs/should_pass/unit_tests/workspace_test/contract_multi_test/src/main.sw
@@ -17,14 +17,16 @@ fn test_foo() {
 
 #[test(should_revert)]
 fn test_fail() {
-    let caller = abi(MyContract, CONTRACT_ID);
+    let contract_id = 0x822c8d3672471f64f14f326447793c7377b6e430122db23b622880ccbd8a33ef; // AUTO-CONTRACT-ID .
+    let caller = abi(MyContract, contract_id);
     let result = caller.test_function {}();
     assert(result == false)
 }
 
 #[test]
 fn test_success() {
-    let caller = abi(MyContract, CONTRACT_ID);
+    let contract_id = 0x822c8d3672471f64f14f326447793c7377b6e430122db23b622880ccbd8a33ef; // AUTO-CONTRACT-ID .
+    let caller = abi(MyContract, contract_id);
     let result = caller.test_function {}();
     assert(result == true)
 }
diff --git a/test/src/in_language_tests/test_programs/bytes_inline_tests/src/main.sw b/test/src/in_language_tests/test_programs/bytes_inline_tests/src/main.sw
index 3d69727a4a2..d5107addd94 100644
--- a/test/src/in_language_tests/test_programs/bytes_inline_tests/src/main.sw
+++ b/test/src/in_language_tests/test_programs/bytes_inline_tests/src/main.sw
@@ -888,7 +888,7 @@ fn bytes_from_raw_slice() {
     };
 
     let mut bytes = Bytes::from(slice);
-    assert(bytes.ptr() == slice.ptr());
+    assert(bytes.ptr() != slice.ptr()); // Bytes should own its buffer
     assert(bytes.len() == slice.number_of_bytes());
 }
 
@@ -921,7 +921,7 @@ fn bytes_raw_slice_into() {
 
     let bytes: Bytes = slice.into();
 
-    assert(bytes.ptr() == slice.ptr());
+    assert(bytes.ptr() != slice.ptr()); // Bytes should own its buffer
     assert(bytes.len() == slice.number_of_bytes());
 }
 
diff --git a/test/src/in_language_tests/test_programs/string_inline_tests/src/main.sw b/test/src/in_language_tests/test_programs/string_inline_tests/src/main.sw
index ec1313fa345..079a28ee78d 100644
--- a/test/src/in_language_tests/test_programs/string_inline_tests/src/main.sw
+++ b/test/src/in_language_tests/test_programs/string_inline_tests/src/main.sw
@@ -55,7 +55,6 @@ fn string_clear_empty() {
 #[test]
 fn string_from_ascii() {
     let mut bytes = Bytes::new();
-
     bytes.push(0u8);
     bytes.push(1u8);
     bytes.push(2u8);
@@ -63,11 +62,15 @@ fn string_from_ascii() {
     bytes.push(4u8);
 
     let mut string_from_ascii = String::from_ascii(bytes);
-    assert(bytes.capacity() == string_from_ascii.capacity());
+    assert(bytes.len() == string_from_ascii.capacity());
+
     let bytes = string_from_ascii.as_bytes();
     assert(bytes.get(0).unwrap() == 0u8);
     assert(bytes.get(1).unwrap() == 1u8);
     assert(bytes.get(2).unwrap() == 2u8);
+    assert(bytes.get(3).unwrap() == 3u8);
+    assert(bytes.get(4).unwrap() == 4u8);
+    assert(bytes.get(5) == None);
 }
 
 #[test]
@@ -147,7 +150,7 @@ fn string_ptr() {
 
     let mut string_from_ascii = String::from_ascii(bytes);
     assert(!string_from_ascii.ptr().is_null());
-    assert(string_from_ascii.ptr() == bytes.ptr());
+    assert(string_from_ascii.ptr() != bytes.ptr());
 }
 
 #[test]
diff --git a/test/src/in_language_tests/test_programs/vec_inline_tests/src/main.sw b/test/src/in_language_tests/test_programs/vec_inline_tests/src/main.sw
index 5ac6a8fef32..78e2df5d1e5 100644
--- a/test/src/in_language_tests/test_programs/vec_inline_tests/src/main.sw
+++ b/test/src/in_language_tests/test_programs/vec_inline_tests/src/main.sw
@@ -641,7 +641,7 @@ fn vec_from_raw_slice() {
     };
 
     let mut vec: Vec<u64> = Vec::from(slice);
-    assert(vec.ptr() == slice.ptr());
+    assert(vec.ptr() != slice.ptr()); // Vec should own its buffer
     assert(vec.len() == slice.len::<u64>());
 }
 
@@ -683,7 +683,7 @@ fn vec_raw_slice_into() {
 
     let vec: Vec<u64> = slice.into();
 
-    assert(vec.ptr() == slice.ptr());
+    assert(vec.ptr() != slice.ptr()); // Vec should own its buffer
     assert(vec.len() == slice.len::<u64>());
 }
 
diff --git a/test/update-contract-ids.sh b/test/update-contract-ids.sh
new file mode 100755
index 00000000000..23c82db18a9
--- /dev/null
+++ b/test/update-contract-ids.sh
@@ -0,0 +1,48 @@
+#! /bin/bash
+
+# CHANGES=$(git status --porcelain | wc -l)
+# if [ "$CHANGES" != "0" ]; then
+#   echo "git state is not clean. commit or restore first."
+#   exit
+# fi
+
+BOLD_RED='\033[1;31m'
+BOLD_GREEN="\033[1;32m"
+BOLD_YELLOW='\033[1;33m'
+BOLD_WHITE='\033[1;97m'
+NC='\033[0m'
+
+function join_by {
+  local d=${1-} f=${2-}
+  if shift 2; then
+    printf %s "$f" "${@/#/$d}"
+  fi
+}
+
+grep --include \*.sw -Hno "// AUTO-CONTRACT-ID" . -R | while read line ; do
+    PARTS=($(echo $line | sed 's/:/ /g'))
+    FOLDER=$(dirname ${PARTS[0]})
+    FILE=${PARTS[0]}
+    LINE=${PARTS[1]}
+
+    CONTRACT_ARGS=($(sed "$LINE!d" $FILE))
+    CONTRACT_ARGS=$(join_by " " ${CONTRACT_ARGS[@]:6})
+
+    if [[ $CONTRACT_ARGS ]]; then 
+        PROJ=$(realpath "$FOLDER/..")
+        echo -e "${BOLD_WHITE}$PROJ${NC}"
+
+        pushd "$FOLDER/.." >> /dev/null
+        CONTRACT_ID=$(cargo r -p forc --release -- contract-id --path $CONTRACT_ARGS 2> /dev/null | grep -oP '0x[a-zA-Z0-9]{64}')
+
+        if [[ $CONTRACT_ID ]]; then 
+            popd >> /dev/null
+            sed -i "${LINE}s/0x[a-zA-Z0-9]*/$CONTRACT_ID/g" $FILE
+            echo -e "    ${BOLD_GREEN}ok${NC} ($CONTRACT_ID)"
+        else
+            echo -e "    ${BOLD_RED}error${NC}"
+            cargo r -p forc --release -- contract-id --release
+            popd >> /dev/null
+        fi
+    fi
+done