LendController
The LendController is the primary user-facing contract for each lending market. Borrowers interact with it to create loans, manage collateral, borrow more, repay, and get liquidated. It wraps the core controller.vy module — which contains all shared loan logic — and extends it with lending-specific features: borrow caps, vault token transfers, and available balance tracking.
Each lending market gets its own LendController instance, deployed by the LendFactory.
LendController.vyThe source code for the LendController.vy contract can be found on GitHub. The core module is controller.vy. The contract is written in Vyper version 0.4.3.
Deployment addresses will be added once contracts are finalized.
The LendController exports most of its functions from the controller.vy module. Functions documented below include both module-exported functions and lending-specific extensions. The module pattern means the core loan logic is shared with MintController (used for crvUSD mint markets).
Loan Management
create_loan
LendController.create_loan(_collateral: uint256, _debt: uint256, _N: uint256)Creates a new loan by depositing collateral and borrowing tokens. The collateral is distributed across _N bands in the AMM.
| Input | Type | Description |
|---|---|---|
_collateral | uint256 | Amount of collateral to deposit |
_debt | uint256 | Amount of borrowed tokens to receive |
_N | uint256 | Number of bands to distribute collateral across (4–50) |
Emits: Borrow event.
<>Source code▼
▶Example▼
borrow_more
LendController.borrow_more(_d_collateral: uint256, _d_debt: uint256)Adds additional collateral and/or borrows more tokens against an existing loan.
| Input | Type | Description |
|---|---|---|
_d_collateral | uint256 | Additional collateral to deposit (can be 0) |
_d_debt | uint256 | Additional debt to take on (can be 0) |
Emits: Borrow event.
<>Source code▼
▶Example▼
add_collateral
LendController.add_collateral(_d_collateral: uint256, _for: address)Adds collateral to an existing loan without borrowing more. Can be called by anyone on behalf of a borrower.
| Input | Type | Description |
|---|---|---|
_d_collateral | uint256 | Amount of collateral to add |
_for | address | Address of the borrower to add collateral for |
Emits: Borrow event.
<>Source code▼
▶Example▼
remove_collateral
LendController.remove_collateral(_d_collateral: uint256)Removes collateral from an existing loan. Reverts if the resulting health would be too low.
| Input | Type | Description |
|---|---|---|
_d_collateral | uint256 | Amount of collateral to remove |
Emits: RemoveCollateral event.
<>Source code▼
▶Example▼
repay
LendController.repay(_d_debt: uint256, _for: address)Repays debt for a loan. If _d_debt exceeds the current debt, only the outstanding debt is repaid. Can be called by anyone on behalf of a borrower.
| Input | Type | Description |
|---|---|---|
_d_debt | uint256 | Amount of debt to repay (use max_value(uint256) to repay all) |
_for | address | Address of the borrower to repay for |
Emits: Repay event.
<>Source code▼
▶Example▼
liquidate
LendController.liquidate(_user: address, _min_x: uint256)Liquidates an unhealthy loan (health < 0). The caller repays the debt and receives the remaining collateral. Supports partial liquidation if the position is partially in soft liquidation.
| Input | Type | Description |
|---|---|---|
_user | address | Address of the borrower to liquidate |
_min_x | uint256 | Minimum amount of collateral to receive (slippage protection) |
Emits: Liquidate event.
<>Source code▼
▶Example▼
Loan Info
debt
LendController.debt(_user: address) -> uint256: viewReturns the current debt of a user, including accrued interest.
| Input | Type | Description |
|---|---|---|
_user | address | Borrower address |
Returns: current debt (uint256).
<>Source code▼
▶Example▼
health
LendController.health(_user: address, _full: bool) -> int256: viewReturns the health of a user's loan. Health > 0 means the loan is safe; health < 0 means it can be liquidated. If _full is true, returns health assuming the worst-case scenario where all collateral has been soft-liquidated.
| Input | Type | Description |
|---|---|---|
_user | address | Borrower address |
_full | bool | If true, use full (pessimistic) health calculation |
Returns: health value (int256).
<>Source code▼
▶Example▼
loan_exists
LendController.loan_exists(_user: address) -> bool: viewReturns whether a loan exists for the given user.
| Input | Type | Description |
|---|---|---|
_user | address | Borrower address |
Returns: whether the loan exists (bool).
<>Source code▼
▶Example▼
user_state
LendController.user_state(_user: address) -> uint256[4]: viewReturns the full state of a user's loan: [collateral, stablecoin, debt, N].
| Input | Type | Description |
|---|---|---|
_user | address | Borrower address |
Returns: [collateral, stablecoin, debt, N] (uint256[4]).
<>Source code▼
▶Example▼
user_prices
LendController.user_prices(_user: address) -> uint256[2]: viewReturns the upper and lower price bounds of a user's collateral bands in the AMM.
| Input | Type | Description |
|---|---|---|
_user | address | Borrower address |
Returns: [price_upper, price_lower] (uint256[2]).
<>Source code▼
▶Example▼
users_to_liquidate
LendController.users_to_liquidate(_from: uint256, _limit: uint256) -> IController.Position[]: viewReturns a list of user positions that can be liquidated, paginated.
| Input | Type | Description |
|---|---|---|
_from | uint256 | Starting index |
_limit | uint256 | Maximum number of positions to return |
Returns: array of liquidatable positions (IController.Position[]).
<>Source code▼
▶Example▼
tokens_to_liquidate
LendController.tokens_to_liquidate(_user: address) -> uint256: viewReturns the amount of borrowed tokens needed to fully liquidate a user's position.
| Input | Type | Description |
|---|---|---|
_user | address | Borrower address |
Returns: tokens needed for liquidation (uint256).
<>Source code▼
▶Example▼
total_debt
LendController.total_debt() -> uint256: viewReturns the total outstanding debt across all loans in this market, including accrued interest.
Returns: total debt (uint256).
<>Source code▼
▶Example▼
n_loans
LendController.n_loans() -> uint256: viewReturns the total number of active loans.
Returns: number of loans (uint256).
<>Source code▼
▶Example▼
loans
LendController.loans(_index: uint256) -> address: viewReturns the borrower address at a given loan index.
| Input | Type | Description |
|---|---|---|
_index | uint256 | Loan index |
Returns: borrower address (address).
<>Source code▼
▶Example▼
loan_ix
LendController.loan_ix(_user: address) -> uint256: viewReturns the index of a user's loan in the loans array.
| Input | Type | Description |
|---|---|---|
_user | address | Borrower address |
Returns: loan index (uint256).
<>Source code▼
▶Example▼
Health Previews
These functions allow UIs to show the health impact of operations before the user submits a transaction.
create_loan_health_preview
LendController.create_loan_health_preview(_user: address, _collateral: uint256, _debt: uint256, _N: uint256, _full: bool) -> int256: viewPreviews the health of a loan that would result from calling create_loan.
| Input | Type | Description |
|---|---|---|
_user | address | Borrower address |
_collateral | uint256 | Collateral amount |
_debt | uint256 | Debt amount |
_N | uint256 | Number of bands |
_full | bool | Full (pessimistic) health |
Returns: predicted health (int256).
<>Source code▼
▶Example▼
borrow_more_health_preview
LendController.borrow_more_health_preview(_user: address, _d_collateral: uint256, _d_debt: uint256, _full: bool) -> int256: viewPreviews the health after borrowing more.
| Input | Type | Description |
|---|---|---|
_user | address | Borrower address |
_d_collateral | uint256 | Additional collateral |
_d_debt | uint256 | Additional debt |
_full | bool | Full (pessimistic) health |
Returns: predicted health (int256).
<>Source code▼
▶Example▼
add_collateral_health_preview
LendController.add_collateral_health_preview(_user: address, _d_collateral: uint256, _full: bool) -> int256: viewPreviews the health after adding collateral.
| Input | Type | Description |
|---|---|---|
_user | address | Borrower address |
_d_collateral | uint256 | Collateral to add |
_full | bool | Full (pessimistic) health |
Returns: predicted health (int256).
<>Source code▼
▶Example▼
remove_collateral_health_preview
LendController.remove_collateral_health_preview(_user: address, _d_collateral: uint256, _full: bool) -> int256: viewPreviews the health after removing collateral.
| Input | Type | Description |
|---|---|---|
_user | address | Borrower address |
_d_collateral | uint256 | Collateral to remove |
_full | bool | Full (pessimistic) health |
Returns: predicted health (int256).
<>Source code▼
▶Example▼
repay_health_preview
LendController.repay_health_preview(_user: address, _d_debt: uint256, _full: bool) -> int256: viewPreviews the health after repaying debt.
| Input | Type | Description |
|---|---|---|
_user | address | Borrower address |
_d_debt | uint256 | Debt to repay |
_full | bool | Full (pessimistic) health |
Returns: predicted health (int256).
<>Source code▼
▶Example▼
liquidate_health_preview
LendController.liquidate_health_preview(_user: address, _full: bool) -> int256: viewPreviews what a user's health would be after liquidation.
| Input | Type | Description |
|---|---|---|
_user | address | Borrower address |
_full | bool | Full (pessimistic) health |
Returns: predicted health (int256).
<>Source code▼
▶Example▼
Lending-Specific
These functions are unique to LendController and not part of the shared controller.vy module.
available_balance
LendController.available_balance() -> uint256: viewReturns the amount of borrowed tokens currently available for new loans — i.e., the tokens deposited by lenders minus what's already lent out.
Returns: available balance (uint256).
<>Source code▼
▶Example▼
borrow_cap
LendController.borrow_cap() -> uint256: viewReturns the maximum total debt allowed for this market. If 0, there is no cap.
Returns: borrow cap (uint256).
<>Source code▼
▶Example▼
vault
LendController.vault() -> address: viewReturns the address of the associated ERC4626 vault.
Returns: vault address (address).
<>Source code▼
▶Example▼
set_borrow_cap
LendController.set_borrow_cap(_borrow_cap: uint256)This function is only callable by the factory admin.
Sets the maximum total debt cap for this market.
| Input | Type | Description |
|---|---|---|
_borrow_cap | uint256 | New borrow cap (0 = unlimited) |
Emits: SetBorrowCap event.
<>Source code▼
▶Example▼
set_admin_percentage
LendController.set_admin_percentage(_admin_percentage: uint256)This function is only callable by the factory admin.
Sets the percentage of interest that goes to the protocol (admin fees) rather than lenders.
| Input | Type | Description |
|---|---|---|
_admin_percentage | uint256 | Admin fee percentage (scaled, max 50%) |
Emits: SetAdminPercentage event.
<>Source code▼
▶Example▼
Calculations
max_borrowable
LendController.max_borrowable(_d_collateral: uint256, _N: uint256, _user: address) -> uint256: viewReturns the maximum amount that can be borrowed given a collateral amount and number of bands, respecting the borrow cap and available balance.
| Input | Type | Description |
|---|---|---|
_d_collateral | uint256 | Collateral amount |
_N | uint256 | Number of bands |
_user | address | Borrower address (for existing loan context) |
Returns: max borrowable amount (uint256).
<>Source code▼
▶Example▼
min_collateral
LendController.min_collateral(_d_debt: uint256, _N: uint256) -> uint256: viewReturns the minimum collateral required for a given debt amount and number of bands.
| Input | Type | Description |
|---|---|---|
_d_debt | uint256 | Desired debt amount |
_N | uint256 | Number of bands |
Returns: minimum collateral required (uint256).
<>Source code▼
▶Example▼
calculate_debt_n1
LendController.calculate_debt_n1(_collateral: uint256, _debt: uint256, _N: uint256) -> int256: viewCalculates the upper band number (n1) for a loan with the given parameters. Used to determine where collateral will be placed in the AMM.
| Input | Type | Description |
|---|---|---|
_collateral | uint256 | Collateral amount |
_debt | uint256 | Debt amount |
_N | uint256 | Number of bands |
Returns: upper band number (int256).
<>Source code▼
▶Example▼
Configuration
set_amm_fee
LendController.set_amm_fee(_fee: uint256)This function is only callable by the factory admin.
Sets the swap fee on the associated AMM.
| Input | Type | Description |
|---|---|---|
_fee | uint256 | New fee value |
<>Source code▼
▶Example▼
set_borrowing_discounts
LendController.set_borrowing_discounts(_loan_discount: uint256, _liquidation_discount: uint256)This function is only callable by the factory admin.
Sets the loan discount and liquidation discount. The loan discount determines the maximum LTV, and the liquidation discount determines the threshold for liquidation.
| Input | Type | Description |
|---|---|---|
_loan_discount | uint256 | New loan discount |
_liquidation_discount | uint256 | New liquidation discount |
Emits: SetBorrowingDiscounts event.
<>Source code▼
▶Example▼
set_monetary_policy
LendController.set_monetary_policy(_monetary_policy: address)This function is only callable by the factory admin.
Sets the monetary policy contract that determines the borrow rate.
| Input | Type | Description |
|---|---|---|
_monetary_policy | address | New monetary policy address |
Emits: SetMonetaryPolicy event.
<>Source code▼
▶Example▼
set_price_oracle
LendController.set_price_oracle(_price_oracle: address)This function is only callable by the factory admin.
Sets the price oracle for this market.
| Input | Type | Description |
|---|---|---|
_price_oracle | address | New price oracle address |
<>Source code▼
▶Example▼
set_callback
LendController.set_callback(_callback: address)This function is only callable by the factory admin.
Sets the liquidity mining callback (gauge) for the AMM.
| Input | Type | Description |
|---|---|---|
_callback | address | Liquidity mining callback address |
Emits: SetLMCallback event.
<>Source code▼
▶Example▼
Other Methods
amm
LendController.amm() -> address: viewReturns the AMM (LLAMMA) address for this market.
Returns: AMM address (address).
<>Source code▼
▶Example▼
amm_price
LendController.amm_price() -> uint256: viewReturns the current price from the AMM's internal oracle.
Returns: AMM price (uint256).
<>Source code▼
▶Example▼
monetary_policy
LendController.monetary_policy() -> address: viewReturns the current monetary policy address.
Returns: monetary policy address (address).
<>Source code▼
▶Example▼
liquidation_discount
LendController.liquidation_discount() -> uint256: viewReturns the current liquidation discount.
Returns: liquidation discount (uint256).
<>Source code▼
▶Example▼
loan_discount
LendController.loan_discount() -> uint256: viewReturns the current loan discount.
Returns: loan discount (uint256).
<>Source code▼
▶Example▼
admin_fees
LendController.admin_fees() -> uint256: viewReturns the amount of uncollected admin fees.
Returns: admin fees (uint256).
<>Source code▼
▶Example▼
admin_percentage
LendController.admin_percentage() -> uint256: viewReturns the current admin fee percentage.
Returns: admin percentage (uint256).
<>Source code▼
▶Example▼
collect_fees
LendController.collect_fees()Collects accumulated admin fees and sends them to the fee receiver set in the factory.
Emits: CollectFees event.
<>Source code▼
▶Example▼
save_rate
LendController.save_rate()Updates the stored interest rate from the monetary policy. This is called automatically during loan operations but can also be called externally to keep the rate fresh.
<>Source code▼
▶Example▼
version
LendController.version() -> String[10]: viewReturns the contract version string (e.g., "2.0.0-lend").
Returns: version string (String[10]).
<>Source code▼
▶Example▼
factory
LendController.factory() -> address: viewReturns the factory that deployed this controller.
Returns: factory address (address).