CredibleBlockGuard, accepts calls in credible blocks, rejects calls in non-credible blocks, and fails open when credible block production stops.
Prerequisites
- A checkout of
credible-std anvil,cast,forge, andjqavailable on yourPATH- A free local port
8545, or another port selected withRPC_PORT
Run the integration script
From the root of yourcredible-std checkout, run:
GuardedCounter fixture. This confirms that the harness and base guard work, but it does not validate your upgrade.
To use another local port or shorten the fail-open test window, set either environment variable:
Test your upgraded contract
The runner always starts a fresh Anvil node. It cannot test an address from a live network or another Anvil instance. Instead, give it commands that deploy the registry and deploy or upgrade your contract after Anvil starts. Prepare two commands in your protocol repository:- A registry command that configures the marker account as an authorized builder and prints the registry address as its final line.
- A target command that deploys or upgrades your contract to use that registry and threshold, sets up required balances, roles, or approvals, and prints the target or proxy address as its final line.
- The guarded function call to execute
- A read-only call that proves the action’s state effect
- The expected state before the call and after a successful call
- The registry and fail-open threshold the target must use
RPC_URL, REGISTRY_ADDRESS, and EXPECTED_THRESHOLD available as environment variables. It runs the registry command first, then supplies its resulting REGISTRY_ADDRESS to the target command.
The script verifies credibleRegistry()(address) and failOpenBlockThreshold()(uint256) by default. If your contract exposes different getters, pass --registry-read-call and --threshold-read-call. If it exposes no suitable getters, use --config-assert-command to run a contract-specific assertion that exits successfully only when the target uses the expected registry and threshold.
The command shape for your contract is:
upgrade-and-print-target.sh must leave the upgraded target or proxy address on its final output line. Choose --expected-threshold to match the threshold configured by that command.
The following is a runnable reference implementation of that interface using the example contracts:
ADMIN_KEY, MARKER_KEY, GUARDED_KEY, MARKER_ADDRESS, and GUARDED_ADDRESS; use them only in trusted local commands.
What the script verifies
- A builder marker transaction and a guarded call are queued and mined in the same block. Both transactions succeed and the counter increments.
- A guarded call mined without a marker reverts with
NonCredibleBlock()while the recent credible-block window is still active. - At the configured threshold, the guard remains closed. Once the latest credible block is more than
FAIL_OPEN_THRESHOLDblocks behind, the call succeeds through the guard’s fail-open path.
Verify the result
Confirm that the summary reports zero failures, for example:0 failed and a zero exit status.
The runner validates the guard’s configuration and behavior. It does not by itself prove broader upgrade safety, such as storage-layout compatibility or the correctness of your upgrade authorization flow.
For unit-level decision coverage without a live-node bundle, see How to Test Assertions.
