Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion assertions-book/assertions/ass01-impl-addr-change.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ For example, it's possible to define a whitelist of allowed implementations - an

Monitors changes to the implementation address storage slot in proxy contracts using:

- `ph.forkPreState()` / `ph.forkPostState()`: Compare implementation address before and after transaction
- `ph.forkPreTx()` / `ph.forkPostTx()`: Compare implementation address before and after transaction
- `getStateChangesAddress()`: Track all changes to the implementation slot during transaction execution
- `registerStorageChangeTrigger()`: Trigger when implementation address changes

Expand Down
2 changes: 1 addition & 1 deletion assertions-book/assertions/ass05-ownership-change.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ For example, in the [Radiant Capital hack](/assertions-book/previous-hacks/hack1

Monitors changes to the owner address storage slot in contracts using:

- `ph.forkPreState()` / `ph.forkPostState()`: Compare owner address before and after transaction
- `ph.forkPreTx()` / `ph.forkPostTx()`: Compare owner address before and after transaction
- `getStateChangesAddress()`: Track all changes to the owner address slot during transaction execution
- `registerStorageChangeTrigger()`: Trigger when owner address changes

Expand Down
2 changes: 1 addition & 1 deletion assertions-book/assertions/ass06-constant-product.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The constant product formula is fundamental to many AMM designs - any deviation

Monitors the product of reserves (k) in AMM pools to ensure it remains constant after transactions using:

- `forkPreState()` / `forkPostState()`: Compare reserve product before and after transaction
- `forkPreTx()` / `forkPostTx()`: Compare reserve product before and after transaction
- `getStateChanges()`: Monitor reserve changes throughout transaction callstack
- Direct validation that k = reserve0 * reserve1 remains unchanged

Expand Down
2 changes: 1 addition & 1 deletion assertions-book/assertions/ass07-lending-health-factor.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Monitors health factors of positions during specific lending operations using:

- `getCallInputs()`: Track all function calls to specified protocol functions
- `registerCallTrigger()`: Trigger on lending operations (supply, borrow, withdraw, repay)
- `forkPostState()`: Verify health factor after each operation (used by default if no pre-state specified)
- `forkPostTx()`: Verify health factor after each operation (used by default if no pre-state specified)

The assertion checks each lending operation individually to ensure positions affected by these operations remain healthy.

Expand Down
2 changes: 1 addition & 1 deletion assertions-book/assertions/ass08-sum-of-all-positions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Since direct iteration over all positions isn't currently supported, this assert
4. Verify that the new total supply equals the pre-state total supply plus the sum of position changes

Uses these cheatcodes:
- `ph.forkPreState()` / `ph.forkPostState()`: Capture total supply before and after transaction
- `ph.forkPreTx()` / `ph.forkPostTx()`: Capture total supply before and after transaction
- `ph.getCallInputs()`: Track function calls that modify positions
- `registerCallTrigger()`: Trigger on position-modifying functions

Expand Down
2 changes: 1 addition & 1 deletion assertions-book/assertions/ass09-timelock-verification.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Timelocks provide a buffer against malicious governance actions - without proper

Verifies timelock integrity by comparing timelock state and parameters before and after transactions:

- `forkPreState()` / `forkPostState()`: Compare timelock state before and after transaction
- `forkPreTx()` / `forkPostTx()`: Compare timelock state before and after transaction
- `registerStorageChangeTrigger()`: Monitor changes to timelock storage slot
- Ensures timelock delay is within acceptable bounds (1 day to 2 weeks)
- Confirms timelock activation follows proper procedures
Expand Down
2 changes: 1 addition & 1 deletion assertions-book/assertions/ass10-oracle-validation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Stale oracle data can indicate service disruption or attacks on oracle infrastru

Monitors oracle timestamp updates when critical protocol functions are called:

- `forkPostState()`: Check oracle's last update time after transaction
- `forkPostTx()`: Check oracle's last update time after transaction
- `registerCallTrigger()`: Trigger on functions that rely on oracle data (e.g., DEX swaps)
- Verify oracle's last update time is within defined maximum time window

Expand Down
2 changes: 1 addition & 1 deletion assertions-book/assertions/ass11-twap-deviation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Sudden price deviations could indicate manipulation through flash loan attacks o

Monitors TWAP price changes using a two-stage approach to ensure price stability:

- `ph.forkPreState()` / `ph.forkPostState()`: Compare post-transaction price against pre-transaction TWAP
- `ph.forkPreTx()` / `ph.forkPostTx()`: Compare post-transaction price against pre-transaction TWAP
- `getStateChangesUint()`: Track all price changes during transaction execution
- `registerStorageChangeTrigger()`: Trigger when price storage slot changes

Expand Down
2 changes: 1 addition & 1 deletion assertions-book/assertions/ass15-price-within-ticks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ If attackers could push prices outside valid tick ranges, they could execute tra

Implements focused tick integrity verification:

- `ph.forkPreState()` / `ph.forkPostState()`: Capture tick state before and after transaction
- `ph.forkPreTx()` / `ph.forkPostTx()`: Capture tick state before and after transaction
- `registerStorageChangeTrigger()`: Monitor changes to tick-related storage slots
- Verify ticks stay within global bounds (-887272 to 887272)
- Ensure ticks align with pool's tick spacing requirements
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ Incorrect health factor validation could lead to unfair liquidations, protocol i

Implements multi-layered liquidation health factor verification:

- **Pre-liquidation**: `forkPreState()` captures health factor before liquidation, verifies position is actually unhealthy
- **Post-liquidation**: `forkPostState()` verifies health factor improves after liquidation
- **Pre-liquidation**: `forkPreTx()` captures health factor before liquidation, verifies position is actually unhealthy
- **Post-liquidation**: `forkPostTx()` verifies health factor improves after liquidation
- **Parameter validation**: `getCallInputs()` monitors liquidation calls, validates seized assets and repaid shares are non-zero, enforces maximum liquidation amounts
- `registerCallTrigger()`: Triggers on liquidation function calls

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Improper handling of pause states can lead to fund lockups, unauthorized access,

Monitors protocol balance and pause state to ensure proper emergency behavior using a multi-layered approach:

- `ph.forkPreState()` / `ph.forkPostState()`: Capture protocol state before and after transaction
- `ph.forkPreTx()` / `ph.forkPostTx()`: Capture protocol state before and after transaction
- `getStateChangesUint()`: Track all state changes during transaction
- `registerCallTrigger()`: Monitor all function calls to the contract
- Verify protocol balance can only decrease when paused (allowing withdrawals)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Incorrect harvest implementations could lead to loss of user funds, price per sh

Implements multi-layered approach to verify harvest operations:

- `forkPreState()` / `forkPostState()`: Capture vault balance and price per share before/after harvest
- `forkPreTx()` / `forkPostTx()`: Capture vault balance and price per share before/after harvest
- `getStateChangesUint()`: Monitor all balance changes during transaction execution
- `registerCallTrigger()`: Trigger on harvest function calls
- Ensures balance hasn't decreased (can stay same if harvested recently)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Violating this invariant could lead to protocol insolvency, loss of user funds,

Implements straightforward verification that total tokens borrowed never exceed total tokens deposited:

- `ph.forkPostState()`: Capture protocol state after transaction to verify invariant holds
- `ph.forkPostTx()`: Capture protocol state after transaction to verify invariant holds
- `registerStorageChangeTrigger()`: Trigger on storage slots tracking supply and borrow totals
- Check total supply of assets (tokens deposited) and total borrowed assets
- Assert total supply ≥ total borrowed assets
Expand Down
2 changes: 1 addition & 1 deletion assertions-book/assertions/ass20-erc20-drain.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ By limiting outflow rates, protocols gain valuable time to respond to security i

Implements percentage-based limit on token outflows in a single transaction:

- `forkPreState()` / `forkPostState()`: Capture token balance before and after transaction
- `forkPreTx()` / `forkPostTx()`: Capture token balance before and after transaction
- `registerCallTrigger()`: Trigger on every transaction without specifying particular function signature
- Calculate percentage of tokens withdrawn in transaction
- Revert if withdrawal percentage exceeds configured threshold
Expand Down
2 changes: 1 addition & 1 deletion assertions-book/assertions/ass21-ether-drain.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Malicious actors often attempt to extract all available ETH in a single transact

Implements tiered protection strategy to detect rapid ETH draining:

- `forkPreState()` / `forkPostState()`: Capture contract's ETH balance and whitelist balances before/after transaction
- `forkPreTx()` / `forkPostTx()`: Capture contract's ETH balance and whitelist balances before/after transaction
- `registerBalanceChangeTrigger()`: Trigger when ETH balances change
- For small withdrawals (below threshold): Allow regardless of destination
- For large withdrawals (above threshold): Require destination to be whitelisted address
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Intra-transaction price manipulations can lead to flash loan attacks, theft of f

Implements approach to verify oracle price updates using both pre/post state comparison and intra-transaction inspection:

- `forkPreState()` / `forkPostState()`: Capture oracle price before and after transaction, compare for deviations
- `forkPreTx()` / `forkPostTx()`: Capture oracle price before and after transaction, compare for deviations
- `getCallInputs()`: Monitor all price update function calls within transaction
- `registerCallTrigger()`: Trigger when oracle price update is detected
- Verify each update's price parameter against initial price
Expand Down
8 changes: 4 additions & 4 deletions assertions-book/previous-hacks/bybit-safe-ui.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ a transaction.

PhEvm precompiles used:

- _forkPreState_ allowing to fork the state of the contract before a transaction
- _forkPreTx_ allowing to fork the state of the contract before a transaction
- _load_ reading specific storage slots
- _getStateChangesAddress_ getting all state changes within a transaction for a given slot

Expand All @@ -89,7 +89,7 @@ contract SafeAssertion is Assertion {
}

function implementationAddressChange() external view {
ph.forkPreState();
ph.forkPreTx();
address preImplementationAddress = address(uint160(uint256(ph.load(address(safe), bytes32(0x0)))));

address[] memory addresses = getStateChangesAddress(address(safe), bytes32(0x0));
Expand All @@ -108,14 +108,14 @@ the balance of the whitelisted addresses increased with the respective amount.

```solidity
function assertionSafeDrain() external {
ph.forkPreState();
ph.forkPreTx();
uint256 preBalance = address(bybitSafeAddress).balance;
uint256[] memory preWhitelistBalances = new uint256[](whitelistedAddresses.length);
for (uint256 i = 0; i < whitelistedAddresses.length; i++) {
preWhitelistBalances[i] = address(whitelistedAddresses[i]).balance;
}

ph.forkPostState();
ph.forkPostTx();
uint256 postBalance = address(bybitSafeAddress).balance;
if (postBalance > preBalance) {
return; // Balance increased, not a hack
Expand Down
2 changes: 1 addition & 1 deletion assertions-book/previous-hacks/cream-finance-2.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ function assertion_priceDeviation() public view {
postPrices.push(priceOracle.getPrice(touchedAssets[i]));
}

ph.forkPreState();
ph.forkPreTx();

for (uint256 i = 0; i < touchedAssets.length; i++) {
uint256 prePrice = priceOracle.getPrice(touchedAssets[i]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Assuming we can check run assertions on each call in the transaction and that we

```solidity
function assertionNoUnsafeDebt() external {
ph.forkPostState();
ph.forkPostTx();

// Get all accounts that were modified in this tx
address[] memory accounts = ph.getModifiedAccounts();
Expand Down
4 changes: 2 additions & 2 deletions assertions-book/previous-hacks/gma-aum-jul25-hack.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ function assertSimplifiedAUMBounds() external {
// Core principle: AUM should closely track actual token flows

// 1. Capture AUM before transaction
ph.forkPreState();
ph.forkPreTx();
uint256 aumBefore = getAumInUsdg(true);

// 2. Capture AUM after transaction
ph.forkPostState();
ph.forkPostTx();
uint256 aumAfter = getAumInUsdg(true);

// 3. Calculate AUM change
Expand Down
12 changes: 6 additions & 6 deletions assertions-book/previous-hacks/hack1-radiant-capital.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ contract LendingPoolAddressesProviderAssertions is Assertion {
// return true indicates a valid state -> owner is the same
// return false indicates an invalid state -> owner is different
function assertionOwnerChange() external returns (bool) {
ph.forkPreState();
ph.forkPreTx();
address prevOwner = lendingPoolAddressesProvider.owner();
ph.forkPostState();
ph.forkPostTx();
address newOwner = lendingPoolAddressesProvider.owner();
return prevOwner == newOwner;
}
Expand All @@ -60,9 +60,9 @@ contract LendingPoolAddressesProviderAssertions is Assertion {
// return true indicates a valid state -> emergency admin is the same
// return false indicates an invalid state -> emergency admin is different
function assertionEmergencyAdminChange() external returns (bool) {
ph.forkPreState();
ph.forkPreTx();
address prevEmergencyAdmin = lendingPoolAddressesProvider.getEmergencyAdmin();
ph.forkPostState();
ph.forkPostTx();
address newEmergencyAdmin = lendingPoolAddressesProvider.getEmergencyAdmin();
return prevEmergencyAdmin == newEmergencyAdmin;
}
Expand All @@ -71,9 +71,9 @@ contract LendingPoolAddressesProviderAssertions is Assertion {
// return true indicates a valid state -> pool admin is the same
// return false indicates an invalid state -> pool admin is different
function assertionPoolAdminChange() external returns (bool) {
ph.forkPreState();
ph.forkPreTx();
address prevPoolAdmin = lendingPoolAddressesProvider.getPoolAdmin();
ph.forkPostState();
ph.forkPostTx();
address newPoolAdmin = lendingPoolAddressesProvider.getPoolAdmin();
return prevPoolAdmin == newPoolAdmin;
}
Expand Down
2 changes: 1 addition & 1 deletion assertions-book/previous-hacks/hack2-vestra-dao.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ contract VestraDAOHack is Assertion {

// Check if the user has already unstaked for a maturity
function assertionExample() external {
ph.forkPostState();
ph.forkPostTx();
PhEvm.CallInputs[] memory unStakes = ph.getCallInputs(address(vestraDAO), vestraDAO.unStake.selector);

for (uint256 i = 0; i < unStakes.length; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function assertion_triggerDeposit_remainsSolvent() public view {
uint256 postBalanceCollateral = visr.balanceOf(address(adopter));
uint256 postTotalSupplyRewards = vvisr.totalSupply();
uint256 postRatio = postBalanceCollateral / postTotalSupplyRewards;
ph.forkPreState();
ph.forkPreTx();

uint256 preBalanceCollateral = visr.balanceOf(address(adopter));
uint256 preTotalSupplyRewards = vvisr.totalSupply();
Expand Down
2 changes: 1 addition & 1 deletion credible/architecture-overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ The [Credible Layer Contracts](/credible/credible-layer-contracts) are on-chain
The Credible Layer can be implemented on different networks. The core concepts remain the same, but implementation details vary by network architecture.

For specific implementation details, see:
- [OP Stack Implementation](/credible/architecture-op-stack)
- [OP Stack Implementation](/credible/network-integrations/architecture-op-stack)

---

Expand Down
2 changes: 1 addition & 1 deletion credible/faq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ Our custom block builder enables the sequencer to check each transaction against
This requires no changes to contracts as it is effectively middleware.

**Learn More:**
- [Architecture - OP Stack Implementation](/credible/architecture-op-stack)
- [Architecture - OP Stack Implementation](/credible/network-integrations/architecture-op-stack)
- [Glossary - Block Builder](/credible/glossary#block-builder)

### Can anyone write assertions for my contracts?
Expand Down
8 changes: 4 additions & 4 deletions credible/network-integration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ Networks provide the following integration surfaces:

- The enforcer runs alongside the block builder and does not change consensus rules
- Enforcement is deterministic and only depends on on-chain state and assertion code
- Networks can stage assertion deployments before enforcing them in production
- dApps choose whether assertions are staged or enforced; networks honor the registry status during validation

## Integration Checklist (High Level)

- Identify the block-building hook for transaction validation
- Configure access to registry data and assertion bytecode
- Decide on staging vs production enforcement
- Ensure the enforcer respects staged vs enforced assertions as set by dApps
- Set up monitoring and incident review workflows

## Integration Requirements (Public)
Expand All @@ -64,13 +64,13 @@ Networks provide the following integration surfaces:
<Card title="Architecture Overview" icon="diagram-project" href="/credible/architecture-overview">
Detailed system architecture and transaction flow
</Card>
<Card title="Linea / Besu Integration" icon="plug" href="/credible/architecture-linea">
<Card title="Linea / Besu Integration" icon="plug" href="/credible/network-integrations/architecture-linea">
Plugin-based integration pattern for Besu
</Card>
<Card title="Assertion Enforcer" icon="shield" href="/credible/assertion-enforcer">
Sidecar validation flow and enforcement role
</Card>
<Card title="OP Stack Implementation" icon="sitemap" href="/credible/architecture-op-stack">
<Card title="OP Stack Implementation" icon="sitemap" href="/credible/network-integrations/architecture-op-stack">
OP Stack integration notes
</Card>
</CardGroup>
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,4 @@ flowchart LR
- [Network Integration Overview](/credible/network-integration)
- [Assertion Enforcer](/credible/assertion-enforcer)
- [Assertion DA](/credible/assertion-da)
- [OP Stack](/credible/architecture-op-stack)
- [OP Stack](/credible/network-integrations/architecture-op-stack)
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ For the general integration path, see [Network Integration Overview](/credible/n
</Note>

<Note>
Looking for the Besu/Linea pattern? See [Linea / Besu Integration](/credible/architecture-linea).
Looking for the Besu/Linea pattern? See [Linea / Besu Integration](/credible/network-integrations/architecture-linea).
</Note>

## Architecture Diagram
Expand Down
11 changes: 8 additions & 3 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,14 @@
"group": "Integrations",
"pages": [
"credible/network-integration",
"credible/dapp-integration",
"credible/architecture-linea",
"credible/architecture-op-stack"
{
"group": "Network Implementations",
"pages": [
"credible/network-integrations/architecture-linea",
"credible/network-integrations/architecture-op-stack"
]
},
"credible/dapp-integration"
]
},
{
Expand Down