Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 91 additions & 22 deletions script/check-published-deploy-constants.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,119 @@
# SPDX-License-Identifier: LicenseRef-DCL-1.0
# SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd
#
# Prints "OK" iff every version published to the soldeer registry for
# `rain-math-float` has a full suite of pinned deploy constants in
# LibDecimalFloatDeploy.sol: a log-tables address + codehash and a DecimalFloat
# address + codehash, each suffixed with the version.
# Checks that the per-version deploy constants pinned in LibDecimalFloatDeploy.sol
# are complete. Each published version needs a full suite: a log-tables address +
# codehash and a DecimalFloat address + codehash, each suffixed with the version
# (dots replaced by underscores).
#
# Two halves, split by what they depend on:
#
# 1. STRUCTURAL (offline). Every version suffix that carries any pinned
# constant must carry all four. Catches a half-written release snapshot.
# Pure file inspection, so it is deterministic and always runs.
# 2. REGISTRY (online). Every version published to the soldeer registry must
# carry a pinned suite, so publishing a tag without pinning its constants
# is caught. Needs api.soldeer.xyz.
#
# Usage:
# check-published-deploy-constants.sh [--lib <path>] [--offline]
#
# --lib <path> file to inspect (default src/lib/deploy/LibDecimalFloatDeploy.sol)
# --offline run the structural half only, and never touch the network.
# Lets a test assert the structural half deterministically
# instead of depending on whether the registry answered.
#
# Consumed by LibDecimalFloatDeployTaggedConstants.t.sol via FFI. Output is one
# of:
# OK - every published version has its full constant suite
# OK - every half that ran, passed
# MISSING: <names...> - one or more expected constants are absent
# SKIP: <reason> - the registry could not be reached (nothing verified)
# SKIP: <reason> - default mode only: the structural half passed but the
# registry was unreachable, so that half did not run
#
# Always exits 0 so the test sees the message rather than an ffi failure.

set -uo pipefail

lib="src/lib/deploy/LibDecimalFloatDeploy.sol"
offline=0

versions=$(
curl -fsS --connect-timeout 5 --max-time 20 --retry 2 --retry-delay 1 \
"https://api.soldeer.xyz/api/v1/revision?project_name=rain-math-float" 2>/dev/null \
| grep -oE '"version":"[0-9][0-9.]*"' | cut -d'"' -f4 | sort -u
)
while [ "$#" -gt 0 ]; do
case "$1" in
--lib)
lib="${2:-}"
if [ -z "$lib" ]; then
printf 'MISSING: --lib requires a path'
exit 0
fi
shift 2
;;
--offline)
offline=1
shift
;;
*)
printf 'MISSING: unknown argument %s' "$1"
exit 0
;;
esac
done

if [ -z "$versions" ]; then
printf 'SKIP: could not fetch published soldeer versions'
if [ ! -f "$lib" ]; then
printf 'MISSING: no such file %s' "$lib"
exit 0
fi

# The deploy constants that must be pinned for every published version, suffixed
# with the version (dots replaced by underscores).
# The deploy constants that must be pinned for every version.
bases="ZOLTU_DEPLOYED_LOG_TABLES_ADDRESS \
LOG_TABLES_DATA_CONTRACT_HASH \
ZOLTU_DEPLOYED_DECIMAL_FLOAT_ADDRESS \
DECIMAL_FLOAT_CONTRACT_HASH"

missing=""
for v in $versions; do
suffix=$(printf '%s' "$v" | tr . _)
for b in $bases; do
name="${b}_${suffix}"
grep -qE "constant ${name} =" "$lib" || missing="${missing} ${name}"

# Append every `<base>_<suffix>` absent from the lib to $missing.
check_suffixes() {
for suffix in $1; do
for b in $bases; do
name="${b}_${suffix}"
grep -qE "constant ${name} =" "$lib" || missing="${missing} ${name}"
done
done
done
}

# 1. Structural half. Collect every version suffix carrying at least one pinned
# constant, then demand the whole suite for each. Requiring `_[0-9]` after the
# base keeps the un-suffixed "current" constants out of the suffix set.
pinned_suffixes=$(
for b in $bases; do
grep -oE "constant ${b}_[0-9][0-9_]* =" "$lib" \
| sed -E "s/^constant ${b}_//; s/ =\$//"
done | sort -u
)
check_suffixes "$pinned_suffixes"

# 2. Registry half.
versions=""
if [ "$offline" -eq 0 ]; then
versions=$(
curl -fsS --connect-timeout 5 --max-time 20 --retry 2 --retry-delay 1 \
"https://api.soldeer.xyz/api/v1/revision?project_name=rain-math-float" 2>/dev/null \
| grep -oE '"version":"[0-9][0-9.]*"' | cut -d'"' -f4 | sort -u
)
if [ -n "$versions" ]; then
check_suffixes "$(printf '%s' "$versions" | tr . _)"
fi
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
fi

