CredibleSafeGuard
Inherits: ITransactionGuard
Title: CredibleSafeGuard
Author: Phylax Systems
Safe transaction guard that only allows owner/multisig Safe transactions while the current block is credible, i.e. built by a Credible Layer builder that enforces assertions. When the credible builder set is offline the guard fails open so the Safe is never bricked.
Installed on a Safe via setGuard(address(thisGuard)). The Safe calls
checkTransaction before every owner-path execution; a revert blocks that execution.
Scope. This guard implements only Safe’s transaction-guard interface ({ITransactionGuard}),
so it gates the owner/multisig execTransaction path only. Module executions
(execTransactionFromModule/...ReturnData) do not run transaction guards, so an enabled
module can still execute while the current block is not credible. Gating module executions
requires a separate Safe module guard (the v1.5.0 checkModuleTransaction hook) or a
Credible Layer assertion such as {SafeTxShapeAssertion}.
Decision in checkTransaction:
- If the current block is credible, the transaction is always allowed.
- Otherwise, if the credible builder set looks offline (the most recent credible block
is more than
failOpenBlockThresholdblocks behind the current block), FAIL OPEN and allow the transaction. This prevents a stalled builder set from permanently locking the Safe. - Otherwise the builder set is live and the current block is not credible, so the transaction is blocked with NonCredibleBlock. Fail-open window. The product requirement is “fail open after ~15 minutes with no credible blocks”. The {ICredibleRegistry} records credibility by block number and does not expose timestamps, so the window is expressed as a block count that the credible builder set would produce in ~15 minutes on the target chain, e.g.:
- ~12s blocks (Ethereum mainnet): 15 min ~= 75 blocks
- ~2s blocks (typical L2): 15 min ~= 450 blocks
- ~1s blocks: 15 min ~= 900 blocks
Both the registry address and the fail-open threshold are immutable; re-pointing or
re-tuning means deploying a new guard and calling
setGuardagain.
Constants
credibleRegistry
The on-chain Credible Registry queried for block credibility.
ICredibleRegistry public immutable credibleRegistry
failOpenBlockThreshold
Number of blocks the most recent credible block may lag the current block before the guard fails open. Should approximate the chain’s 15-minute block budget.
uint256 public immutable failOpenBlockThreshold
Functions
constructor
constructor(ICredibleRegistry credibleRegistry_, uint256 failOpenBlockThreshold_) ;
Parameters
| Name | Type | Description |
|---|---|---|
credibleRegistry_ | ICredibleRegistry | The Credible Registry address (configurable per deployment). |
failOpenBlockThreshold_ | uint256 | Blocks of builder silence tolerated before failing open. |
checkTransaction
Called by the Safe before executing an owner-authorized transaction.
Reverts with NonCredibleBlock to block a Safe transaction. All transaction fields are ignored: the guard only gates on whether the executing block is credible.
function checkTransaction(
address,
uint256,
bytes memory,
Enum.Operation,
uint256,
uint256,
uint256,
address,
address payable,
bytes memory,
address
) external view override;
checkAfterExecution
Called by the Safe after executing the transaction.
No post-execution checks are performed.
function checkAfterExecution(bytes32, bool) external pure override;
supportsInterface
function supportsInterface(bytes4 interfaceId) external pure override returns (bool);
isCurrentBlockAllowed
Whether a Safe transaction would currently be allowed by this guard.
View helper mirroring checkTransaction’s decision for off-chain inspection.
function isCurrentBlockAllowed() external view returns (bool);
Returns
| Name | Type | Description |
|---|---|---|
<none> | bool | True if the current block is credible or the guard is failing open. |
failOpenActive
Whether the guard is currently failing open because the builder set looks offline.
function failOpenActive() external view returns (bool);
Returns
| Name | Type | Description |
|---|---|---|
<none> | bool | True if the most recent credible block lags the current block beyond the threshold. |
_checkCredibleBlock
Core gate: allow credible blocks, otherwise fail open only when the builder set is offline. The credible-block check runs first so the expected hot path (credible block, live builder set) costs a single registry call.
function _checkCredibleBlock() internal view;
_failOpenActive
Fail-open is active when the current block is strictly more than
failOpenBlockThreshold blocks ahead of the last credible block. The
block.number > lastCredibleBlock_ guard avoids underflow if the registry ever
reports a last credible block at or beyond the current block.
function _failOpenActive() internal view returns (bool);
Errors
NonCredibleBlock
Thrown when the current block is not credible and the builder set is live.
error NonCredibleBlock();
ZeroCredibleRegistryAddress
Thrown when constructed with the zero address as the registry.
error ZeroCredibleRegistryAddress();
ZeroFailOpenBlockThreshold
Thrown when constructed with a zero fail-open threshold.
error ZeroFailOpenBlockThreshold();