Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.blend.money/llms.txt

Use this file to discover all available pages before exploring further.

Every transaction through Blend passes through 4 independent security layers before it executes: transaction guards, rate limiting, reentrancy protection, and slippage verification.

Transaction guards

Every Safe has a RolesGuard installed as its transaction guard. The guard runs two pre-execution hooks. checkTransaction fires before any direct transaction. When the system is paused, only Safe owners can execute. Non-owners receive a SystemPaused() revert. checkModuleTransaction fires before any module-initiated transaction. When paused, ALL module transactions are blocked. There is no owner bypass for module calls. This means the automation layer stops completely during a pause, even if the Safe owner tries to trigger it. The pause mechanism is controlled by PAUSER_ROLE via pause(bool _shouldPause). This is a kill switch for the automation layer that does not affect the owner’s ability to withdraw directly.

Rate limiting

Every rebalance and vault action is rate-limited per (safe, vault) pair. The key is keccak256(abi.encodePacked(safe, vault)). MIN_SECONDS_BETWEEN_OPERATIONS is set between 1 and 300 seconds at deployment. The contract enforces strictly-greater-than comparison against the last operation timestamp. The timestamp is set before execution. If the transaction reverts, all state changes (including the timestamp) roll back.
ParameterValue
Rate limit keykeccak256(safe, vault) per pair
Min interval1-300 seconds (set at deployment)
Failure behaviorTimestamp still updates
ScopePer safe/vault pair, not global

Reentrancy protection

The StrategyManager uses separate boolean guards for two execution paths. isRebalanceInitiated is set to true during executeRebalance and checked by downstream contracts. isVaultActionInitiated is set to true during executeVaultAction. These are independent flags, not a shared mutex. This separation matters because vault actions and rebalances call different controller contracts. A rebalance cannot trick a vault action controller into executing, and vice versa.

Slippage protection

Three independent layers protect against unfavorable swaps. Layer 1: Governance maximum. maxSlippageBps is a hard ceiling set by governance. No swap can exceed this tolerance, regardless of what the caller requests. Layer 2: Per-swap limit. Every swap call includes a slippageBps parameter. The SwapAdapter rejects any value exceeding maxSlippageBps. Layer 3: Oracle verification. The SwapAdapter calculates the expected output using PriceLib.quoteToBase (or baseToQuote for reverse swaps) and then applies the slippage tolerance to derive a minimum acceptable output. The actual swap result must meet or exceed this minimum. Beyond the three layers, checkSwapInvariants enforces a zero-balance invariant. The SwapAdapter must hold zero tokens of both the input and output before and after every swap. This prevents residual token accumulation that could be drained.
// Simplified slippage check flow
uint256 expected = PriceLib.quoteToBase(inputAmount, oracle);
uint256 minimum = PriceLib.applySlippage(expected, slippageBps);
require(actualOutput >= minimum, "SlippageExceeded");
MorphoVaultLib adds a fourth check for vault deposits and withdrawals: the assets/shares ratio must stay within bounds of the provided assetPerShare parameter.

Access control

Multiple layers restrict who can call what. onlyExecutor - StrategyManager.executeRebalance and executeVaultAction are restricted to a single authorized executor address. This is the off-chain worker that triggers operations. _onlyDelegateCall - All VaultControllers, including UserWithdrawController, compare address(this) against an immutable SELF address. This ensures the code only runs via delegatecall from a Safe, never as a standalone call. Trusted broadcaster and chain - RolesReceiver validates both the broadcaster address AND the source chain ID on every cross-chain message. Both are immutable, set at construction. setPeer() always reverts. An attacker would need to compromise LayerZero AND match both trust anchors. Temporal access - WhitelistedSwapAdapter only allows swaps during active isRebalanceInitiated() or isVaultActionInitiated() execution windows. Outside those windows, swap calls revert. Single-owner validation - UserWithdrawController requires the Safe to have exactly one owner. This resolves the withdrawal recipient on-chain without relying on off-chain input.

OFAC screening

Blend screens wallet addresses at three stages before any funds move.
StageWhenWhat happens
Account resolutionGET /account or SIWE verifyEOA screened against Chainalysis API
Deposit quotequoteDepositDeposit EOA screened separately
Account-scoped routesEvery authenticated requestAccount OFAC flag checked
The screening uses the Chainalysis sanctions API with a Redis-backed cache. Cache misses fall back to the database or a fresh Chainalysis screen. If the Chainalysis API is unreachable, the check fails closed (blocks the request with 503).
OFAC screening is a legal compliance requirement. It cannot be bypassed or disabled.

Haltable operations

The API supports a per-account-type halt state. When isHalted is true, the API returns HTTP 423 Locked for deposit-related operations. Withdrawals are intentionally allowed during halt. Users can always retrieve their funds, even when the system is in a degraded state.
OperationDuring halt
Deposit quotesBlocked (423)
Deposit session lock/submitBlocked (423)
WithdrawalsAllowed
Balance and discoveryAllowed
Withdrawal quotesAllowed
Balance queriesAllowed
DiscoveryAllowed
The halt flag is set at the account type level, not globally. One neobank’s account type can be halted while others continue operating.

Architecture overview

See how Safe isolation and cross-chain coordination work.

Contracts

Explore the 9 contract systems powering the protocol.

Security model

Understand the defense-in-depth model and real-world scenarios.

Audits

Review independent security audit reports.
Last modified on May 7, 2026