Assertion
Inherits: ForkUtils, StateChanges
Title: Assertion
Author: Phylax Systems
Base contract for creating Credible Layer assertions
Inherit from this contract to create custom assertions. Assertions can inspect
transaction state via the inherited ph precompile and register triggers to specify
when the assertion should be executed.
Example:
contract MyAssertion is Assertion {
function triggers() external view override {
registerCallTrigger(this.checkInvariant.selector, ITarget.deposit.selector);
}
function checkInvariant() external {
ph.forkPostTx();
Check invariants...
}
}
Constants
triggerRecorder
The trigger recorder precompile for registering assertion triggers
Address is derived from a deterministic hash for consistency
TriggerRecorder constant triggerRecorder = TriggerRecorder(address(uint160(uint256(keccak256("TriggerRecorder")))))
specRecorder
The spec recorder precompile for registering the assertion spec
Address is derived from keccak256(“SpecRecorder”)
SpecRecorder constant specRecorder = SpecRecorder(address(uint160(uint256(keccak256("SpecRecorder")))))
Functions
triggers
Used to record fn selectors and their triggers.
function triggers() external view virtual;
registerCallTrigger
Registers a call trigger for the AA without specifying an AA function selector. This will trigger the assertion function on any call to the AA.
function registerCallTrigger(bytes4 fnSelector) internal view;
Parameters
| Name | Type | Description |
|---|---|---|
fnSelector | bytes4 | The function selector of the assertion function. |
registerCallTrigger
Registers a call trigger for calls to the AA with a specific AA function selector.
function registerCallTrigger(bytes4 fnSelector, bytes4 triggerSelector) internal view;
Parameters
| Name | Type | Description |
|---|---|---|
fnSelector | bytes4 | The function selector of the assertion function. |
triggerSelector | bytes4 | The function selector upon which the assertion will be triggered. |
registerStorageChangeTrigger
Registers storage change trigger for any slot
function registerStorageChangeTrigger(bytes4 fnSelector) internal view;
Parameters
| Name | Type | Description |
|---|---|---|
fnSelector | bytes4 | The function selector of the assertion function. |
registerStorageChangeTrigger
Registers storage change trigger for a specific slot
function registerStorageChangeTrigger(bytes4 fnSelector, bytes32 slot) internal view;
Parameters
| Name | Type | Description |
|---|---|---|
fnSelector | bytes4 | The function selector of the assertion function. |
slot | bytes32 | The storage slot to trigger on. |
registerBalanceChangeTrigger
Registers balance change trigger for the AA
function registerBalanceChangeTrigger(bytes4 fnSelector) internal view;
Parameters
| Name | Type | Description |
|---|---|---|
fnSelector | bytes4 | The function selector of the assertion function. |
registerFnCallTrigger
Registers an onFnCall trigger. The assertion fires once per matching call, with TriggerContext available via ph.context().
function registerFnCallTrigger(bytes4 fnSelector, bytes4 triggerSelector) internal view;
Parameters
| Name | Type | Description |
|---|---|---|
fnSelector | bytes4 | The assertion function to invoke. |
triggerSelector | bytes4 | The 4-byte selector on the adopter to watch for. |
registerTxEndTrigger
Registers a trigger that fires once after the entire transaction completes.
function registerTxEndTrigger(bytes4 fnSelector) internal view;
Parameters
| Name | Type | Description |
|---|---|---|
fnSelector | bytes4 | The assertion function to invoke. |
registerErc20ChangeTrigger
Registers a trigger that fires when a token’s balances change.
function registerErc20ChangeTrigger(bytes4 fnSelector, address token) internal view;
Parameters
| Name | Type | Description |
|---|---|---|
fnSelector | bytes4 | The assertion function to invoke. |
token | address | The ERC20 token address to watch. |
watchCumulativeOutflow
Registers a circuit breaker trigger that fires when cumulative ERC20 outflow from the assertion adopter exceeds a percentage threshold within a rolling time window.
function watchCumulativeOutflow(address token, uint256 thresholdBps, uint256 windowDuration, bytes4 fnSelector)
internal
view;
Parameters
| Name | Type | Description |
|---|---|---|
token | address | The ERC20 token address to monitor. |
thresholdBps | uint256 | Maximum cumulative outflow as basis points of the TVL snapshot taken at window start. 1000 = 10%. |
windowDuration | uint256 | Rolling window length in seconds. |
fnSelector | bytes4 | The assertion function to invoke when the threshold is breached. |
watchCumulativeInflow
Registers a circuit breaker trigger that fires when cumulative ERC20 inflow into the assertion adopter exceeds a percentage threshold within a rolling time window.
function watchCumulativeInflow(address token, uint256 thresholdBps, uint256 windowDuration, bytes4 fnSelector)
internal
view;
Parameters
| Name | Type | Description |
|---|---|---|
token | address | The ERC20 token address to monitor. |
thresholdBps | uint256 | Maximum cumulative inflow as basis points of the TVL snapshot taken at window start. 1000 = 10%. |
windowDuration | uint256 | Rolling window length in seconds. |
fnSelector | bytes4 | The assertion function to invoke when the threshold is breached. |
_successOnlyFilter
Returns a CallFilter that only matches successful calls at any depth.
function _successOnlyFilter() internal pure returns (PhEvm.CallFilter memory filter);
_matchingCalls
Returns successful calls matching target and selector, up to limit.
function _matchingCalls(address target, bytes4 selector, uint256 limit)
internal
view
returns (PhEvm.TriggerCall[] memory);
_preTx
function _preTx() internal pure returns (PhEvm.ForkId memory);
_postTx
function _postTx() internal pure returns (PhEvm.ForkId memory);
_preCall
function _preCall(uint256 callId) internal pure returns (PhEvm.ForkId memory);
_postCall
function _postCall(uint256 callId) internal pure returns (PhEvm.ForkId memory);
registerAssertionSpec
Registers the desired assertion spec. Must be called within the constructor. The assertion spec defines what subset of precompiles are available. Can only be called once. For an assertion to be valid, it needs a defined spec.
function registerAssertionSpec(AssertionSpec spec) internal view;
Parameters
| Name | Type | Description |
|---|---|---|
spec | AssertionSpec | The desired AssertionSpec. |