---
id: TIP-1057
title: T5 Hardfork Meta TIP
description: Meta TIP collecting bug fixes, security hardening, and infrastructure changes gated behind the T5 hardfork.
authors: Marc Martinez (@0xrusowsky)
status: Draft
related: TIP-1026, TIP-1030, TIP-1033, TIP-1034, TIP-1035, TIP-1045, TIP-1053, TIP-1056
protocolVersion: T5
---

# TIP-1057: T5 Hardfork Meta TIP

## Abstract

This meta TIP collects bug fixes, security hardening, and infrastructure changes that activate at T5. Each item is small in isolation, but together they define the complete in-scope T5 bug-fix and infrastructure bundle. Feature changes already specified by standalone TIPs (TIP-1026, TIP-1030, TIP-1033, TIP-1034, TIP-1035, TIP-1045, TIP-1053, TIP-1056) are intentionally excluded from this meta TIP.

## Motivation

Ongoing internal review and audit follow-ups uncovered correctness issues in precompile storage codegen that require hardfork gating. Additionally, cross-chain interoperability requirements necessitate deploying standard factory contracts at the T5 boundary. Because these changes alter state-function behavior or chain state at activation boundaries, they are grouped here as one coordinated rollout under T5.

---

# Changes

## 1. Fix fixed-size array packing in precompile storage codegen

**PR**: [#3811](https://github.com/tempoxyz/tempo/pull/3811) · **Author**: @0xrusowsky

Two paired correctness bugs in `[T; N]` storage codegen for element types where `T::BYTES <= 16` but `32 % T::BYTES != 0` (in practice: `[U96; N]`, `[I96; N]`, and odd-sized `[FixedBytes<N>; M]`).

- **Bulk and indexed paths used mismatched packing rules.** `storable_primitives::is_packable` required `32 % byte_count == 0`, excluding 12-byte types from the packed bulk path. `ArrayHandler::compute_handler` gates only on `T::BYTES <= 16` and uses the packed path. A bulk write followed by an indexed read on the same `[U96; N]` returns the wrong element; an indexed write mutates the wrong slot.
- **Packed slot-count formula undercounted the trailing partial slot.** `(N * byte_count).div_ceil(32)` treats storage as contiguous and undercounts when `byte_count` does not divide 32. `[U96; 5]` reported 2 slots instead of 3, and the bulk-store loop dropped the final element.

T5+ fixes: relax `is_packable` to `byte_count < 32` (matching the trait-level `Layout::is_packable()` already used by indexed access) and route both array-codegen call sites through `packing::calc_packed_slot_count`.

## 2. Clean up stale tail slots in dynamic storage types

**PR**: [#3840](https://github.com/tempoxyz/tempo/pull/3840) · **Author**: @0xrusowsky

Overwriting a dynamic storable (`Vec<T>`, `String`, `Bytes`) with a shorter value left stale tail slots populated, so subsequent reads observed garbage past the new length. T5+ ensures that shrinking writes on dynamic types clear their stale tails. Additionally introduces a `LayoutCtx::INIT` sentinel for hot paths that know the destination is virgin (`Vec::push`), letting them skip the extra SLOAD + cleanup.