# An absence outranks an unreachable registry: a MISSING from the structural
# half is a real failure whether or not the registry answered.
if [ -n "$missing" ]; then
printf 'MISSING:%s' "$missing"
printf 'MISSING:'
printf '%s' "$missing" | tr ' ' '\n' | grep -v '^$' | sort -u | while IFS= read -r n; do
printf ' %s' "$n"
done
elif [ "$offline" -eq 0 ] && [ -z "$versions" ]; then
printf 'SKIP: could not fetch published soldeer versions; pinned constant suites are structurally complete'
else
printf 'OK'
fi
16 changes: 16 additions & 0 deletions test/fixtures/half-pinned-deploy-constants.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# SPDX-License-Identifier: LicenseRef-DCL-1.0
# SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd
#
# Fixture for LibDecimalFloatDeployTaggedConstantsTest. Stands in for
# LibDecimalFloatDeploy.sol and deliberately pins version 9.9.9 only HALFWAY:
# the two address constants are present, the two codehash constants are not.
# The structural half of script/check-published-deploy-constants.sh must report
# both absent codehashes for it.
#
# Deliberately NOT a .sol file: forge compiles everything under test/, and this
# is grep fodder rather than Solidity. The script only ever matches
# `constant <NAME> =`, so the surrounding prose is inert.

address constant ZOLTU_DEPLOYED_LOG_TABLES_ADDRESS_9_9_9 = address(0xc51a14251b0dcF0ae24A96b7153991378938f5F5);

address constant ZOLTU_DEPLOYED_DECIMAL_FLOAT_ADDRESS_9_9_9 = address(0xBee0eEFaffD046c9602109eB30A858Be301CC926);
58 changes: 51 additions & 7 deletions test/src/lib/deploy/LibDecimalFloatDeployTaggedConstants.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,69 @@
pragma solidity =0.8.25;

import {Test} from "forge-std-1.16.1/src/Test.sol";
import {console2} from "forge-std-1.16.1/src/console2.sol";

/// @title LibDecimalFloatDeployTaggedConstantsTest
/// @notice Every version published to the soldeer registry for `rain-math-float`
/// must have a full suite of pinned deploy constants in `LibDecimalFloatDeploy`:
/// a log-tables address + codehash and a DecimalFloat address + codehash for
/// each published version. `script/check-published-deploy-constants.sh` queries
/// the live registry (via FFI) and lists any missing constants, so publishing a
/// new tag without pinning its constants fails this test. Skips if the registry
/// is unreachable rather than failing on network flakiness.
/// each published version.
///
/// `script/check-published-deploy-constants.sh` splits that into a structural
/// half (every version suffix carrying any pinned constant carries all four —
/// pure file inspection) and a registry half (every published version is
/// pinned — needs api.soldeer.xyz). The structural half is asserted
/// unconditionally here, so a run that cannot reach the registry still verifies
/// something real rather than verifying nothing.
contract LibDecimalFloatDeployTaggedConstantsTest is Test {
string constant SCRIPT = "script/check-published-deploy-constants.sh";
string constant HALF_PINNED_FIXTURE = "test/fixtures/half-pinned-deploy-constants.txt";

/// Structural half against the committed lib. No network, so this asserts
/// on every run: a version pinned halfway fails here.
function testEveryPinnedVersionGroupIsComplete() external {
string[] memory cmd = new string[](3);
cmd[0] = "bash";
cmd[1] = SCRIPT;
cmd[2] = "--offline";
assertEq(string(vm.ffi(cmd)), "OK", "a pinned version is missing part of its deploy constant suite");
}

/// The structural half must actually detect a half-pinned version, not just
/// report OK for everything. Without this, a check that inspected nothing
/// would pass `testEveryPinnedVersionGroupIsComplete` just as happily.
function testStructuralCheckDetectsAHalfPinnedVersion() external {
string[] memory cmd = new string[](5);
cmd[0] = "bash";
cmd[1] = SCRIPT;
cmd[2] = "--offline";
cmd[3] = "--lib";
cmd[4] = HALF_PINNED_FIXTURE;
assertEq(
string(vm.ffi(cmd)),
"MISSING: DECIMAL_FLOAT_CONTRACT_HASH_9_9_9 LOG_TABLES_DATA_CONTRACT_HASH_9_9_9",
"the structural check failed to report a half-pinned version"
);
}

/// Both halves. Publishing a soldeer tag without pinning its deploy
/// constants fails here.
function testAllPublishedSoldeerTagsHaveAFullConstantSuite() external {
string[] memory cmd = new string[](2);
cmd[0] = "bash";
cmd[1] = "script/check-published-deploy-constants.sh";
cmd[1] = SCRIPT;
bytes memory out = vm.ffi(cmd);

// The registry could not be reached; there is nothing to verify.
// api.soldeer.xyz was unreachable, so the registry half did not run.
// This is a pass on what was checked, NOT a skip: the structural half
// ran and passed inside the same invocation, and is asserted outright
// by testEveryPinnedVersionGroupIsComplete above. Only "is every
// PUBLISHED version pinned" is unverifiable without the network,
// because the set of published versions lives on the registry. The
// reason is logged so a green run that never reached the registry says
// so, instead of looking like a full check.
if (_startsWith(out, bytes("SKIP"))) {
vm.skip(true);
console2.log(string(out));
return;
}

Expand Down
Loading