Skip to main content

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

ContractRole
FactoryDeploys new instances; manages protocol fees
LenderPer-instance core: borrow, repay, liquidate, redeem, PSM
CoinPer-instance ERC‑20 stablecoin
VaultPer-instance ERC‑4626 staked vault (yield-bearing)
LensRead-only helpers (preview redeem, synced debt)
MetadataPer-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.