test(contracts): enforce __GAP slot + size invariant in storage layout check (#448)

## Summary
- Adds an arithmetic invariant check (`slot + size == 151`) to
`check-storage-layout.sh` that catches cases where a new state variable
is added without shrinking `__GAP` accordingly
- The existing snapshot-diff check alone could pass with a wrong gap
size if the snapshot is updated to match — this new check prevents that
- Updates the negative test to also accept the new `__GAP invariant
violated!` error message

## Test plan
- [x] `check-storage-layout.sh` passes on the current correct layout
- [x] `check-storage-layout-negative.sh` passes — the bad layout
contract (slot 107 + size 45 = 152) correctly triggers the invariant
failure
This commit is contained in:
Ahmad Kaouk 2026-02-20 09:29:34 +01:00 committed by GitHub
parent ddbc9bdd8b
commit b88727d7bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 23 additions and 1 deletions

View file

@ -20,7 +20,7 @@ if [ "$EXIT_CODE" -eq 0 ]; then
exit 1
fi
if ! printf '%s\n' "$OUTPUT" | grep -q "ERROR: Storage layout has changed!"; then
if ! printf '%s\n' "$OUTPUT" | grep -qE "ERROR: (Storage layout has changed!|__GAP invariant violated!)"; then
echo "ERROR: Storage layout check failed, but not for the expected reason."
echo ""
echo "Output:"

View file

@ -59,4 +59,26 @@ if ! diff -q /tmp/snap_normalized.json /tmp/curr_normalized.json > /dev/null 2>&
exit 1
fi
# Verify gap invariant: __GAP slot + array size must equal a fixed constant.
# This catches cases where a new variable is added but __GAP is not shrunk accordingly.
EXPECTED_GAP_TOTAL=151
GAP_SLOT=$(jq '.storage[] | select(.label == "__GAP") | .slot | tonumber' /tmp/current_layout.json)
GAP_SIZE=$(jq -r '.storage[] | select(.label == "__GAP") | .type' /tmp/current_layout.json \
| grep -oE '[0-9]+' | tail -1)
if [ -n "$GAP_SLOT" ] && [ -n "$GAP_SIZE" ]; then
GAP_TOTAL=$((GAP_SLOT + GAP_SIZE))
if [ "$GAP_TOTAL" -ne "$EXPECTED_GAP_TOTAL" ]; then
echo ""
echo "=========================================="
echo "ERROR: __GAP invariant violated!"
echo "=========================================="
echo ""
echo " slot($GAP_SLOT) + size($GAP_SIZE) = $GAP_TOTAL, expected $EXPECTED_GAP_TOTAL"
echo ""
echo "If you added a new state variable, shrink __GAP by the same number of slots."
exit 1
fi
fi
echo "Storage layout OK - no changes detected"