Documentation Index
Fetch the complete documentation index at: https://docs.monolith.market/llms.txt
Use this file to discover all available pages before exploring further.
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 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.
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 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.
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:
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:
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.
// 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.
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):
interface ILens {
function previewRedeem(address lender, address borrower, uint256 amountIn)
external view returns (uint256 coinIn, uint256 amountOut);
}
See 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).
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.
// 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
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.
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 for the full list.
JavaScript example (ethers v6)
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.