# Contract Addresses
Source: https://docs.monolith.market/developers/contract-addresses
Deployed Monolith contract addresses
Monolith consists of a small set of singleton contracts per chain, plus per-instance `Lender`, `Coin`, and `Vault` contracts deployed by the `Factory`.
## Singletons
### Ethereum Mainnet
| Contract | Address |
| -------- | ----------------------------------------------------------------------------------------------------------------------- |
| Factory | [`0x6D961c9DCF1AD73566822BA4B087892e3839B849`](https://etherscan.io/address/0x6D961c9DCF1AD73566822BA4B087892e3839B849) |
| Lens | [`0x8aAb59675e123cEEFE5E05B0BC1bE8fe6101E60d`](https://etherscan.io/address/0x8aAb59675e123cEEFE5E05B0BC1bE8fe6101E60d) |
| Metadata | [`0x2Afb125bB848049b54D0903A1fd365E7518f581A`](https://etherscan.io/address/0x2Afb125bB848049b54D0903A1fd365E7518f581A) |
### Sepolia Testnet
| Contract | Address |
| -------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Factory | [`0x365009FA2Ddb17f386E20854E4B281827619E4D2`](https://sepolia.etherscan.io/address/0x365009FA2Ddb17f386E20854E4B281827619E4D2) |
| Lens | [`0x82342771D91a4DAA9947419D1e0F95Fe7E3d2a22`](https://sepolia.etherscan.io/address/0x82342771D91a4DAA9947419D1e0F95Fe7E3d2a22) |
| Metadata | [`0x8aAb59675e123cEEFE5E05B0BC1bE8fe6101E60d`](https://sepolia.etherscan.io/address/0x8aAb59675e123cEEFE5E05B0BC1bE8fe6101E60d) |
## Discovering per-instance contracts
Each stablecoin instance consists of three contracts deployed by `Factory.deploy(DeployParams)`:
* **Lender** — core lending contract for the instance
* **Coin** — ERC‑20 stablecoin for the instance
* **Vault** — ERC‑4626 staked vault for the instance
Enumerate existing instances by reading the Factory:
```solidity theme={null}
uint256 count = factory.deploymentsLength();
address lender = factory.deployments(i); // i < count
address coin = address(Lender(lender).coin());
address vault = address(Lender(lender).vault());
```
Or index the `Deployed(address indexed lender, address indexed coin, address indexed vault)` event emitted by the Factory on each `deploy()` call.
## Interest model
A single `InterestModel` instance is deployed per chain by the `Factory` constructor. Read its address from the Factory:
```solidity theme={null}
address interestModel = factory.interestModel();
```
## Source code
All contracts are open source at [github.com/MonolithMarket/Monolith](https://github.com/MonolithMarket/Monolith).
# Integration Guide
Source: https://docs.monolith.market/developers/integration-guide
How to integrate with Monolith contracts from Solidity and JavaScript
## Overview
Monolith is a permissionless stablecoin factory. There is no off-chain API, SDK, or indexer — all interactions go through on-chain contracts. This guide shows the core flows.
Before reading, make sure you have the [contract addresses](/developers/contract-addresses) for your chain.
## Core contracts
| Contract | Role |
| ---------- | -------------------------------------------------------- |
| `Factory` | Deploys new instances; manages protocol fees |
| `Lender` | Per-instance core: borrow, repay, liquidate, redeem, PSM |
| `Coin` | Per-instance ERC‑20 stablecoin |
| `Vault` | Per-instance ERC‑4626 staked vault (yield-bearing) |
| `Lens` | Read-only helpers (preview redeem, synced debt) |
| `Metadata` | Per-Lender branding (URLs, logos, description) |
## Deploying a new instance
`Factory.deploy(DeployParams)` creates a `Lender`, `Coin`, and `Vault` in a single transaction and returns their addresses.
```solidity theme={null}
interface IFactory {
struct DeployParams {
string name;
string symbol;
address collateral;
address psmAsset; // address(0) to disable PSM
address psmVault; // address(0) or ERC4626
address feed; // Chainlink-style
uint256 collateralFactor; // max 8500 (85%)
uint256 minDebt; // must be >= factory.minDebtFloor()
uint256 timeUntilImmutability; // seconds, max 1460 days (~4 years)
address operator;
address manager;
uint64 halfLife; // 12 hours .. 30 days
uint16 targetFreeDebtRatioStartBps; // >= 500, <= end
uint16 targetFreeDebtRatioEndBps; // <= 9500
uint16 redeemFeeBps; // <= 500 (5%)
uint32 stalenessThreshold; // oracle max staleness (seconds)
uint16 maxBorrowDeltaBps; // 50..200
uint128 psmVaultMinTotalSupply; // required if psmVault != 0
}
function deploy(DeployParams memory params) external returns (address lender, address coin, address vault);
}
```
See [Stablecoin Factory](/protocol/stablecoin-factory) for parameter guidance.
## Borrowing and managing a position
`Lender.adjust` is the single entry point for all position changes: deposit/withdraw collateral, borrow/repay debt, switch between paid and free (redeemable) debt modes.
```solidity theme={null}
interface ILender {
// collateralDelta and debtDelta are signed: positive = deposit/borrow, negative = withdraw/repay.
function adjust(
address account,
int256 collateralDelta,
int256 debtDelta,
bool chooseRedeemable
) external;
// Overload without the status flag (keeps current setting).
function adjust(
address account,
int256 collateralDelta,
int256 debtDelta
) external;
}
```
Example — deposit 1 WETH and borrow 1,000 Coin in paid-debt mode:
```solidity theme={null}
IERC20(weth).approve(lender, 1 ether);
ILender(lender).adjust(msg.sender, int256(1 ether), int256(1_000e18), false);
```
Example — repay all debt and withdraw all collateral:
```solidity theme={null}
uint256 debt = ILender(lender).getDebtOf(msg.sender);
uint256 collateral = ILender(lender).collateralBalances(msg.sender);
IERC20(coin).approve(lender, debt);
ILender(lender).adjust(msg.sender, -int256(collateral), -int256(debt), false);
```
Delegation (`lender.delegate(address, bool)`) lets another address manage the position on the owner's behalf.
## Staking the Coin
`Vault` is a standard ERC‑4626. Yield comes from interest paid by borrowers in paid-debt mode.
```solidity theme={null}
// Stake
IERC20(coin).approve(vault, amount);
uint256 shares = IERC4626(vault).deposit(amount, msg.sender);
// Unstake
uint256 assets = IERC4626(vault).redeem(shares, msg.sender, msg.sender);
```
Note: the first depositor burns `1e16` shares (`MIN_SHARES`) to prevent the ERC‑4626 inflation attack.
## Redemption (arbitrage)
Anyone can redeem `Coin` for a redeemable borrower's collateral at oracle price minus `redeemFeeBps`.
```solidity theme={null}
interface ILender {
function redeem(address borrower, uint amountIn, uint minAmountOut)
external returns (uint amountOut);
}
```
Preview the outcome off-chain via `Lens` (simulates without mutating state):
```solidity theme={null}
interface ILens {
function previewRedeem(address lender, address borrower, uint256 amountIn)
external view returns (uint256 coinIn, uint256 amountOut);
}
```
See [Redemptions](/protocol/redemptions) for the mechanism.
## PSM (if enabled on the instance)
If `psmAsset` was configured at deployment, anyone can convert between `Coin` and the PSM asset at 1:1 (decimals-adjusted).
```solidity theme={null}
interface ILender {
function sell(uint coinIn, uint minAssetOut) external returns (uint assetOut); // no fee
function buy (uint assetIn, uint minCoinOut) external returns (uint coinOut); // pre-deadline, small ramping fee
}
```
## Querying state
`Lender` exposes direct getters; `Lens` provides a version that simulates accrual before reading.
```solidity theme={null}
// Already-accrued debt (from Lender)
uint256 debt = ILender(lender).getDebtOf(account);
// Debt including pending interest (from Lens)
uint256 syncedDebt = ILens(lens).getDebtOf(lender, account);
// Oracle state
(uint price, bool reduceOnly, bool allowLiquidations) = ILender(lender).getCollateralPrice();
```
## Liquidating a position
```solidity theme={null}
interface ILender {
function liquidate(address borrower, uint repayAmount, uint minCollateralOut)
external returns (uint collateralOut);
}
```
Up to 25% of a position's debt (or the full position if smaller) can be liquidated per call, with a minimum chunk of `10_000e18`. Incentive scales from 0% at the collateral factor up to 10% at `collateralFactor + 500 bps`. See [Liquidations](/protocol/liquidations).
## Events to index
Factory:
* `Deployed(address indexed lender, address indexed coin, address indexed vault)`
Per Lender (subset most integrators care about):
* `PositionAdjusted(address indexed account, int collateralDelta, int debtDelta)`
* `RedemptionStatusUpdated(address indexed account, bool isRedeemable)`
* `Liquidated(address indexed borrower, address indexed liquidator, uint repayAmount, uint collateralOut)`
* `Redeemed(address indexed account, address indexed borrower, uint amountIn, uint amountOut)`
* `Sold(address indexed account, uint coinIn, uint assetOut)`
* `Bought(address indexed account, uint assetIn, uint coinOut)`
* `WrittenOff(address indexed borrower, address indexed to, uint debt, uint collateral)`
See the [Lender reference](/reference/Lender) for the full list.
## JavaScript example (ethers v6)
```javascript theme={null}
import { ethers } from "ethers";
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const lender = new ethers.Contract(lenderAddress, lenderAbi, signer);
const coin = new ethers.Contract(coinAddress, erc20Abi, signer);
// Deposit 1 WETH, borrow 1000 Coin, paid-debt mode
await (await weth.approve(lenderAddress, ethers.parseEther("1"))).wait();
await (await lender.adjust(
await signer.getAddress(),
ethers.parseEther("1"), // +1 WETH
ethers.parseUnits("1000", 18), // +1000 Coin debt
false, // chooseRedeemable = false (paid debt)
)).wait();
```
## Source
ABIs and Solidity sources: [github.com/MonolithMarket/Monolith](https://github.com/MonolithMarket/Monolith).
# Overview
Source: https://docs.monolith.market/developers/overview
Technical documentation, contract addresses, and integration guides for developers
Access contract addresses, integration guides, and technical documentation for building on Monolith.
## Developers
Find deployed contract addresses across all supported networks.
Step-by-step guide for integrating Monolith stablecoins into your application.
# Borrower FAQ
Source: https://docs.monolith.market/faq/borrower
Frequently asked questions for borrowers
# Borrower FAQ
Choose free debt if you want 0% interest and accept that redemptions can seize collateral while repaying your debt. Choose paid debt if you prefer stable ownership of collateral (no redemptions) and are comfortable paying interest.
Redemptions reduce your computed debt and seize collateral pro‑rata based on your free‑debt shares. They are not always lossy but can cause you to actively rebalance your position.
Yes. You can migrate between the two modes at any time.
When your loan becomes unsafe (debt exceeds borrowing power), anyone can repay part of your debt in Coin and seize collateral of the same value with a small, LTV‑dependent incentive.
A last‑resort path for irrecoverable positions: if your debt exceeds the value of your collateral, the protocol can wipe your remaining debt, redistribute it proportionally across all borrowers, and transfer your remaining collateral to the caller. It can happen at the end of liquidations and can be called directly. The purpose of write offs is to socialize losses among borrowers to ensure the system stays solvent.
Each call can liquidate up to 25% of total debt, with a 10,000 Coin minimum chunk (or the entire debt if smaller).
The additional incentive you pay to liquidators from your collateral scales with how far a position exceeds the collateral factor: 0% at the collateral factor, linearly up to 10% when loan‑to‑value is 5 percentage points above it. This design minimizes the liquidation penalty as much as possible.
Paid debt incurs variable interest; free debt has no interest. If you use the PSM for swapping when borrowing or repaying, you may pay a PSM swap fee.
If you change your debt, the result must be either 0 or ≥ `minDebt`. Partial repays that would leave debt below `minDebt` while non‑zero are not allowed; fully repay or leave at least `minDebt` outstanding.
You can authorize addresses to manage your position. Delegates can borrow, withdraw collateral and toggle redemption status on your behalf; you can grant multiple delegates and revoke at any time.
No. Collateral stays in the instance. It can be seized only via redemptions (if you opt into free debt) or liquidations/write‑offs (if unsafe). It is never lent out or reused elsewhere by the protocol.
# Deployer FAQ
Source: https://docs.monolith.market/faq/deployer
Frequently asked questions for instance deployers
# Deployer FAQ
It sets the immutability deadline offset from deployment. Before the deadline, you can tune half‑life, target free‑debt band, redeem fee and interest fee. After the deadline, these lock permanently. Setting it to 0 enables immediate immutability.
Required: `name`, `symbol`, `collateral`, `feed`, `collateralFactor`, `minDebt`, `timeUntilImmutability`. Optional: `psmAsset`, `psmVault`, `operator`, `manager` (use `address(0)` to omit operator/manager).
PSM provides direct Coin↔asset convertibility and can harvest vault yield, but increases exposure to the reference asset. If you want a pure collateral‑anchored design, skip PSM; if you want immediate exit liquidity and cushion for the peg, enable it.
Choose factors in bps based on collateral volatility and liquidity. Higher factor increases borrow power but tightens liquidation buffers. `minDebt` should avoid dust accounts while not blocking legitimate use.
The Factory operator sets a global fee (bps) capped at 10% and per‑instance overrides. Global reserves accrue at the Lender and are pulled by the Factory’s `feeRecipient`. Local reserves accrue to the instance and are pullable by the instance operator.
Yes. The Factory uses two‑step operator transfer (`setPendingOperator`/`acceptOperator`). Each Lender supports operator/manager rotation; some actions require operator or operator/manager and must happen before the immutability deadline.
The operator has broader authority: can set/revoke pending operator, set local reserve fee bps, pull local reserves, and perform all pre‑deadline parameter updates that the manager can. The manager is a secondary role that can adjust a subset of parameters (e.g., half‑life, target free‑debt ratio, redeem fee) before immutability but cannot pull reserves or change roles.
# General FAQ
Source: https://docs.monolith.market/faq/general
Frequently asked questions about Monolith
# General FAQ
Monolith is built by the creators of Inverse.Finance DAO, DOLA stablecoin and FiRM fixed rate lending protocol.
It uses borrower choices as an indirect oracle. The share of free (redeemable) debt signals perceived redemption risk: too low → rates rise; too high → rates decay toward a floor. Combined with redemptions and the PSM, this self-correcting loop nudges price back toward \$1.
They serve different user preferences and protocol needs. Paid debt funds staking yield and insulates collateral from redemptions; free debt pays 0% interest but is eligible for redemptions, forming an opt-in exit buffer that supports peg stability.
The protocol switches to reduce-only mode and disables liquidations/redemptions/write-offs until fresh data arrives. This prevents mispriced liquidations and redemptions while still allowing users to deleverage and exit safely.
Each instance has an immutability deadline. Before it, operators can tune select parameters. After it, sensitive controls permanently lock; only non-sensitive fee pulls/roles remain. This creates credibly neutral, governance-minimized instances.
Redemptions swap Coin for collateral from free-debt borrowers; the PSM swaps Coin for a reference asset. Redemptions always exist when free debt/collateral is available; PSM buys are disabled after immutability to cap exposure.
Most borrow interest is earned by Vault stakers after taking operator and global protocol fee.
# Holder & Staker FAQ
Source: https://docs.monolith.market/faq/holder-staker
Frequently asked questions for Coin holders and Vault stakers
# Holder & Staker FAQ
Two paths: redemptions (Coin → collateral from free‑debt pool) and the PSM (Coin → reference asset, if enabled). Redemptions always depend on free debt and redeemable collateral; PSM sells depend on on‑hand asset liquidity.
Paid borrowers’ interest (after protocol/local fees) is minted as Coin to the Vault.
No. The Vault simply holds Coin and reflects interest minted to it.
No. Monolith is intentionally partially redeemable: only free‑debt collateral is used for redemptions. If free‑debt capacity or redeemable collateral is scarce, redemptions may be limited until borrowers migrate to free debt or the controller nudges the system back into balance. The PSM (if enabled) offers an additional convertibility path.
First, unsafe loans are liquidated in bounded chunks with an incentive, restoring solvency. If a position becomes irrecoverable, a write‑off socializes the loss across all borrowers.
Three layers: (1) Redemptions convert Coin → collateral from free‑debt borrowers at the oracle price minus a small fee (2) the interest controller adjusts borrow rates using the free‑debt ratio as an indirect price oracle (thin buffer → higher rates; ample buffer → lower rates) (3) the PSM (if enabled) adds direct Coin ↔ reference‑asset convertibility. Arbitrage across these keeps price near \$1.
No. Coin is a minimal ERC‑20 minted/burned by the Lender. There is no pause, blacklist, or upgrade hook in any Monolith contracts.
Each instance issues its own Coin backed by its chosen collateral, oracle, parameters (collateral factor, minDebt, fees, target band), and optional PSM setup. Risk/behavior can differ; always review the instance’s parameters before holding or staking.
# Introduction
Source: https://docs.monolith.market/index
Welcome to Monolith — The Decentralized Stablecoin-as-a-Service Protocol
Monolith allows anyone to deploy their own decentralized crypto-backed stablecoin
## How it works
* The Monolith Factory allows anyone to deploy an **immutable stablecoin** by providing a collateral token address and a price feed.
* Borrowers can mint Monolith stablecoins by choosing between two modes: a **0% borrow rate** loan but be subject to redemptions OR a variable rate loan and be **protected from redemptions**.
* The protocol adjusts the variable borrow rate to protect the peg. This is possible thanks to the first fully **autonomous interest rate controller** in a stablecoin.
* Each Monolith stablecoin includes a **staking vault** (sToken) that pays holders from the interest generated by borrowers.
* Each Monolith stablecoin becomes irreversibly immutable when reaching a maximum **immutability deadline** of four years since deployment.
## Under the hood
Dive deeper into the technical aspects and advanced features of Monolith:
Understand the core mechanics of stablecoin creation, debt management, and protocol economics.
Review our security audits, bug bounty program, and risk disclosures.
Access contract addresses, integration guides, and technical documentation.
Complete API reference for all Monolith smart contracts with detailed function specifications.
## Join the Community
Like what you see? Join the Monolith community to stay updated and ask questions:
Join our community discussions, get help, and stay updated with the latest developments.
Follow us for announcements, updates, and insights into the world of Monolith stablecoins.
# Why Monolith
Source: https://docs.monolith.market/overview/why-monolith
Understanding the problems Monolith solves and what makes it different
## Problems
* **Stablecoins are getting worse**: Stablecoins have deviated from the ethos of Ethereum: permissionlessness, censorship resistance, transparency and trustlessness. Monolith is designed in the image of Ethereum.
* **Stablecoins are hard**: Deploying a stablecoin should be as simple as deploying a Uniswap pair or Morpho pool.
* **Stablecoins are risky**: Stablecoins have become too risky: custodian risk, freezing risk, bank insolvency risk, governance risk. An ultra low-risk alternative is needed.
## Why Monolith is different
Permissionless Deployment
Anyone can deploy a Monolith stablecoin on any supported chain without permission in few minutes.
Redeemable
All Monolith stablecoins are redeemable for their underlying collateral.
Redemption Protection
Borrowers may avoid redemptions by paying a variable borrow rate.
Interest-Free Loans
Borrowers may avoid paying interest by allowing their loans to be redeemed.
Peg Stability Module
A temporary PSM may use an existing stablecoin to bootstrap supply.
Immutability deadline
All Monolith stablecoins either start immutable or become immutable within four years.
## Our Vision
Monolith aims to democratize access to decentralized stablecoins:
* **Low barrier to entry**: A user-friendly interface for creating a stablecoin in minutes.
* **Sound Economics**: A carefully-designed stablecoin protocol that maintains the peg no matter what.
* **Discoverability**: A list of user-created stablecoins for lenders and borrowers to find new opportunities.
* **Immutability**: Stability requires certainty. Immutability protects stablecoin users from human mistakes.
# Bad Debt Socialization
Source: https://docs.monolith.market/protocol/bad-debt-socialization
How irrecoverable losses are redistributed across borrowers when a loan is written off
# Bad Debt Socialization
## Overview
When a borrower’s position becomes undercollateralized, fully recovering the debt via normal liquidations may be impossible. In that rare case, the protocol “writes off” the position and socializes the loss across all remaining borrowers of the instance in order to prevent a bank run among `Coin` holders.
Write‑offs are guarded by strict conditions and are typically invoked automatically at the end of a liquidation. They may also be executed independent of liquidations via the `writeOff()` function.
## Mechanism
Bad debt identification and handling are governed by the `writeOff(borrower, to)` flow:
* Accrue and sync: Interest is accrued and the borrower’s internal accounting is synchronized.
* Price gate: The oracle must report a valid, sufficiently fresh price; otherwise socialization is disabled.
* Write off threshold: If `debt > 100 × collateralValue` at the oracle price, the collateral value is considered negligible and the position qualifies for write‑off.
* Three actions then occur atomically:
1. Delete borrower debt: The borrower’s entire outstanding debt is wiped.
2. Redistribute the wiped debt: The same amount of debt is added back to the system by increasing total free and total paid debt in proportion to their current sizes.
3. Transfer residual collateral: All of the borrower’s remaining collateral is sent to `to` (the liquidator/caller), and the borrower’s collateral balance is set to zero.
This function is called from liquidations via a safe external call (try/catch) so that liquidation success is not jeopardized if the write‑off preconditions are not met.
## Impact
Effects by stakeholder:
* Remaining borrowers (free and paid): Their total pool debt increases while their individual shares remain unchanged, so their computed debts rise proportionally. This fairly spreads the loss across active borrowers.
* Liquidator/caller: Receives the borrower’s remaining collateral as compensation for calling the `writeOff()` function.
* `Coin` holders/stakers: Re-collateralizes their holdings using collateral of other borrowers and avoids bank runs.
## Prevention
Preventing bad debt write‑offs starts with prudent instance configuration and healthy market structure:
* Conservative collateral factors and robust oracles limit the chance of undercollateralization.
* Timely liquidations reduce drift into the write‑off zone.
* The immutability deadline locks sensitive parameters after launch, removing configuration risk over time.
Related:
* [Liquidations](/protocol/liquidations)
* [Paid vs Free Debt](/protocol/paid-vs-free-debt)
# Immutability Deadline
Source: https://docs.monolith.market/protocol/immutability-deadline
Time‑locked switch that permanently disables sensitive controls, making an instance credibly neutral after launch.
# Immutability Deadline
## Overview
Each instance has an immutability deadline: a timestamp after which sensitive parameters and admin actions permanently lock. This turns the instance into a credibly‑neutral system with no ongoing configuration powers over protocol behavior.
## Why it exists
* Early flexibility: Gives operators the ability to finetune parameters after launch.
* Predictability: Once locked, users can rest assured that the rules will never change.
* Safety: Eliminates the possibility of human error, building Lindiness over time.
## How it’s set
* On deployment, the deadline is set to `deployTimestamp + timeUntilImmutability`.
* `timeUntilImmutability` is bounded (at most 4 years) and can be `0` for immediate immutability at launch.
* Before the deadline, the operator may call an early lock by calling `enableImmutabilityNow()` (irreversible, cannot be delayed or reopened later).
## What the deadline locks
After the deadline passes (or is enabled early), the following become permanently unavailable:
* Interest policy knobs:
* Half‑life of rate changes (exponential rate)
* Target free‑debt ratio band
* Redemption fee basis points
* PSM‑related mutability:
* The buy path (asset→coin) through the PSM wrapper
These gates ensure the instance’s monetary policy surface cannot be altered after the lock, and that exposure to the PSM asset can no longer increase.
## What remains adjustable (intentionally)
Only fee-related actions remain accessible by the operator:
* Operator/manager rotation
* Local reserve fee bps for the instance operator (bounded by a 10% cap)
* Pulling the instance operator fee
## Related
* [Interest Rate Controller](/protocol/interest-rate-controller)
* [Paid vs Free Debt](/protocol/paid-vs-free-debt)
# Interest Rate Controller
Source: https://docs.monolith.market/protocol/interest-rate-controller
How interest rates are determined and controlled
# Interest Rate Controller
## Overview
The Interest Rate Controller sets the borrow rate for each instance to keep the system balanced and liquid. It is designed to be:
* Predictable: changes follow smooth, time‑based curves rather than step functions.
* Objective: driven by a single measurable signal — the share of free (redeemable) debt in the system.
* Resilient: implemented as a shared, minimal, non‑upgradeable, external math contract with a failsafe in case of unexpected reverts.
## Why it exists (and what’s unique)
* Ensures exit liquidity: By targeting a healthy share of free debt, the controller helps keep redemption capacity available without constant governance.
* Enforces peg stability: The controller infers the market condition of the stablecoin through borrower choice and uses this signal to steer the peg to \$1.
* Aligns incentives: When free‑debt share is scarce, rates rise to encourage migration to free debt (or repayment). When it’s abundant, rates decay toward a low floor to make paid borrowing attractive again.
* Smooth policy, minimal complexity: Adjustments are exponential over time with an explicit floor, avoiding volatile jumps.
## How it works (high‑level)
* The controller observes the system’s free‑debt ratio `f` and compares it to a target band `[f_start, f_end]`.
* If `f < f_start`: the borrow rate increases over time (borrowers mostly choose paid; perceived redemption risk high; price likely ≤ \$1).
* If `f > f_end`: the borrow rate decays over time toward a minimum floor (borrowers mostly choose free; perceived redemption risk low; price likely ≥ \$1).
* If `f` is inside the band: the borrow rate remains constant (price near \$1).
This feedback loop lets borrowers’ mode choices (paid vs free) collectively steer the system toward a stable equilibrium while preserving exit liquidity and peg health.
## Peg maintenance (over/under/at‑peg signals)
* The controller does not read secondary‑market prices. Instead, it treats borrower mode choices as a crowd‑sourced “indirect oracle”: the resulting free‑debt ratio `f` reflects perceived redemption risk (and thus peg pressure) in a robust, manipulation‑resistant way.
* Interpreting `f` relative to the target band:
* `f < f_start` (too little redeemable collateral): most borrowers are choosing paid debt, which we treat as an indirect signal that perceived redemption risk is high. That typically corresponds to price pressure at or below \$1 where an arbitrage opportunity opens up between redemptions and the secondary market. The controller raises the borrow rate to discourage paid borrowing and encourage migration to free debt, expanding redeemability and helping lift the price toward \$1.
* `f > f_end` (abundant redeemable collateral): most borrowers are choosing free debt, signaling perceived redemption risk is low. That typically corresponds to price pressure at or above \$1 where there is no arbitrage opportunity between redemptions and the secondary market. The controller lets the rate drift toward a floor, making paid borrowing cheaper and drawing borrowers back to paid, while incentivizing new paid borrowers to come in and increase total supply.
* `f_start <= f <= f_end`: choices are mixed, signaling moderate perceived redemption risk. The coin is likely near \$1; the rate holds steady while redemptions and market participants keep the peg tight.
* Combined with redemptions (direct \$1 exits), this creates a self‑correcting system that keeps the stablecoin near its peg without constant governance or external market information.
## Under the hood: math (from InterestModel.sol)
Let:
* `r_old`: previous borrow rate (mantissa)
* `dt`: time elapsed
* `k`: exponential rate constant (`expRate`)
* `g = exp(-k * dt)`: exponential growth/decay factor
* `D`: total paid debt (principal that accrues interest)
Case 1 — Below target (increase):
* `r_new = r_old / g = r_old * exp(k * dt)`
* `I = D * (r_new - r_old) / (k * 365 days)`
Case 2 — Above target (decay toward a floor):
* `r_new = max(r_old * g, r_min)`
If the decay crosses the floor during `dt`, interest integrates piece‑wise: an exponential segment down to `r_min`, then a flat segment at `r_min`:
* `t_min = -ln(r_min / r_old) / k`
* `I = D * ((r_old - r_min) / k + r_min * (dt - t_min)) / (365 days)`
If the floor is not reached within `dt`:
* `I = D * (r_old - r_new) / (k * 365 days)`
Case 3 — Inside the band (hold):
* `r_new = r_old`
* `I = D * r_old * dt / (365 days)`
Notes:
* The implementation uses a single function `calculateInterest(...)` to return `r_new` and the interest `I` given `D, r_old, dt, k, f, f_start, f_end`.
* A minimum rate `r_min` prevents rates from decaying below a fixed floor (0.5% APR).
* The calculation is called externally from each `Lender` with try/catch, so if anything ever failed, accrual would safely skip instead of freezing funds.
## Inputs and outputs
Inputs per accrual step:
* `totalPaidDebt` (`D`)
* `lastBorrowRateMantissa` (`r_old`)
* `timeElapsed` (`dt`)
* `expRate` (`k`)
* `lastFreeDebtRatioBps` (`f`)
* `targetFreeDebtRatioStartBps`, `targetFreeDebtRatioEndBps` (band `[f_start, f_end]`)
Outputs:
* `currBorrowRate` (`r_new`)
* `interest` (`I`) accumulated over `dt`
See also: [InterestModel contract reference](/reference/InterestModel)
## Related
* [Paid vs Free Debt](/protocol/paid-vs-free-debt)
* [Redemptions](/protocol/redemptions)
# Liquidations
Source: https://docs.monolith.market/protocol/liquidations
How unhealthy positions are force-repaid
# Liquidations
## Overview
Liquidations close unsafe positions when a borrower’s debt exceeds their borrowing power at the current oracle price. Anyone can repay part of an unsafe borrower’s debt in `Coin` and seize collateral with a variable incentive. This keeps solvency intact and prevents bad debt.
## Triggers
Liquidations are enabled only when a valid, sufficiently fresh oracle price is available. A position becomes liquidatable when:
* Borrowing power \< debt at the current price, where borrowing power = price × collateral × collateralFactor.
* When liquidations are enabled. Liquidations are disabled when no valid price is provided by the feed.
## Process
High‑level flow (per `liquidate(borrower, repayAmount, minCollateralOut)`):
1. Accrue interest and update borrower’s internal accounting.
2. Read oracle price; require liquidations to be allowed.
3. Compute the maximum chunk that can be liquidated now:
* If the position is healthy, liquidation is not allowed.
* If unhealthy, the protocol allows liquidating up to 25% of the borrower's debt, but at least a minimum chunk size (10,000 `Coin`) when applicable.
4. Reduce the borrower’s debt by `repayAmount`.
5. Compute the liquidator’s collateral reward at the current price with an incentive (see Incentives below).
6. Cap the reward by the borrower’s remaining collateral and enforce `minCollateralOut` (slippage protection for the liquidator).
7. Transfer collateral to the liquidator; pull `repayAmount` of `Coin` from the liquidator and burn it.
8. If the position is undercollateralized, the protocol attempts a write‑off: delete remaining debt, redistribute it across the system’s borrowers, and hand the borrower’s remaining collateral to the liquidator.
## Incentives
The liquidation incentive scales with how far the position is beyond the collateral factor:
* 0% incentive when loan‑to‑value (LTV) is at or below the collateral factor.
* Up to 10% when LTV is 5 percentage points above the collateral factor.
* Linear between those points.
Collateral reward calculation (conceptually):
* collateralReward = repayAmount × (1 + incentiveBps/10,000) ÷ price
* Reward is capped so it cannot exceed the borrower’s available collateral.
This design pays more to liquidators as positions drift further into unsafe territory, incentivizing liquidators while minimizing loss to borrowers.
## Limits and safety valves
* Chunked liquidations: At most \~25% of a borrower’s debt can be liquidated per call (subject to the 10,000 `Coin` minimum). This ensures that the liquidation incentive is sufficient to attract liquidators.
* Oracle‑gated: If the oracle is stale/invalid, liquidations are temporarily disabled to avoid mispricing.
* Write‑off path: If a position is effectively irrecoverable (debt > 100× collateral value), remaining debt can be redistributed among borrowers, and the liquidator receives the borrower’s remaining collateral (negligible).
## Example
* Suppose a borrower has debt of 200,000 `Coin`, collateral value of 230,000 at the oracle price, and a collateral factor of 80% (borrowing power = 184,000). The position is undercollateralized (200,000 > 184,000).
* Maximum liquidatable chunk is 25% of debt = 50,000 `Coin` (greater than the 10,000 minimum).
* If the incentive computes to 8%, and the price implies 1 `Coin` buys \$1 of collateral value, then the liquidator who repays 50,000 `Coin` receives collateral worth 54,000 in value (capped by what’s available), transferred at the oracle price.
# Overview
Source: https://docs.monolith.market/protocol/overview
Deep dive into Monolith protocol mechanics, economics, and technical specifications
## Core Concepts
Learn how anyone can deploy their own decentralized stablecoin using the Monolith Factory.
Understand the autonomous interest rate system that protects peg stability.
Discover automated market operations that maintain stablecoin peg stability.
Learn about the redemption mechanism and its role in maintaining peg stability.
## Debt Management
Compare the two borrowing modes: 0% interest loans vs variable rate loans.
Understand how the protocol handles bad debt through socialization mechanisms.
Learn about liquidation processes and incentives for maintaining protocol solvency.
Discover the four-year immutability deadline that makes stablecoins permanently immutable.
# Paid vs Free Debt
Source: https://docs.monolith.market/protocol/paid-vs-free-debt
Understanding the difference between paid (non-redeemable) and free (redeemable) debt positions.
# Overview
Monolith offers borrowers two borrowing modes that behave differently under interest accrual and redemptions:
* **Paid debt**: interest‑paying borrowing that funds yield to stakers while being exempt from redemptions.
* **Free debt**: non‑interest‑paying borrowing that is eligible to be repaid by external redemptions, with collateral seized according to oracle price plus a fee.
Both modes use the same collateralization and solvency rules; the choice primarily affects eligibility for redemptions and the cost of the loan (interest rate).
# Paid Debt
## Characteristics
* Accrues interest continuously on the outstanding debt.
* Interest paid by borrowers funds staking yield minted to the instance `Vault`, after fees.
* Collateral is protected from third-party redemptions.
## When to choose paid debt
* You prefer predictable ownership of your collateral (not subject to redemptions).
* You are comfortable paying interest in exchange for stability of your collateral and debt.
* You are a passive borrower who prefers not to actively manage and rebalance their position.
# Free Debt
## Characteristics
* Does not accrue interest; your loan is always free.
* Your position becomes “redeemable”: external users can redeem `Coin` for collateral from your position at the oracle price + a fee, with the paid amount reducing your debt.
* When targeted by a redemption:
* Your debt will fall
* An equivalent value of collateral (minus a small redemption fee kept by you) is seized from you and sent to the redeemer.
## When to choose free debt
* You optimize for cost of capital and want zero interest accrual at the cost of more active management.
* You accept that part of your collateral can be redeemed away as your debt is repaid by the third-parties.
* You want to support redemption‑driven peg stability and potentially profit from redempmtion fees.
* You want your debt to decrease automatically during periods of active redemptions.
# Switching between modes
* You can toggle between paid and free debt at any time by switching your “redeemable” status.
* You may also specify a delegate address that may toggle modes on your behalf. Be careful because your delegate also has access to your collateral and may borrow on your behalf.
# Interest and fees at a glance
* Paid debt funds staking yield: Interest is periodically converted into newly minted `Coin` credited to the instance `Vault` (stakers), after deducting protocol and local reserve fees.
* Free debt pays no interest; instead, redemptions repay free debt and seize collateral value from redeemable borrowers.
* A small redemption fee reduces the collateral a redeemer receives; this fee is kept by the free borrower and helps protect against adverse selection during redemptions.
# How borrower choices guide the interest rate
* The protocol targets a healthy range for the share of “free debt” in the system. Think of this as a band with a lower and an upper threshold.
* If the free‑debt share falls below the lower threshold (too little free debt), the borrow rate rises over time. This nudges borrowers to either repay paid debt or switch to free debt, restoring balance and funding more yield while demand is strong.
* If the free‑debt share rises above the upper threshold (too much free debt), the borrow rate decays toward a low floor, making paid debt cheaper and encouraging borrowers to switch back into paid mode or borrow more there.
* Inside the target band, the rate holds steady. Adjustments are smooth and time‑based (half‑life‑like), avoiding sudden jumps.
* Practical levers for borrowers:
* Moving to free increases the system’s free‑debt share; moving to paid decreases it.
* New borrowing in paid reduces the free‑debt share; redemptions reduce outstanding free debt and can also affect the mix.
* The result is a self‑correcting loop: borrowers’ mode choices collectively steer rates, and rates in turn steer future choices, stabilizing the system around the target equilibrium.
# Solvency and liquidations (applies to both)
* Both modes share the same collateralization rules and oracle‑based solvency checks.
* If your position becomes unsafe, it can be liquidated irrespective of mode.
# PSM deposits influence on free debt
* Monolith comes with an optional Price Stability Module (PSM)
* The PSM allows depositors to deposit a `PSM asset` of equivalent value to `Coin` and receive `Coin` in return.
* `Coin` issued this way is accounted as free debt.
* While there is PSM assets in the PSM vault, PSM assets can be redeemed 1-to-1 for `Coin`.
# Peg Stability Module
Source: https://docs.monolith.market/protocol/peg-stability-module
Direct convertibility between Coin and a reference asset to cushion the peg and provide exit liquidity.
# Peg Stability Module
## Overview
The Peg Stability Module (PSM) gives every instance an optional, direct convertibility path between its `Coin` and a reference asset (`psmAsset`), optionally held via an ERC‑4626 vault (`psmVault`). It cushions the peg, offers predictable exit liquidity, and can harvest yield if a vault is used.
Key ideas:
* Optional per instance: some instances may not enable a PSM.
* 1:1 nominal conversion (subject to decimals and a temporary buy fee) without relying on external liquidity.
* After the immutability deadline, exposure cannot increase: the buy path is disabled; the sell path remains available.
## How it works
There are two flows.
### Sell (Coin → Asset) — before and after immutability deadline
1. You send `Coin` to the instance.
2. The instance burns your `Coin` and returns `psmAsset` one‑for‑one (with decimals conversion), subject to available `psmAsset` liquidity.
3. If a `psmVault` is configured, assets are withdrawn from the vault; otherwise they are sent directly from the instance.
Effect: If `Coin` trades below the reference asset, arbitrageurs can buy `Coin` on the secondary market to sell it into the PSM and lift price back up.
### Buy (Asset → Coin) — only before immutability deadline
1. You send `psmAsset` to the instance.
2. If a `psmVault` is configured, the asset is deposited; otherwise the instance holds it.
3. The instance mints `Coin` to you, one‑for‑one (with decimals conversion), less a temporary buy fee that may apply.
Effect: If `Coin` trades above the reference asset during the launch window, arbitrageurs can buy `Coin` from the PSM to sell it on the market and pull price back down.
After the immutability deadline, this buy path is disabled to prevent increasing exposure to the reference asset.
## Fees and pricing
* Conversion price: nominally 1:1 against the reference asset, with precise decimals handling (e.g., 18‑dec `Coin` vs 6‑dec `psmAsset`).
* Buy fee: during the second half of the immutability window, a linear fee ramps from 0 bps to 100 bps (max 1%). The fee is deducted from `Coin` out and credited to instance local reserves. Before halfway, the buy fee is 0; after the deadline, buys are disabled entirely.
* Sell fee: none. (Redemption fees are separate and apply only to the redemption mechanism, not the PSM.)
## Reserves and profit
* `freePsmAssets` tracks how many reference assets back future PSM sells.
* If a `psmVault` is used, or if the `psmAsset` is rebasing, passive gains are periodically recognized and sent to local reserves. This accrues value to the instance operator.
## Effect on free‑debt ratio and rates
* The system’s free‑debt ratio treats on‑hand PSM assets as part of exit liquidity. Internally, the ratio includes both free debt and `freePsmAssets` in the numerator.
* When `freePsmAssets` grows (e.g., users buy `Coin` with `psmAsset` pre‑deadline, or the vault/rebasing asset accrues profit), the free‑debt share rises. If it rises above the target band, the interest controller decays the borrow rate toward its floor.
* When `freePsmAssets` is drawn down by sells, the free‑debt share falls. If it drops below the target band, the controller raises the borrow rate, nudging borrowers to switch to free debt or repay, rebuilding redemption capacity.
* This coupling ensures PSM liquidity directly informs the controller about exit capacity, aligning rates with peg conditions. See [Interest Rate Controller](/protocol/interest-rate-controller).
# Redemptions
Source: https://docs.monolith.market/protocol/redemptions
How users can redeem stablecoins for collateral
# Redemptions
## Overview
Redemptions let `Coin` holders exit into underlying collateral at the oracle price, less a small redemption fee. They provide reliable exit liquidity and a price floor mechanism when secondary markets are thin or dislocated.
* **Exit liquidity**: Any holder can redeem `Coin` for collateral directly from the instance, regardless of DEX liquidity.
* **Partial redeemability by design**: Only the portion of the system backed by borrowers who opted into free debt is redeemable. Paid‑debt positions are not touched. See the distinction in [Paid vs Free Debt](/protocol/paid-vs-free-debt).
## How redemptions work (high‑level)
1. A user submits a redeemable borrower address to redeem `Coin` from.
2. The instance values the `Coin` at the oracle price and applies a small redemption fee.
3. The protocol burns the redeemed `Coin` and transfers collateral to the redeemer.
4. Global accounting updates:
* Total free debt decreases by the redeemed amount.
* Collateral and debt is removed from the redeemable borrower.
In effect, redemptions repay free debt with the redeemer’s `Coin`, while seizing collateral of equal value (minus fee) from the free‑debt borrower.
## Why only part of the system is redeemable
Monolith is intentionally not “fully redeemable.” Borrowers can choose paid debt (non‑redeemable) or free debt (redeemable). This creates a robust, opt‑in redemption buffer without forcing all borrowers to accept redemption risk. It makes the system more flexible and capital‑efficient while preserving a credible exit for holders.
## Interest‑rate controller and redemption liquidity
The protocol targets a healthy share of free debt to back redemptions. When redemption liquidity is low (free‑debt share below target), the borrow rate rises over time, nudging borrowers to switch to free or repay paid debt. When free‑debt share is abundant, the borrow rate decays toward a low floor, encouraging paid borrowing. This feedback loop keeps redemption capacity available without human intervention. Learn more in [Interest Rate Controller](/protocol/interest-rate-controller).
## Examples: impact on free‑debt borrowers
* **Proportional adjustment**
* Setup: Two free‑debt borrowers, Alice owes 600, Bob owes 400. Total free debt = 1,000.
* Redemption: A user redeems 100 `Coin` from Bob at the oracle price (ignoring fees for simplicity).
* Result: Total free debt becomes 900. Bob’s debt drops to 300 (−100) while Alice's remains unchanged. Collateral is seized pro‑rata from Bob to fund the redeemer.
* **Effect of the redemption fee**
* Setup: Same as above, with a 0.3% redemption fee.
* Redemption: User redeems 100 `Coin` from Bob; The user receive slightly less collateral than the fair price according to the oracle.
* Result: The collateral shortfall (the fee) remains in the system, benefiting Bob.
## What this means for users
* `Coin` holders: You can always find exit liquidity via redemption, subject to current redeemable capacity and fees.
* Borrowers in free mode: You pay no interest, but your collateral is subject to pro‑rata redemptions. Your debt typically falls during active redemption periods.
* Borrowers in paid mode: You pay interest but are insulated from redemptions.
## Related
* [Paid vs Free Debt](/protocol/paid-vs-free-debt)
* [Interest Rate Controller](/protocol/interest-rate-controller)
# Stablecoin Factory
Source: https://docs.monolith.market/protocol/stablecoin-factory
How stablecoins are created in the Monolith protocol
## Overview
The Stablecoin Factory enables anyone to create new Monolith instances. Each instance is a synthetic asset (e.g., a USD‑pegged stablecoin) consisting of a `Lender` (core instance logic), a `Coin` (the ERC‑20 synthetic token), and a `Vault` (an yield-bearing ERC‑4626). The Factory is also the entry-point for the protocol fee operator.
## How to create an instance
1. Choose your inputs: collateral token, price feed, branding (name/symbol), and risk posture (e.g., collateral factor, minimum debt). Optionally connect a PSM asset/vault for direct convertibility.
2. Submit a single, permissionless transaction to deploy. The Factory creates three contracts (Lender, Coin, Vault) in a fixed, pre‑computable way.
3. Announce the addresses and begin distribution, integrations, and liquidity programs as needed. The instance will also be displayed on Monolith UI.
## Architecture
### Per‑instance Components
After deployment, the three following contracts will be created:
* **Lender**: Core instance contract and main entry-point for borrowers, liquidators and instance operators.
* **Coin**: ERC‑20 synthetic asset token (e.g., stablecoin) minted/redeemed by the `Lender` for the instance.
* **Vault**: Yield-bearing ERC‑4626 tokenized wrapper linked to the `Lender` and branded with the instance `(Staked) name`/`(s)symbol`.
## Deploy Parameters
`DeployParams` expected by `Factory.deploy`:
* **name**: Instance display name used for `Vault`/`Coin` branding.
* **symbol**: Instance symbol used for `Vault`/`Coin` branding.
* **collateral**: ERC‑20 address used as collateral.
* **psmAsset**: ERC‑20 asset used by the PSM (Peg Stability Module), if applicable.
* **psmVault**: ERC‑4626 vault used by the PSM, if applicable.
* **feed**: Price feed implementing a Chainlink‑style interface.
* **collateralFactor**: Risk parameter in basis points controlling maximum borrow against collateral.
* **minDebt**: Minimum debt per position or market constraint (enforced by `Lender`).
* **timeUntilImmutability**: Relative time window after which select `Lender` parameters become immutable. Set to 0 for immediate immutability.
* **operator**: Instance‑level operator for the `Lender` (Optional. Set to `address(0)` for none).
* **manager**: Instance‑level manager for the `Lender`. (Optional. Set to `address(0)` for none).
* **halfLife**: Interest rate half‑life for the exponential rate model. Must be between 12 hours and 30 days.
* **targetFreeDebtRatioStartBps**: Lower bound of the target free‑debt ratio band in basis points. Must be ≥500 and ≤ `targetFreeDebtRatioEndBps`.
* **targetFreeDebtRatioEndBps**: Upper bound of the target free‑debt ratio band in basis points. Must be ≤9500.
* **redeemFeeBps**: Redemption fee in basis points. Must be ≤500 (5%).
* **stalenessThreshold**: Maximum acceptable age of an oracle update, in seconds. Prices older than this enter reduce‑only mode and decay linearly to zero over an additional 24 hours.
* **maxBorrowDeltaBps**: Maximum acceptable rounding error when share accounting converts between debt and shares, in basis points. Must be between 50 and 200 (0.5%–2%).
* **psmVaultMinTotalSupply**: Minimum total supply required in the PSM vault to allow PSM buys. Must be greater than 0 whenever `psmVault` is set; unused otherwise.
## Integration tips
* Treat the `Lender` address as the canonical identifier for an instance; `Coin` and `Vault` addresses can be fetched from it.
* Indexing: watch the Factory’s deployment events or `deployments` registry to discover new instances.
* Wallets/exchanges: list the `Coin` address; staking/earn products can use the `Vault` for deposit/withdraw flows.
* Dashboards: read instance configuration (feed, collateral, factors) and status (debt, supply, reserves) from the `Lender` to present risk and performance metrics.
If you need implementation details and ABI-level specifics, see the Factory contract reference:
* [Factory contract reference](/reference/Factory)
## Operator role
* The Factory includes an operator role which only controls fee-related parameters.
* Capabilities:
* Choose or rotate the fee recipient that collects protocol reserves from instances.
* Set a global protocol fee (bounded by a 10% cap) applied to borrower interest.
* Define per‑instance fee overrides bounded by the same cap.
* Perform a two‑step operator handoff to safely transfer control when needed.
* Limitations:
* Cannot upgrade contracts, mint tokens, move user funds, or pause instances.
* Cannot change risk parameters of instances.
# Coin
Source: https://docs.monolith.market/reference/Coin
ERC20 stablecoin implementation
# Coin Contract
The Coin contract implements an ERC20 stablecoin with additional functionality for the Monolith protocol.
[Contract implementation](https://github.com/MonolithMarket/Monolith/blob/main/src/Coin.sol)
## Constructor
```solidity theme={null}
constructor(
address _minter,
string memory name,
string memory symbol
)
```
Initializes the stablecoin with a designated minter address, token name, and symbol.
**Parameters:**
* `_minter`: Address authorized to mint new tokens (Lender.sol)
* `name`: ERC20 token name (e.g., "USD Coin")
* `symbol`: ERC20 token symbol (e.g., "USDC")
## User-Facing Functions
### mint
```solidity theme={null}
function mint(address to, uint256 amount) external
```
Creates new tokens and assigns them to the specified address. Can only be called by the minter (Lender.sol).
**Parameters:**
* `to`: Address to receive the minted tokens
* `amount`: Amount of tokens to mint (in wei, 18 decimals)
**Requirements:**
* `msg.sender` must be the minter address (Lender.sol).
**Events Emitted:**
* `Transfer(address(0), to, amount)`
***
### burn
```solidity theme={null}
function burn(uint256 amount) external
```
Destroys tokens from the caller's balance, reducing the total supply.
**Parameters:**
* `amount`: Amount of tokens to burn from caller's balance
**Requirements:**
* Caller must have sufficient balance (`balanceOf(msg.sender) >= amount`)
**Events Emitted:**
* `Transfer(msg.sender, address(0), amount)`
***
### transfer
```solidity theme={null}
function transfer(address to, uint256 amount) external returns (bool)
```
Standard ERC20 transfer function. Moves tokens from caller's balance to another address.
**Parameters:**
* `to`: Recipient address
* `amount`: Amount of tokens to transfer
**Returns:**
* `bool`: Always returns true on successful transfer
**Requirements:**
* Caller must have sufficient balance
**Events Emitted:**
* `Transfer(msg.sender, to, amount)`
***
### transferFrom
```solidity theme={null}
function transferFrom(address from, address to, uint256 amount) external returns (bool)
```
Standard ERC20 transferFrom function. Moves tokens from one address to another using allowance mechanism.
**Parameters:**
* `from`: Address to transfer tokens from
* `to`: Recipient address
* `amount`: Amount of tokens to transfer
**Returns:**
* `bool`: Always returns true on successful transfer
**Requirements:**
* `from` must have sufficient balance
* Caller must have sufficient allowance from `from`
**Events Emitted:**
* `Transfer(from, to, amount)`
***
### approve
```solidity theme={null}
function approve(address spender, uint256 amount) external returns (bool)
```
Standard ERC20 approve function. Allows spender to transfer up to amount tokens from caller's balance.
**Parameters:**
* `spender`: Address authorized to spend tokens
* `amount`: Maximum amount spender can transfer
**Returns:**
* `bool`: Always returns true on successful approval
**Events Emitted:**
* `Approval(msg.sender, spender, amount)`
***
## View Functions
### balanceOf
```solidity theme={null}
function balanceOf(address account) external view returns (uint256)
```
Returns the token balance of the specified address.
**Parameters:**
* `account`: Address to query balance for
**Returns:**
* `uint256`: Token balance in wei
***
### allowance
```solidity theme={null}
function allowance(address owner, address spender) external view returns (uint256)
```
Returns the remaining allowance that spender can spend on behalf of owner.
**Parameters:**
* `owner`: Address that granted the allowance
* `spender`: Address authorized to spend
**Returns:**
* `uint256`: Remaining allowance amount
***
### totalSupply
```solidity theme={null}
function totalSupply() external view returns (uint256)
```
Returns the total supply of tokens in circulation.
**Returns:**
* `uint256`: Total token supply in wei
***
### name
```solidity theme={null}
function name() external view returns (string memory)
```
Returns the name of the token.
**Returns:**
* `string`: Token name
***
### symbol
```solidity theme={null}
function symbol() external view returns (string memory)
```
Returns the symbol of the token.
**Returns:**
* `string`: Token symbol
***
### decimals
```solidity theme={null}
function decimals() external view returns (uint8)
```
Returns the number of decimals used for token amounts.
**Returns:**
* `uint8`: Number of decimals (18 for this token)
***
### minter
```solidity theme={null}
function minter() external view returns (address)
```
Returns the address authorized to mint new tokens (Lender.sol).
**Returns:**
* `address`: Minter address
## Events
### Transfer
```solidity theme={null}
event Transfer(address indexed from, address indexed to, uint256 amount)
```
Emitted when tokens are transferred, minted, or burned.
**Parameters:**
* `from`: Sender address (address(0) for mints)
* `to`: Recipient address (address(0) for burns)
* `amount`: Amount of tokens transferred
***
### Approval
```solidity theme={null}
event Approval(address indexed owner, address indexed spender, uint256 amount)
```
Emitted when allowance is set or changed.
**Parameters:**
* `owner`: Address granting the allowance
* `spender`: Address receiving the allowance
* `amount`: New allowance amount
# Factory
Source: https://docs.monolith.market/reference/Factory
Contract factory for deploying Monolith protocol components
The Factory contract is responsible for deploying all components of a Monolith instance and managing the global fee.
[Contract implementation](https://github.com/MonolithMarket/Monolith/blob/main/src/Factory.sol)
## Constructor
```solidity theme={null}
constructor(address _operator, uint256 _minDebtFloor)
```
Deploys the Factory and a shared `InterestModel` (accessible via `interestModel()`). Sets the initial operator and the global `minDebtFloor` that applies to every instance's `minDebt` parameter.
## User-Facing Functions
### deploy
```solidity theme={null}
function deploy(DeployParams memory params) external returns (address lender, address coin, address vault)
```
Deploys a complete Monolith lending system consisting of a lender, stablecoin, and vault contracts.
**Parameters:**
* `params`: DeployParams struct containing deployment configuration
**DeployParams Structure:**
```solidity theme={null}
struct DeployParams {
string name; // Token name (e.g., "USD Coin")
string symbol; // Token symbol (e.g., "USDC")
address collateral; // Collateral token address
address psmAsset; // PSM asset token address (address(0) disables PSM)
address psmVault; // PSM ERC4626 vault (address(0) if unused)
address feed; // Chainlink-style price feed address
uint256 collateralFactor; // Max LTV numerator in bps (≤8500 = 85%)
uint256 minDebt; // Minimum debt per position (≥ factory.minDebtFloor())
uint256 timeUntilImmutability; // Seconds until operator params lock (max 1460 days)
address operator; // Instance operator (address(0) for none)
address manager; // Instance manager (address(0) for none)
uint64 halfLife; // Interest rate half-life (12 hours to 30 days)
uint16 targetFreeDebtRatioStartBps; // Target free-debt ratio lower bound (≥500, ≤ end)
uint16 targetFreeDebtRatioEndBps; // Target free-debt ratio upper bound (≤9500)
uint16 redeemFeeBps; // Redemption fee (≤500 = 5%)
uint32 stalenessThreshold; // Oracle max staleness in seconds
uint16 maxBorrowDeltaBps; // Share-accounting rounding tolerance (50–200)
uint128 psmVaultMinTotalSupply; // PSM vault minimum supply (required if psmVault set)
}
```
**Returns:**
* `lender`: Address of the deployed Lender contract
* `coin`: Address of the deployed Coin (ERC‑20) contract
* `vault`: Address of the deployed Vault (ERC‑4626) contract
**Requirements:**
* All bounds listed above are enforced by `Lender`'s constructor and revert on violation.
* `params.collateral` decimals must be ≤ 30.
* `params.psmAsset` must differ from the deployed `coin`.
* If `params.psmVault` is set, its underlying `asset()` must equal `params.psmAsset` and `psmVaultMinTotalSupply` must be > 0.
**Deployment Process:**
1. Calculates deterministic addresses using CREATE3
2. Deploys contracts in order: Lender → Coin → Vault
3. Initializes contracts with proper cross-references
4. Records deployment in factory registry
**Events Emitted:**
* `Deployed(lender, coin, vault)`
***
### deploymentsLength
```solidity theme={null}
function deploymentsLength() external view returns (uint256)
```
Returns the total number of deployments created by this factory.
**Returns:**
* `uint256`: Number of deployments
***
### deployments
```solidity theme={null}
function deployments(uint256 index) external view returns (address lender)
```
Array accessor returning the Lender address at a given deployment index. Use together with `deploymentsLength()` to enumerate all instances.
***
### interestModel
```solidity theme={null}
function interestModel() external view returns (address)
```
Returns the address of the shared `InterestModel` deployed by this Factory's constructor. All Lenders deployed by this Factory use this same `InterestModel` instance.
***
### minDebtFloor
```solidity theme={null}
function minDebtFloor() external view returns (uint256)
```
Returns the global immutable minimum debt floor. Every Lender's `minDebt` must be ≥ this value at deployment.
***
### pendingOperator
```solidity theme={null}
function pendingOperator() external view returns (address)
```
Returns the address currently queued to accept the operator role via `acceptOperator()`.
***
### operator
```solidity theme={null}
function operator() external view returns (address)
```
Returns the current operator address authorized to manage the factory.
**Returns:**
* `address`: Current operator address
***
### feeRecipient
```solidity theme={null}
function feeRecipient() external view returns (address)
```
Returns the address that receives protocol fees.
**Returns:**
* `address`: Fee recipient address
***
### feeBps
```solidity theme={null}
function feeBps() external view returns (uint256)
```
Returns the default fee rate in basis points (bps).
**Returns:**
* `uint256`: Default fee in bps (e.g., 100 = 1%)
***
### getFeeOf
```solidity theme={null}
function getFeeOf(address _lender) external view returns (uint256)
```
Returns the fee rate for a specific lender deployment, using custom fee if set, otherwise default fee.
**Parameters:**
* `_lender`: Address of the lender deployment
**Returns:**
* `uint256`: Fee rate in bps
***
### isDeployed
```solidity theme={null}
function isDeployed(address deployment) external view returns (bool)
```
Checks if an address was deployed by this factory.
**Parameters:**
* `deployment`: Address to check
**Returns:**
* `bool`: True if address was deployed by this factory
***
### customFeeBps
```solidity theme={null}
function customFeeBps(address lender) external view returns (uint256)
```
Returns the custom fee rate for a specific lender deployment.
**Parameters:**
* `lender`: Address of the lender deployment
**Returns:**
* `uint256`: Custom fee in bps, 0 if using default fee
## Operator Functions
### setPendingOperator
```solidity theme={null}
function setPendingOperator(address _pendingOperator) external
```
Sets a new pending operator address. Can only be called by current operator.
**Parameters:**
* `_pendingOperator`: Address to set as pending operator
**Requirements:**
* `msg.sender` must be current operator
***
### acceptOperator
```solidity theme={null}
function acceptOperator() external
```
Accepts operator role for the pending operator address.
**Requirements:**
* `msg.sender` must be pending operator
***
### setFeeRecipient
```solidity theme={null}
function setFeeRecipient(address _feeRecipient) external
```
Sets the address that receives protocol fees.
**Parameters:**
* `_feeRecipient`: New fee recipient address
**Requirements:**
* `msg.sender` must be current operator
***
### setFeeBps
```solidity theme={null}
function setFeeBps(uint256 _feeBps) external
```
Sets the default fee rate in basis points.
**Parameters:**
* `_feeBps`: New fee rate in bps (max 1000 = 10%)
**Requirements:**
* `msg.sender` must be current operator
* `_feeBps` must be ≤ 1000
***
### setCustomFeeBps
```solidity theme={null}
function setCustomFeeBps(address _address, uint256 _feeBps) external
```
Sets a custom fee rate for a specific lender deployment.
**Parameters:**
* `_address`: Lender deployment address
* `_feeBps`: Custom fee rate in bps (max 1000 = 10%)
**Requirements:**
* `msg.sender` must be current operator
* `_feeBps` must be ≤ 1000
***
### pullReserves
```solidity theme={null}
function pullReserves(address _deployment) external
```
Pulls accumulated reserves from a lender deployment to the fee recipient.
**Parameters:**
* `_deployment`: Lender deployment address
**Requirements:**
* `msg.sender` must be fee recipient
* `_deployment` must be a valid deployment
## Events
* `Deployed(address indexed lender, address indexed coin, address indexed vault)` — emitted by `deploy()` with the new instance addresses.
* `CustomFeeBpsSet(address indexed lender, uint256 feeBps)` — emitted by `setCustomFeeBps()`.
* `FeeBpsUpdated(uint256 feeBps)` — emitted by `setFeeBps()`.
* `FeeRecipientUpdated(address indexed feeRecipient)` — emitted by `setFeeRecipient()`.
* `PendingOperatorUpdated(address indexed pendingOperator)` — emitted by `setPendingOperator()`.
* `OperatorUpdated(address indexed operator)` — emitted by `acceptOperator()`.
* `ReservesPulled(address indexed lender, address indexed recipient, uint256 amount)` — emitted by `pullReserves()`.
# InterestModel
Source: https://docs.monolith.market/reference/InterestModel
Dynamic interest rate calculation for borrowing
# Interest Model
The InterestModel contract calculates the borrow rate and accrued interest using an exponential controller driven by the free‑debt ratio. It is a shared, pure math contract used by all `Lender` instances.
[Contract implementation](https://github.com/MonolithMarket/Monolith/blob/main/src/InterestModel.sol)
## Core Calculation Function
### calculateInterest
```solidity theme={null}
function calculateInterest(
uint _totalPaidDebt,
uint _lastRate,
uint _timeElapsed,
uint _expRate,
uint _lastFreeDebtRatioBps,
uint _targetFreeDebtRatioStartBps,
uint _targetFreeDebtRatioEndBps
) external pure returns (uint currBorrowRate, uint interest)
```
Calculates the new borrow rate and the interest accrued over `_timeElapsed` seconds using an exponential controller around a target free‑debt ratio band.
**Parameters:**
* `_totalPaidDebt`: Current paid (interest‑bearing) debt principal `D`.
* `_lastRate`: Previous borrow rate mantissa `r_old` (APR scaled by 1e18).
* `_timeElapsed`: Seconds since last accrual `dt`.
* `_expRate`: Exponential rate constant `k` (derived from half‑life via `wadLn(2e18)/halfLife`).
* `_lastFreeDebtRatioBps`: Last observed free‑debt ratio `f` in basis points (0–10000), including PSM assets.
* `_targetFreeDebtRatioStartBps`, `_targetFreeDebtRatioEndBps`: Target band `[f_start, f_end]` in basis points.
**Returns:**
* `currBorrowRate`: Updated borrow rate mantissa `r_new` (APR scaled by 1e18).
* `interest`: Accrued interest amount over the interval.
**Algorithm summary:**
* Let `g = exp(-k * dt)`.
* If `f < f_start` (below band): rate grows exponentially
* `r_new = r_old / g`
* `interest = D * (r_new - r_old) / (k * 365 days)`
* Else if `f > f_end` (above band): rate decays exponentially toward a floor
* `r_new = max(r_old * g, r_min)` with `r_min = 0.5% APR`
* If the decay hits the floor during `dt`:
* `t_min = -ln(r_min / r_old) / k`
* `interest = D * ((r_old - r_min) / k + r_min * (dt - t_min)) / (365 days)`
* Else:
* `interest = D * (r_old - r_new) / (k * 365 days)`
* Else (inside band): hold rate constant
* `r_new = r_old`
* `interest = D * r_old * dt / (365 days * 1e18)`
## Constants
* `MIN_RATE = 0.5% APR` (as `5e15` in 1e18 mantissa) — lower bound for the borrow rate.
## Integration Notes
* The model is stateless and pure; it is called externally by `Lender` using `try/catch` so accrual can safely skip if anything unexpected happens.
* Each `Lender` stores its own `expRate` (set via half‑life) and target band; these can be adjusted before the immutability deadline.
* One shared `InterestModel` instance is deployed by the `Factory` and referenced by all `Lender` contracts.
## Security Considerations
* Pure math (no state) and no external calls inside the function.
* Uses wad math (`wadExp`, `wadLn`) and explicit floor handling to avoid overflows and negative rates.
# Lender
Source: https://docs.monolith.market/reference/Lender
Core lending pool contract for the Monolith protocol
# Lender Contract
The Lender contract implements the core lending functionality for an instance: collateral management, debt accounting, interest accrual, liquidations, redemptions, and PSM conversions.
[Contract implementation](https://github.com/MonolithMarket/Monolith/blob/main/src/Lender.sol)
## User-Facing Functions
### adjust
```solidity theme={null}
function adjust(address account, int collateralDelta, int debtDelta, bool chooseRedeemable) external
```
Adjusts a user's position by modifying collateral and/or debt. This is the primary function for depositing, withdrawing, borrowing, repaying and changing redemption status.
**Parameters:**
* `account`: Address of the position to adjust
* `collateralDelta`: Amount to add (positive) or remove (negative) collateral (in wei)
* `debtDelta`: Amount to borrow (positive) or repay (negative) debt (in wei)
* `chooseRedeemable`: True to turn on redeemable (free debt) mode. False to turn off.
**Requirements:**
* If `collateralDelta > 0`: `msg.sender` must provide collateral in (approval required)
* If `debtDelta > 0`: Position must remain solvent after the change
* If `debtDelta < 0`: Caller must provide Coin to repay (approval required)
* If decreasing collateral or increasing debt: caller must be `account` or a delegated address
* If `debtDelta != 0`: resulting debt must be 0 or ≥ `minDebt`
**Behavior:**
* Automatically accrues interest before adjustment
* Updates collateral and debt of the borrower
* Maintains minimum debt requirements
* Emits position update events
***
### liquidate
```solidity theme={null}
function liquidate(address borrower, uint repayAmount, uint minCollateralOut) external returns (uint collateralOut)
```
Liquidates an undercollateralized position to maintain protocol solvency. Oracle‑gated; disabled when price is stale/invalid.
**Parameters:**
* `borrower`: Address of the position to liquidate
* `repayAmount`: Amount of debt to repay (in wei)
* `minCollateralOut`: Minimum collateral amount to receive (caller protection)
**Returns:**
* `collateralOut`: Amount of collateral received by liquidator
**Requirements:**
* Borrower loan must be unhealthy at the oracle price and liquidations allowed
* Up to 25% of total debt can be liquidated per call (minimum 10,000 Coin chunk, or full debt if smaller)
* Liquidator must provide Coin to repay and set an acceptable `minCollateralOut`
**Liquidation Process:**
1. Accrue interest on borrower's position
2. Verify liquidation conditions
3. Transfer Coin from liquidator to repay debt
4. Calculate collateral reward with incentive
5. Transfer collateral to liquidator
6. Update borrower's position
**Incentive Calculation:**
* Incentive scales from 0% (at collateralFactor) up to 10% (5 percentage points above collateralFactor), linearly in between
***
### redeem
```solidity theme={null}
function redeem(uint amountIn, uint minAmountOut) external returns (uint amountOut)
```
Redeems Coin for collateral from the redeemable pool at the oracle price minus a redemption fee.
**Parameters:**
* `amountIn`: Amount of Coin to redeem (in wei)
* `minAmountOut`: Minimum collateral amount to receive (slippage protection)
**Returns:**
* `amountOut`: Amount of collateral received
**Requirements:**
* Redemptions must be allowed (fresh oracle)
* Redeemable borrowers must have sufficient collateral to redeem and debt to repay
* `amountOut` must be ≥ `minAmountOut`
**Redemption Amount:**
* `amountOut = amountIn * 1e18 * (10000 - redeemFeeBps) / price / 10000`
***
### sell
```solidity theme={null}
function sell(uint coinIn, uint minAssetOut) external returns (uint assetOut)
```
Sells Coin for PSM asset at a 1:1 nominal rate (decimals‑adjusted). No fee.
**Parameters:**
* `coinIn`: Amount of Coin to sell (in wei)
* `minAssetOut`: Minimum PSM asset amount to receive
**Returns:**
* `assetOut`: Amount of PSM asset received
**Requirements:**
* PSM must be configured with a `psmAsset`
* Sufficient PSM reserves available
* `assetOut` must be ≥ `minAssetOut`
**Pricing:**
* Decimals conversion between 18‑dec Coin and `psmAsset` decimals. No fee.
***
### buy
```solidity theme={null}
function buy(uint assetIn, uint minCoinOut) external returns (uint coinOut)
```
Buys Coin using PSM asset (only before immutability deadline). A time‑based buy fee may apply.
**Parameters:**
* `assetIn`: Amount of PSM asset to spend (in wei)
* `minCoinOut`: Minimum Coin amount to receive
**Returns:**
* `coinOut`: Amount of Coin received
**Requirements:**
* PSM must be configured
* Must be before immutability deadline
* `coinOut` must be ≥ `minCoinOut`
**Pricing:**
* Decimals conversion; buy fee ramps from 0→100 bps during the second half of the immutability window
***
### delegate
```solidity theme={null}
function delegate(address delegatee, bool isDelegatee) external
```
Delegates or revokes delegation rights for position management.
**Parameters:**
* `delegatee`: Address to grant/revoke delegation
* `isDelegatee`: True to grant, false to revoke
**Effects:**
* Allows delegatee to borrow and withdraw collateral via `adjust()` and call `setRedemptionStatus()` on behalf of delegator
* A delegator may assign multiple concurrent delegatees.
* Delegation can be changed at any time by delegator
***
### setRedemptionStatus
```solidity theme={null}
function setRedemptionStatus(address account, bool chooseRedeemable) external
```
Sets whether an account's position participates in redemptions (free debt) or accrues interest (paid debt).
**Parameters:**
* `account`: Address to set redemption status for (can be any address)
* `chooseRedeemable`: True to allow redemption, false to prevent
**Requirements:**
* Caller must be `account` or a delegated address
**Effects:**
* Toggles redeemable status. If true, borrower pays 0 interest. If false, borrowers pays variable rate.
* Default is non‑redeemable.
***
### accrueInterest
```solidity theme={null}
function accrueInterest() public
```
Accrues interest on paid debt. Called automatically by state‑changing functions and may be called directly.
**Effects:**
* Uses the shared InterestModel to compute current rate and interest
* Splits interest into fees (local/global reserves) and staking yield (minted to the Vault)
* Emits `InterestAccrued(interestAccrued, newBorrowRateMantissa)` on a successful accrual
***
### writeOff
```solidity theme={null}
function writeOff(address borrower, address to) external returns (bool writtenOff)
```
Writes off unrecoverable debt and socializes losses across all borrowers.
**Parameters:**
* `borrower`: Address with bad debt position
* `to`: Address to receive written-off collateral
**Returns:**
* `writtenOff`: True if debt was written off
**Requirements:**
* Oracle must allow liquidations
* Position must be extremely undercollateralized (debt > 100× collateral value)
* Callable by anyone (also attempted from `liquidate()` via try/catch)
**Effects:**
* Deletes borrower debt
* Redistributes it across free/paid pools proportionally
* Sends remaining collateral to `to`
## View Functions
### getDebtOf
```solidity theme={null}
function getDebtOf(address account) public view returns (uint debt)
```
Returns the current debt amount for an account, including accrued interest.
**Parameters:**
* `account`: Address to query debt for
**Returns:**
* `debt`: Current debt amount in wei
***
### getCollateralPrice
```solidity theme={null}
function getCollateralPrice() public view returns (uint price, bool reduceOnly, bool allowLiquidations)
```
Returns the normalized collateral price and safety flags.
**Returns:**
* `price`: Normalized to `36 - collateralDecimals` digits (never zero inside consumers)
* `reduceOnly`: True if only reductions allowed
* `allowLiquidations`: True if liquidations/redemptions/write‑offs permitted
***
### getFreeDebtRatio
```solidity theme={null}
function getFreeDebtRatio() public view returns (uint ratio)
```
Returns the current ratio of free debt to total debt (includes PSM assets in the free buffer).
**Returns:**
* `ratio`: Free debt ratio in basis points (0–10000)
***
### getSellAmountOut
```solidity theme={null}
function getSellAmountOut(uint coinIn) public view returns (uint assetOut)
```
Calculates the amount of PSM asset received for selling Coin (pure decimals conversion).
**Parameters:**
* `coinIn`: Amount of Coin to sell
**Returns:**
* `assetOut`: Amount of PSM asset received
***
### getBuyAmountOut
```solidity theme={null}
function getBuyAmountOut(uint assetIn) public view returns (uint coinOut, uint coinFee)
```
Calculates the amount of Coin and buy fee for buying with PSM asset (pre‑deadline).
**Parameters:**
* `assetIn`: Amount of PSM asset to spend
**Returns:**
* `coinOut`: Amount of Coin received
* `coinFee`: Fee amount deducted
***
### getFeedPrice
```solidity theme={null}
function getFeedPrice() external view returns (uint price, uint updatedAt)
```
Returns raw price feed data without protocol modifications.
**Returns:**
* `price`: Raw price from Chainlink feed
* `updatedAt`: Timestamp when price was last updated
## Protocol Management Functions
### setPendingOperator
```solidity theme={null}
function setPendingOperator(address _pendingOperator) external
```
Sets a new pending operator address (two‑step handoff).
**Parameters:**
* `_pendingOperator`: New operator address
**Requirements:**
* Caller must be current operator
***
### acceptOperator
```solidity theme={null}
function acceptOperator() external
```
Accepts operator role for pending operator.
**Requirements:**
* Caller must be pending operator
***
### setManager
```solidity theme={null}
function setManager(address _manager) external
```
Sets or updates the manager address (shared with operator for certain pre‑deadline actions).
**Parameters:**
* `_manager`: New manager address
**Requirements:**
* Caller must be operator or manager
***
### enableImmutabilityNow
```solidity theme={null}
function enableImmutabilityNow() external
```
Immediately enables immutability (locks certain configuration permanently).
**Requirements:**
* Caller must be operator
* Must be before immutability deadline
***
### pullLocalReserves
```solidity theme={null}
function pullLocalReserves() external
```
Mints accumulated local reserves to the caller (operator only).
**Requirements:**
* Caller must be operator
***
### pullGlobalReserves
```solidity theme={null}
function pullGlobalReserves(address _to) external returns (uint256 amount)
```
Mints accumulated global reserves to `_to` and returns the amount minted.
**Parameters:**
* `_to`: Address to receive reserves
**Returns:**
* `amount`: Amount of reserves minted
**Requirements:**
* Caller must be Factory
***
### reapprovePsmVault
```solidity theme={null}
function reapprovePsmVault() external
```
Reapproves the PSM vault for unlimited spending (before immutability deadline).
**Requirements:**
* Must be before immutability deadline
## Configuration Functions
### setHalfLife
```solidity theme={null}
function setHalfLife(uint64 halfLife) external
```
Sets the interest rate half-life for exponential decay and growth.
**Parameters:**
* `halfLife`: New half-life in seconds
**Requirements:**
* Caller must be operator or manager
* Must be before immutability deadline
* `halfLife` must be between 12 hours and 30 days
***
### setTargetFreeDebtRatio
```solidity theme={null}
function setTargetFreeDebtRatio(uint16 startBps, uint16 endBps) external
```
Sets the target free debt ratio range in basis points.
**Parameters:**
* `startBps`: Minimum free debt ratio (basis points)
* `endBps`: Maximum free debt ratio (basis points)
**Requirements:**
* Caller must be operator or manager
* Must be before immutability deadline
* `startBps` must be ≥500 and ≤ `endBps`
* `endBps` must be ≤9500
***
### setRedeemFeeBps
```solidity theme={null}
function setRedeemFeeBps(uint16 _redeemFeeBps) external
```
Sets the redemption fee in basis points.
**Parameters:**
* `_redeemFeeBps`: New redemption fee (basis points)
**Requirements:**
* Caller must be operator or manager
* Must be before immutability deadline
* `_redeemFeeBps` must be ≤500 (5%)
***
### setMaxBorrowDeltaBps
```solidity theme={null}
function setMaxBorrowDeltaBps(uint16 _maxBorrowDeltaBps) external
```
Sets the maximum acceptable rounding error for share-accounting conversions between debt and shares.
**Parameters:**
* `_maxBorrowDeltaBps`: New max rounding delta (basis points)
**Requirements:**
* Caller must be operator or manager
* Must be before immutability deadline
* `_maxBorrowDeltaBps` must be between 50 and 200 (0.5%–2%)
***
### setLocalReserveFeeBps
```solidity theme={null}
function setLocalReserveFeeBps(uint _feeBps) external
```
Sets the local reserve fee rate.
**Parameters:**
* `_feeBps`: New fee rate (basis points)
**Requirements:**
* Caller must be operator
***
## Key State Variables
### Debt accounting
* `totalPaidDebt` — cached total interest-bearing debt. May be missing accrued interest until `accrueInterest()` is called.
* `totalFreeDebt` — total non-interest-bearing (redeemable) debt.
* `totalPaidDebtShares`, `totalFreeDebtShares` — share-based accounting totals for the two debt pools.
* `freeDebtShares(address)`, `paidDebtShares(address)` — per-borrower shares in each pool.
* `isRedeemable(address)` — whether an account's debt is in redeemable (free) mode.
* `collateralBalances(address)` — per-borrower collateral in collateral-token decimals.
### Immutable deployment parameters
* `collateralFactor` — max LTV numerator in basis points (e.g., 8000 = 80%). Capped at 8500.
* `minDebt` — minimum debt per position (0 or ≥ this value).
* `stalenessThreshold` — oracle max staleness in seconds.
* `psmVaultMinTotalSupply` — PSM vault minimum supply required to enable buys (if `psmVault` set).
* `coin`, `collateral`, `vault`, `feed`, `psmAsset`, `psmVault`, `interestModel`, `factory` — contract references set at deployment.
* `immutabilityDeadline` — timestamp after which tunable parameters are locked.
### Tunable parameters (changeable by operator/manager before deadline)
* `redeemFeeBps` — redemption fee (max 500 / 5%).
* `maxBorrowDeltaBps` — share-accounting rounding tolerance (50–200).
* `targetFreeDebtRatioStartBps`, `targetFreeDebtRatioEndBps` — interest rate controller target band.
* `expRate` — exponential decay/growth rate derived from `halfLife`.
* `feeBps` — local reserve fee (operator-only; not protected by deadline).
### Reserves and governance
* `accruedLocalReserves`, `accruedGlobalReserves` — interest accrued to operator / fee recipient.
* `cachedGlobalFeeBps` — Factory fee rate cached at last accrual.
* `operator`, `pendingOperator`, `manager` — access-control addresses.
## Events
* `PositionAdjusted(address indexed account, int collateralDelta, int debtDelta)`
* `HalfLifeUpdated(uint64 halfLife)`
* `TargetFreeDebtRatioUpdated(uint16 startBps, uint16 endBps)`
* `RedeemFeeBpsUpdated(uint16 redeemFeeBps)`
* `MaxBorrowDeltaBpsUpdated(uint16 maxBorrowDeltaBps)`
* `DelegationUpdated(address indexed delegator, address indexed delegatee, bool isDelegatee)`
* `PendingOperatorUpdated(address indexed pendingOperator)`
* `OperatorAccepted(address indexed operator)`
* `ManagerUpdated(address indexed manager)`
* `LocalReserveFeeUpdated(uint256 feeBps)`
* `RedemptionStatusUpdated(address indexed account, bool isRedeemable)`
* `Liquidated(address indexed borrower, address indexed liquidator, uint repayAmount, uint collateralOut)`
* `WrittenOff(address indexed borrower, address indexed to, uint debt, uint collateral)`
* `Redeemed(address indexed account, address indexed borrower, uint amountIn, uint amountOut)`
* `Sold(address indexed account, uint coinIn, uint assetOut)`
* `Bought(address indexed account, uint assetIn, uint coinOut)`
* `ImmutabilityEnabled(uint256 timestamp)`
* `AccruedLocalReserves(uint256 amount)`
* `AccruedGlobalReserves(uint256 amount)`
* `InterestAccrued(uint256 interestAccrued, uint256 newBorrowRateMantissa)`
# Lens
Source: https://docs.monolith.market/reference/Lens
Read-only helper contract for simulating and querying Monolith state
# Lens Contract
`Lens` is a stateless, view-only helper that simulates interest accrual and redemption outcomes without mutating protocol state. It is useful for UI previews and off-chain integrations that need fresh values without paying gas for `accrueInterest()`.
[Contract source](https://github.com/MonolithMarket/Monolith/blob/main/src/Lens.sol)
## Functions
### previewRedeem
```solidity theme={null}
function previewRedeem(Lender _lender, address borrower, uint256 amountIn)
external
view
returns (uint256 coinIn, uint256 amountOut)
```
Simulates the outcome of redeeming `amountIn` Coin against `borrower`'s collateral on `_lender`, using current state plus pending interest.
**Parameters:**
* `_lender`: Lender instance to query
* `borrower`: Borrower to redeem against (must be in redeemable mode)
* `amountIn`: Desired amount of Coin to redeem
**Returns:**
* `coinIn`: Amount of Coin that would actually be consumed (capped by the borrower's debt and by their collateral value at the current price)
* `amountOut`: Amount of collateral the redeemer would receive, in collateral token decimals
**Returns `(0, 0)` when any of the following hold:**
* `amountIn` is zero
* `borrower` is not redeemable (`isRedeemable(borrower) == false`)
* `borrower` has no collateral
* The oracle does not allow liquidations (stale/invalid price or reduce-only)
* `borrower` has no debt
* The computed `amountOut` is zero or exceeds the borrower's collateral balance
***
### getDebtOf
```solidity theme={null}
function getDebtOf(Lender _lender, address borrower) public view returns (uint256)
```
Returns `borrower`'s current debt on `_lender`, **including interest that has accrued since the last `accrueInterest()` call**. In contrast, `Lender.getDebtOf` reflects only already-accrued state.
**Parameters:**
* `_lender`: Lender instance to query
* `borrower`: Borrower address
**Returns:**
* Current debt amount (18 decimals), synchronized with `InterestModel.calculateInterest`. Zero if the borrower has no shares in the appropriate (paid or free) debt pool.
**Details:**
* For redeemable borrowers, debt is computed from `freeDebtShares` against `totalFreeDebt` (free debt does not accrue interest).
* For non-redeemable borrowers, debt is computed from `paidDebtShares` against a synced `totalPaidDebt` that includes pending interest via a `try/catch` call to `InterestModel.calculateInterest`. If the interest math would overflow, the function falls back to the unsynced value rather than reverting.
# Metadata
Source: https://docs.monolith.market/reference/Metadata
Singleton contract for per-instance branding and display metadata
# Metadata Contract
`Metadata` is a chain-singleton contract that stores branding and display information for each Monolith instance: social URLs, logos, project name, coin denomination, description, and an optional collateral USD price feed. It holds no funds and performs no protocol logic — it exists purely so that UIs can render consistent information for every deployed stablecoin.
[Contract source](https://github.com/MonolithMarket/Monolith/blob/main/src/Metadata.sol)
## Access control
All setters are guarded by the `onlyOperatorOrManager(address _lender)` modifier. A caller must equal `ILender(_lender).operator()` or `ILender(_lender).manager()` to set metadata for that Lender. Each Lender's operator and manager therefore manage its own metadata independently; there is no global admin.
## Types
```solidity theme={null}
enum CoinType { Stablecoin, Volatile }
struct MetadataValues {
string websiteUrl;
string xUrl;
string discordUrl;
string telegramUrl;
string otherUrl;
string coinLogoUrl;
string vaultLogoUrl;
string projectName;
string projectLogoUrl;
CoinType coinType;
string coinDenomination;
address collateralUsdPriceFeed; // optional; address(0) if market feed is already USD-denominated
string description;
}
```
## Storage
Per-Lender mappings (all public, so each has an auto-generated getter):
* `websiteUrl`, `xUrl`, `discordUrl`, `telegramUrl`, `otherUrl`
* `coinLogoUrl`, `vaultLogoUrl`, `projectLogoUrl`
* `projectName`, `coinDenomination`, `description`
* `coinType` (`CoinType` enum)
* `collateralUsdPriceFeed` (address)
## Functions
### setMetadata
```solidity theme={null}
function setMetadata(address _lender, MetadataValues calldata m) external
```
Batch setter that writes every metadata field for `_lender` in one call. Emits `MetadataUpdated(_lender, m)`.
**Requirements:**
* `msg.sender == ILender(_lender).operator()` or `msg.sender == ILender(_lender).manager()`
***
### getMetadata
```solidity theme={null}
function getMetadata(address _lender) external view returns (MetadataValues memory)
```
Reads all metadata fields for `_lender` as a single `MetadataValues` struct.
***
### Individual setters
Each of the following sets one field and emits the corresponding `*Updated` event. All require `msg.sender == ILender(_lender).operator()` or `msg.sender == ILender(_lender).manager()`.
```solidity theme={null}
function setDescription (address _lender, string calldata _description) external;
function setWebsiteUrl (address _lender, string calldata _websiteUrl) external;
function setXUrl (address _lender, string calldata _xUrl) external;
function setDiscordUrl (address _lender, string calldata _discordUrl) external;
function setTelegramUrl (address _lender, string calldata _telegramUrl) external;
function setOtherUrl (address _lender, string calldata _otherUrl) external;
function setCoinLogoUrl (address _lender, string calldata _coinLogoUrl) external;
function setVaultLogoUrl (address _lender, string calldata _vaultLogoUrl) external;
function setProjectName (address _lender, string calldata _projectName) external;
function setProjectLogoUrl (address _lender, string calldata _projectLogoUrl) external;
function setCoinType (address _lender, CoinType _coinType) external;
function setCoinDenomination (address _lender, string calldata _coinDenomination) external;
function setCollateralUsdPriceFeed (address _lender, address _collateralUsdPriceFeed) external;
```
## Events
* `MetadataUpdated(address indexed lender, MetadataValues values)` — emitted by `setMetadata`.
* `WebsiteUrlUpdated(address indexed lender, string websiteUrl)`
* `XUrlUpdated(address indexed lender, string xUrl)`
* `DiscordUrlUpdated(address indexed lender, string discordUrl)`
* `TelegramUrlUpdated(address indexed lender, string telegramUrl)`
* `OtherUrlUpdated(address indexed lender, string otherUrl)`
* `CoinLogoUrlUpdated(address indexed lender, string coinLogoUrl)`
* `VaultLogoUrlUpdated(address indexed lender, string vaultLogoUrl)`
* `ProjectNameUpdated(address indexed lender, string projectName)`
* `ProjectLogoUrlUpdated(address indexed lender, string projectLogoUrl)`
* `CoinTypeUpdated(address indexed lender, CoinType coinType)`
* `CoinDenominationUpdated(address indexed lender, string coinDenomination)`
* `DescriptionUpdated(address indexed lender, string description)`
* `CollateralUsdPriceFeedUpdated(address indexed lender, address collateralUsdPriceFeed)`
# Vault
Source: https://docs.monolith.market/reference/Vault
ERC4626 vault implementation for yield farming
# Vault Contract
The Vault contract implements ERC4626 tokenized vault functionality for earning yield generated by borrower's interest.
[Contract implementation](https://github.com/MonolithMarket/Monolith/blob/main/src/Vault.sol)
## ERC4626 Standard Functions
### deposit
```solidity theme={null}
function deposit(uint256 assets, address receiver) public accrueInterest override returns (uint256 shares)
```
Deposits assets into the vault and mints corresponding vault shares to receiver.
**Parameters:**
* `assets`: Amount of underlying assets to deposit (in wei)
* `receiver`: Address to receive the vault shares
**Returns:**
* `shares`: Amount of vault shares minted
**Requirements:**
* `assets` must be > 0
* Caller must have approved vault for asset transfer
* If this is the first ever deposit into the vault, the minted shares must be at least `MIN_SHARES` (1e16); otherwise the transaction reverts
**Effects:**
* Transfers assets from caller to vault
* Mints shares to receiver
* Updates total assets
* Accrues interest before deposit
* On the first ever deposit, `MIN_SHARES` shares are burned from the receiver and sent to `address(0)` to initialize share pricing; the receiver's net minted shares are reduced by `MIN_SHARES`
***
### mint
```solidity theme={null}
function mint(uint256 shares, address receiver) public accrueInterest override returns (uint256 assets)
```
Mints exact amount of vault shares by depositing corresponding assets.
**Parameters:**
* `shares`: Exact amount of shares to mint
* `receiver`: Address to receive the vault shares
**Returns:**
* `assets`: Amount of assets required for the mint
**Requirements:**
* `shares` must be > 0
* Caller must have sufficient assets approved
* If this is the first ever mint into the vault, the requested `shares` must be at least `MIN_SHARES` (1e16); otherwise the transaction reverts
**Effects:**
* Calculates required assets based on current share price
* Transfers assets from caller to vault
* Mints exact shares to receiver
* On the first ever mint, `MIN_SHARES` shares are burned from the receiver and sent to `address(0)`; the corresponding `assets` are effectively reserved
***
### withdraw
```solidity theme={null}
function withdraw(
uint256 assets,
address receiver,
address owner
) public accrueInterest override returns (uint256 shares)
```
Burns vault shares and returns corresponding assets to receiver.
**Parameters:**
* `assets`: Amount of assets to withdraw
* `receiver`: Address to receive the assets
* `owner`: Address that owns the shares (can be different from caller with approval)
**Returns:**
* `shares`: Amount of shares burned
**Requirements:**
* `assets` must be ≤ owner's balance
* If `owner != msg.sender`, caller must have withdrawal approval
* Vault must have sufficient assets
**Effects:**
* Burns shares from owner
* Transfers assets to receiver
* Updates total assets
***
### redeem
```solidity theme={null}
function redeem(
uint256 shares,
address receiver,
address owner
) public accrueInterest override returns (uint256 assets)
```
Burns exact amount of vault shares and returns corresponding assets.
**Parameters:**
* `shares`: Amount of shares to redeem
* `receiver`: Address to receive the assets
* `owner`: Address that owns the shares
**Returns:**
* `assets`: Amount of assets returned
**Requirements:**
* `shares` must be ≤ owner's balance
* If `owner != msg.sender`, caller must have approval
**Effects:**
* Burns shares from owner
* Transfers assets to receiver
* Returns actual assets received (may differ due to rounding)
***
## View Functions
### totalAssets
```solidity theme={null}
function totalAssets() public view override returns (uint256)
```
Returns the total amount of underlying assets held by the vault.
**Returns:**
* `uint256`: Total assets in wei
**Note:** Returns the current `asset` token balance held by the vault contract.
***
### convertToShares
```solidity theme={null}
function convertToShares(uint256 assets) public view override returns (uint256)
```
Calculates the amount of shares that would be minted for given assets.
**Parameters:**
* `assets`: Amount of assets to convert
**Returns:**
* `uint256`: Equivalent shares amount
***
### convertToAssets
```solidity theme={null}
function convertToAssets(uint256 shares) public view override returns (uint256)
```
Calculates the amount of assets that would be returned for given shares.
**Parameters:**
* `shares`: Amount of shares to convert
**Returns:**
* `uint256`: Equivalent assets amount
***
### maxDeposit
```solidity theme={null}
function maxDeposit(address) public view override returns (uint256)
```
Returns the maximum amount of assets that can be deposited.
**Returns:**
* `uint256`: Maximum deposit amount (type(uint256).max if unlimited)
***
### maxMint
```solidity theme={null}
function maxMint(address) public view override returns (uint256)
```
Returns the maximum amount of shares that can be minted.
**Returns:**
* `uint256`: Maximum mint amount
***
### maxWithdraw
```solidity theme={null}
function maxWithdraw(address owner) public view override returns (uint256)
```
Returns the maximum amount of assets that can be withdrawn by owner.
**Parameters:**
* `owner`: Address to check withdrawal limit for
**Returns:**
* `uint256`: Maximum withdrawable assets
***
### maxRedeem
```solidity theme={null}
function maxRedeem(address owner) public view override returns (uint256)
```
Returns the maximum amount of shares that can be redeemed by owner.
**Parameters:**
* `owner`: Address to check redemption limit for
**Returns:**
* `uint256`: Maximum redeemable shares
***
### previewDeposit
```solidity theme={null}
function previewDeposit(uint256 assets) public view override returns (uint256)
```
Previews the amount of shares that would be minted for a deposit.
**Parameters:**
* `assets`: Amount of assets to deposit
**Returns:**
* `uint256`: Expected shares to receive
***
### previewMint
```solidity theme={null}
function previewMint(uint256 shares) public view override returns (uint256)
```
Previews the amount of assets required to mint given shares.
**Parameters:**
* `shares`: Amount of shares to mint
**Returns:**
* `uint256`: Required assets amount
***
### previewWithdraw
```solidity theme={null}
function previewWithdraw(uint256 assets) public view override returns (uint256)
```
Previews the amount of shares that would be burned for a withdrawal.
**Parameters:**
* `assets`: Amount of assets to withdraw
**Returns:**
* `uint256`: Shares to be burned
***
### previewRedeem
```solidity theme={null}
function previewRedeem(uint256 shares) public view override returns (uint256)
```
Previews the amount of assets that would be returned for redeeming shares.
**Parameters:**
* `shares`: Amount of shares to redeem
**Returns:**
* `uint256`: Assets to be received
***
## ERC20 Functions
The vault also implements standard ERC20 functions for shares:
* `name()`: Returns vault share token name
* `symbol()`: Returns vault share token symbol
* `decimals()`: Returns decimals (same as underlying asset)
* `totalSupply()`: Returns total vault shares
* `balanceOf(address)`: Returns shares balance of address
* `transfer(address,uint256)`: Transfers shares
* `allowance(address,address)`: Returns transfer allowance
* `approve(address,uint256)`: Approves share transfers
* `transferFrom(address,address,uint256)`: Transfers shares with approval
## Yield and Staking Features
### accrueInterest
```solidity theme={null}
function accrueInterest() external
```
Accrues interest from the underlying lender contract. Must be called before share calculations.
**Effects:**
* Updates vault's asset balance with accrued interest
* Maintains accurate share pricing
***
## Security Considerations
* All state-changing functions accrue interest first
* Share calculations use current total assets
* The first ever depositor forfeits `MIN_SHARES` (1e16 = 0.01 share units) which are burned to `address(0)` to prevent the ERC‑4626 inflation attack
# Overview
Source: https://docs.monolith.market/reference/overview
Complete API reference for all Monolith smart contracts with detailed function specifications
## Contracts
The main contract for deploying new Monolith stablecoins and managing the protocol.
The ERC-20 stablecoin minted by borrowers and the PSM.
The staking vault that allows users to earn yield from protocol fees.
Manages borrowing positions, collateral, and debt accounting for stablecoins.
Autonomous interest rate controller that adjusts rates based borrower choice.
Read-only contract providing convenient access to protocol state.
# Audits
Source: https://docs.monolith.market/security/audits
Security audit history for the Monolith protocol
## Overview
Monolith's core contracts have been independently reviewed by multiple security firms before and after deployment. All findings from completed engagements have been addressed by the development team. The ChainSecurity re-audit final report is pending publication.
The ChainSecurity re-audit report is a pre-publication draft. All other audit reports are linked in the table below.
***
## Audit History
| Auditor | Type | Date | Report |
| ------------------ | ------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| Electisec (yAudit) | Private audit | June 2025 | [View report](https://monolith-public-files.vercel.app/audits/yAudit-Monolith-Report-June-2025.pdf) |
| ChainSecurity | Private audit | October 2025 | [View report](https://monolith-public-files.vercel.app/audits/ChainSecurity-Monolith-Audit-Report-October-2025.pdf) |
| Sherlock | Public contest | December 2025 | [View report](https://monolith-public-files.vercel.app/audits/Sherlock-Monolith-Public-Audit-Contest-Report-December-2025.pdf) |
| ChainSecurity | Re-audit (v5.1) | March–April 2026 | [View report](https://monolith-public-files.vercel.app/audits/ChainSecurity-Monolith-Re-Audit-Report-March-2026.pdf) |
| Sherlock AI | AI-assisted review | April 2026 | [View report](https://monolith-public-files.vercel.app/audits/Sherlock-AI-Monolith-Audit-Report-April-2026.pdf) |
| Nemesis | AI-assisted review | April 2026 | [View report](https://monolith-public-files.vercel.app/audits/Nemesis-Monolith-Audit-Report-April-2026.md) |
| Zellic v12 | AI-assisted review | April 2026 | [View report](https://v12.sh/runs/1892/public) |
***
### Electisec — June 2025
Electisec (formerly yAudit) conducted a private review of the five core Monolith protocol contracts: `Factory.sol`, `Lender.sol`, `Vault.sol`, `InterestModel.sol`, and `Coin.sol`. Two auditors conducted the review over five days, with particular focus on the protocol's novel dual-debt architecture, the interaction between the interest rate model and redeemable borrower positions, and the correctness of interest accrual and liquidation mechanics. All findings were fully resolved prior to deployment.
***
### ChainSecurity — October 2025
ChainSecurity performed an independent code assessment of the Monolith smart contracts, covering the same core contract suite reviewed by Electisec. The assessment examined precision of arithmetic operations, integration with external ERC-4626 vaults, functional correctness of the redemption and liquidation systems, and the trustworthiness of the operator access control model. All findings were addressed by the development team.
***
### Sherlock Public Contest — December 2025
A competitive public audit contest was hosted on Sherlock from December 8–14, 2025, with lead security expert bughuntoor overseeing the engagement. The contest extended the scope to include `src/Lens.sol` alongside the five core contracts, and drew participation from over 100 independent security researchers. All issues identified during the contest were fully resolved prior to deployment.
***
### ChainSecurity Re-audit — March–April 2026
ChainSecurity conducted a re-audit of the Monolith protocol covering material changes made since their initial October 2025 review, including updates introduced across multiple iterative code versions. The engagement incorporated a final audit slot on March 23, 2026. The final report is pending publication.
Pre-disclosure findings from this engagement are confidential until ChainSecurity publishes the final report. This page will be updated with the report link upon release.
***
### Sherlock AI — April 2026
An AI-assisted security review of the Monolith protocol contracts was conducted using Sherlock's automated analysis tooling. The review covered the core contract suite and was run in conjunction with the broader AI audit initiative ahead of deployment.
***
### Nemesis — April 2026
An AI-assisted review was conducted using Nemesis, covering the Monolith protocol contracts. The engagement was part of a multi-tool AI audit initiative run in parallel to complement the human-led audit program.
***
### Zellic v12 — April 2026
An AI-assisted review was conducted using Zellic's v12 automated analysis tooling across the Monolith protocol contracts. The review was run as part of the same April 2026 AI audit initiative alongside Sherlock AI and Nemesis.
***
Learn about our live bug bounty program on Sherlock and how to report vulnerabilities.
Understand the risks associated with using Monolith stablecoins and the protocol.
# Bug Bounty
Source: https://docs.monolith.market/security/bug-bounty
Report security vulnerabilities and earn rewards
## Overview
Monolith runs a live bug bounty program hosted on [Sherlock](https://audits.sherlock.xyz/bug-bounties/287). Security researchers who responsibly disclose valid vulnerabilities in Monolith's smart contracts are eligible for rewards based on severity. All submissions must be made through the Sherlock platform in accordance with their [platform rules](https://docs.sherlock.xyz/bug-bounties/post-launch-bounty/platform-rules).
Submit all vulnerability reports through Sherlock. Do not publicly disclose findings before they are resolved, and do not test on mainnet or public testnets.
***
## Rewards
| Severity | Reward |
| ------------------- | ---------------- |
| Critical | $5,000 – $20,000 |
| High | \$3,000 |
| Medium | \$1,000 |
| Low / Informational | $250 – $500 |
Reward amounts within ranges are determined at the discretion of the Monolith team based on the actual impact, exploitability, and quality of the report. Rewards are paid in DOLA. Duplicate submissions — where the same vulnerability has already been reported — are not eligible for a reward.
***
## Assets in Scope
The following contracts are in scope for the bug bounty program:
* `Factory.sol`
* `Coin.sol`
* `InterestModel.sol`
* `Vault.sol`
* `Lender.sol`
Only contracts explicitly listed in the active Sherlock program page are considered in scope. Scope is updated to reflect new deployments and to remove deprecated contracts as the protocol evolves.
***
## Impacts in Scope
### Critical
* Direct theft of user funds or collateral
* Protocol insolvency or permanent loss of funds
* Unauthorized minting of stablecoins
* Permanent freezing of user funds
### High
* Temporary freezing of funds
* Significant disruption to liquidations or redemptions
* Material miscalculation of borrowing power or debt
### Medium
* Smart contract unable to operate due to missing token funds
* Griefing attacks causing damage without direct profit motive
* Theft of gas or unbounded gas consumption
### Low / Informational
* Contract fails to deliver promised returns without loss of principal
* Edge case behavior inconsistent with specification
***
## Out of Scope
The following are not eligible for rewards:
* Attacks requiring access to leaked keys or privileged addresses
* Oracle manipulation where the reporter did not cause the depeg through a code bug
* Issues already disclosed in a prior audit report
* Best practice recommendations or feature requests
* Impacts requiring attacks the researcher has already exploited themselves
* Any testing conducted on mainnet or public testnet
* Social engineering, phishing, or denial-of-service attacks
* Third-party infrastructure not controlled by the Monolith protocol
***
## Previous Audits
The following audits have been completed. Issues identified in these reports are out of scope for the bug bounty program.
| Auditor | Type | Date | Report |
| ------------------ | ------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| Electisec (yAudit) | Private audit | June 2025 | [View report](https://monolith-public-files.vercel.app/audits/yAudit-Monolith-Report-June-2025.pdf) |
| ChainSecurity | Private audit | October 2025 | [View report](https://monolith-public-files.vercel.app/audits/ChainSecurity-Monolith-Audit-Report-October-2025.pdf) |
| Sherlock | Public contest | December 2025 | [View report](https://monolith-public-files.vercel.app/audits/Sherlock-Monolith-Public-Audit-Contest-Report-December-2025.pdf) |
| ChainSecurity | Re-audit (v5.1) | March–April 2026 | [View report](https://monolith-public-files.vercel.app/audits/ChainSecurity-Monolith-Re-Audit-Report-March-2026.pdf) |
| Sherlock AI | AI-assisted review | April 2026 | [View report](https://monolith-public-files.vercel.app/audits/Sherlock-AI-Monolith-Audit-Report-April-2026.pdf) |
| Nemesis | AI-assisted review | April 2026 | [View report](https://monolith-public-files.vercel.app/audits/Nemesis-Monolith-Audit-Report-April-2026.md) |
| Zellic v12 | AI-assisted review | April 2026 | [View report](https://v12.sh/runs/1892/public) |
***
## Rules
All participants must adhere to Sherlock's [platform rules](https://docs.sherlock.xyz/bug-bounties/post-launch-bounty/platform-rules). Key requirements:
* All testing must be conducted on local forks — never on mainnet or public testnet
* Do not publicly disclose vulnerabilities before they are resolved
* Do not exploit discovered vulnerabilities or threaten to do so
* Submit all reports through the official Sherlock channel
* Do not communicate with the protocol team outside of Sherlock's platform
***
## How to Submit
Submissions are made directly through the Sherlock bug bounty platform. Sherlock manages the triage and dispute resolution process. Reports should include a clear description of the vulnerability, the affected contracts and functions, steps to reproduce, and an assessment of potential impact. A proof of concept is strongly encouraged.
Publicly known bugs or issues reported in a previous audit are not eligible for a payout. Ensure your finding is novel before submitting.
***
## Direct Disclosure
Under extraordinary circumstances, researchers may contact the Monolith team directly before submitting through Sherlock — for example, in cases of active exploitation risk. In such cases, reach out via the [Inverse Finance Discord](https://discord.gg/CrkzvpGMz) prior to submission to discuss the appropriate channel. Direct submissions are evaluated on a case-by-case basis and do not guarantee a reward outside the standard Sherlock process.
Review completed and ongoing third-party security audits.
Understand the risks associated with using the Monolith protocol.
# Overview
Source: https://docs.monolith.market/security/overview
Security audits, bug bounty program, and risk disclosures for the Monolith protocol
## Security at Monolith
Security is treated as a foundational design constraint rather than an afterthought. Monolith's contract architecture is intentionally minimal and its immutability model is designed to reduce the ongoing attack surface over time — once a deployed instance reaches its immutability deadline, its core monetary policy parameters lock permanently, eliminating a broad class of governance and upgrade risk.
Monolith's core protocol contracts have been reviewed across four independent security engagements: a private audit by Electisec, an initial private assessment by ChainSecurity, a public audit contest on Sherlock, and a re-audit by ChainSecurity covering all subsequent protocol changes. The ChainSecurity re-audit final report is pending publication.
A live bug bounty program is hosted on Sherlock.
***
## Security Documentation
Review third-party security audits and code reviews conducted on Monolith smart contracts.
Learn about our live bug bounty program on Sherlock and how to report vulnerabilities.
Understand the risks associated with using Monolith stablecoins and the protocol.
# Risks
Source: https://docs.monolith.market/security/risks
Understanding the risks involved with using Monolith
## Overview
Using Monolith involves real financial risk. This page documents the material risks specific to the protocol's design. It is not exhaustive — DeFi carries inherent risks beyond any single protocol's control. Users should understand these risks fully before borrowing, staking, or holding Monolith stablecoins.
This is not financial advice. Only deploy capital you are prepared to lose. Always verify contract addresses independently before interacting with any Monolith instance.
***
## Smart Contract Risk
Despite audits by Electisec and a completed re-audit by ChainSecurity, no smart contract review eliminates the possibility of undiscovered vulnerabilities. Bugs in core contracts — including the Factory, Lender, Vault, or interest rate model — could result in loss of user funds. Complexity in how contracts interact increases the surface area for unexpected behavior.
***
## Oracle Risk
Monolith relies on external price feeds to value collateral and determine liquidation eligibility. A manipulated, stale, or failed oracle can cause incorrect liquidations or allow over-borrowing. Users should be aware of the specific price feed used by any instance they interact with and understand its update frequency and reliability properties.
***
## Liquidation Risk
Borrowers whose collateral falls below the required threshold will have their position liquidated. In fast-moving markets, collateral value can decline faster than a borrower can respond. Partial or full liquidation reduces the amount of stablecoin debt but also permanently reduces the borrower's collateral position. There is no grace period — liquidations are permissionless and can be triggered by any party at any time threshold conditions are met.
***
## Redemption Risk (0% Borrowing Mode)
Borrowers who use the 0% interest rate mode accept the risk of redemption. Any holder of the stablecoin can redeem their tokens directly against the collateral of a specified borrower in redeemable status. Redemptions improve the overall health of the loan book by targeting borrowers and repaying their debt, but the affected borrower will have their collateral reduced in exchange. Borrowers who wish to avoid redemption risk should switch to the variable rate borrowing mode, which provides full protection from redemptions.
***
## Interest Rate Risk (Variable Borrowing Mode)
Borrowers in the variable rate mode are protected from redemptions but face a dynamically adjusted borrow rate. The autonomous interest rate controller adjusts rates to defend the stablecoin's peg. In periods of significant peg pressure, rates may rise substantially. Borrowers should account for variable rate exposure when sizing positions.
***
## Collateral Concentration Risk
Each Monolith instance is backed by a single collateral asset. Unlike diversified lending pools, there is no cross-collateralization — the solvency of the stablecoin depends entirely on the price stability and liquidity of that one asset. A severe decline or illiquidity event in the collateral asset can impair the stablecoin's peg and result in bad debt.
***
## Bad Debt Risk
In extreme scenarios where a position becomes deeply undercollateralized and cannot be fully liquidated, the resulting bad debt is socialized across all active borrowers in the system — both variable rate and 0% mode borrowers — proportionally. This reduces the debt burden of the bad debt position at the cost of increasing the effective debt of other borrowers. Users should be aware that the financial health of the overall borrower pool affects their own position.
***
## Immutability Risk
Monolith's immutability model is a feature, but it carries its own considerations. Before the immutability deadline, an instance operator retains the ability to adjust certain parameters, including interest model knobs and redemption fees. Users should be aware of whether the instance they are using has reached its immutability deadline. After the deadline passes (or `enableImmutabilityNow()` is called), the operator loses all policy-level access permanently — meaning a discovered misconfiguration cannot be corrected.
***
## Factory and Instance Legitimacy Risk
Anyone can deploy a Monolith stablecoin instance through the Factory. Not all instances are created or endorsed by the Monolith core team. Users must independently verify the legitimacy of any instance they interact with, including reviewing the collateral asset, price feed, operator configuration, and immutability status. Interacting with an unverified or malicious instance carries significant risk.
***
## Network and Gas Risk
Liquidations, redemptions, and debt management actions require on-chain transactions. During periods of high Ethereum network congestion, gas costs may be prohibitive and transaction confirmation may be delayed. This can affect a borrower's ability to add collateral or repay debt before a liquidation or redemption event occurs.
***
## Mitigation
These risks are not unique to Monolith, but they are real. Users are encouraged to maintain conservative collateral ratios, monitor their positions actively, review the audit history for any instance they use, and stay current with protocol communications.
Review the security audits covering Monolith's smart contracts.
Report potential vulnerabilities through our Sherlock bug bounty program.
# Safe Harbor
Source: https://docs.monolith.market/security/safe-harbor
SEAL Whitehat Safe Harbor Agreement
## Overview
Monolith has adopted the [SEAL Whitehat Safe Harbor Agreement](https://securityalliance.org/safe-harbor), a legal framework developed by the Security Alliance that authorizes ethical security researchers to intervene during active exploits in order to rescue user funds.
Under this framework, whitehats who detect an ongoing attack may take emergency action to recover funds on behalf of affected users. In exchange for a successful rescue, the whitehat is entitled to a bounty deducted from the recovered assets. The agreement provides legal protection to both the rescuing whitehat and the protocol community, and establishes clear rules governing when and how rescue attempts may occur.
Monolith's adoption was governed by the Inverse Finance DAO governance proposal available [here](https://www.inverse.finance/governance/proposals/mills/357).
Safe Harbor does not replace or modify the standard bug bounty program. It applies exclusively to scenarios involving active, ongoing exploitation of the protocol.
***
## How It Works
When an active exploit is detected, an authorized whitehat may:
1. Intervene to halt or redirect the exploit
2. Recover funds on behalf of affected users
3. Receive a bounty deducted from the rescued assets as compensation
The rescued funds are returned to the protocol or to affected users. The bounty percentage and eligibility conditions are governed by the terms of the Whitehat Agreement. Whitehat actions taken in good faith under this framework are granted legal safe harbor — meaning the protocol community agrees not to pursue legal action against them for conduct covered by the agreement.
***
## User Agreement
By depositing assets into the Monolith protocol, users acknowledge and agree to the terms of the Safe Harbor Agreement as set out below.
### Exhibit D: User Adoption Procedures
**User Agreement to be Bound By Agreement, Consent to Attempted Eligible Funds Rescues and Payment of Bounties**
The User hereby acknowledges and agrees to, and consents to be bound by the terms and conditions of, that certain Safe Harbor Agreement for Whitehats, adopted by the Inverse Finance DAO on March 5th, 2025 (the "Whitehat Agreement"), available [here](https://www.inverse.finance/governance/proposals/mills/357), as a "User" and member of the "Protocol Community" thereunder. Without limiting the generality of the foregoing:
* the User hereby consents to Whitehats attempting Eligible Funds Rescues of any and all Tokens deposited into the Protocol by the User and the deduction of Bounties out of User's deposited Tokens to compensate Eligible Whitehats for successful Eligible Funds Rescues;
* the User acknowledges and agrees that Tokens may be lost, stolen, suffer diminished value, or become disabled or frozen in connection with attempts at Eligible Funds Rescues, and assumes all the risk of the foregoing;
* the User acknowledges and agrees that payment of the Bounty as a deduction from User's Tokens to an Eligible Whitehat may constitute a taxable disposition by the User of the deducted Tokens, and agrees to assume all risk of such adverse tax treatment; and
* the User agrees to hold the other Protocol Community Members harmless from any loss, liability or other damages suffered by the User in connection with attempted Eligible Funds Rescues under the Whitehat Agreement.
***
## Further Reading
* [SEAL Safe Harbor Agreement](https://securityalliance.org/safe-harbor) — full agreement text and program details
* [Governance Proposal](https://www.inverse.finance/governance/proposals/mills/357) — Inverse Finance DAO adoption proposal
Report vulnerabilities and earn rewards through the Sherlock bug bounty program.
Review completed and ongoing third-party security audits.