Antler by Autoflux

Lending

Manages deposit, borrow, and repay operations with dynamic interest rate models.

Path: lending

Third-party documentation. This is independently authored analysis of the public Aurum Protocol codebase — not the official docs, and not reviewed or endorsed by the Aurum Protocol team.

Lending Module

The Lending module is the primary user-facing interface for capital deployment. Users deposit assets as collateral and borrow against them at algorithmically-set rates.

Interest Rate Model

Rates follow a two-kink piecewise linear curve:

  • 0–70% utilisation: base rate (2% APR)
  • 70–90% utilisation: base + multiplier (ramps to 20% APR)
  • 90–100% utilisation: jump multiplier (ramps to 150% APR)

This creates natural pressure to keep pool utilisation below the first kink, protecting liquidity for withdrawals.

Accrual

Interest accrues per-second using continuous compounding: balance × e^(rate × Δt). The accrueInterest() function must be called (by any account) before any state-changing operation to sync the accumulator.

Examples

Full deposit-and-borrow flow

Full deposit-and-borrow flow
typescript
// 1. Approve the lending module to pull USDC
await usdc.approve(lending.address, depositAmount);
 
// 2. Deposit collateral
await lending.deposit(USDC_ADDRESS, depositAmount);
console.log("Deposited", ethers.formatUnits(depositAmount, 6), "USDC");
 
// 3. Borrow ETH against it (70% LTV)
const borrowAmt = depositAmount * 70n / 100n;
await lending.borrow(WETH_ADDRESS, borrowAmt);
console.log("Borrowed", ethers.formatEther(borrowAmt), "ETH");
STATUSexample

The canonical flow for opening a leveraged position.

Repay full debt with permit

Repay full debt with permit
typescript
// Use type(uint256).max to repay all outstanding debt
const sig = await signPermit(signer, weth, lending.address, type(uint256).max);
await lending.repayWithPermit(WETH_ADDRESS, type(uint256).max, sig);
console.log("Debt fully cleared");
STATUSexample

Repay without a prior approve transaction using EIP-2612 permit.

Edge Cases

  • borrow() reverts if resulting health-factor < 1.05 (5% safety buffer)
  • withdraw() reverts if the withdrawal would drop health-factor below 1.0
  • Depositing a delisted asset still succeeds — only borrowing is blocked for delisted assets
  • accrueInterest() is idempotent within the same block

Interface

Interface
solidity
interface ILending {
/// @notice Deposit asset as collateral
function deposit(address asset, uint256 amount) external;
 
/// @notice Withdraw previously deposited collateral
function withdraw(address asset, uint256 amount) external;
 
/// @notice Borrow asset against existing collateral
function borrow(address asset, uint256 amount) external;
 
/// @notice Repay outstanding debt (use type(uint256).max to repay all)
function repay(address asset, uint256 amount) external;
 
/// @notice Sync interest accumulator — must precede any state mutation
function accrueInterest(address asset) external;
 
/// @notice Current borrow APR for an asset (1e18 = 100%)
function borrowRate(address asset) external view returns (uint256);
 
event Deposited(address indexed user, address indexed asset, uint256 amount);
event Borrowed(address indexed user, address indexed asset, uint256 amount);
event Repaid(address indexed user, address indexed asset, uint256 amount);
}
 
STATUSinterface