Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CredibleSafeGuard

Git Source

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:

  1. If the current block is credible, the transaction is always allowed.
  2. Otherwise, if the credible builder set looks offline (the most recent credible block is more than failOpenBlockThreshold blocks behind the current block), FAIL OPEN and allow the transaction. This prevents a stalled builder set from permanently locking the Safe.
  3. 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 setGuard again.

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

NameTypeDescription
credibleRegistry_ICredibleRegistryThe Credible Registry address (configurable per deployment).
failOpenBlockThreshold_uint256Blocks 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

NameTypeDescription
<none>boolTrue 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

NameTypeDescription
<none>boolTrue 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();