# Lend

Every graduated token has its own lending pool (`AtomicIsolatedLendingPool`) with two assets: **asset 0 is the quote** (ETH or USDG, borrowed by longs) and **asset 1 is the token** (borrowed by shorts). Lenders deposit either asset, receive pool shares, and earn the funding traders pay. Each pool is separate: a loss in one token's pool does not touch another.

## What lenders earn and risk

- **Income:** funding paid by positions (the borrow rate plus the skew premium), added to the pool's assets on close and on `extend`. Shares grow in value; there is no separate reward to claim. Each position's funding earns evenly from open to the end of its paid term, so a new deposit shares only in what is earned after it and a withdrawal keeps what was earned before it; if a position cannot pay its funding, that amount comes off the share value at once.
- **Borrow rate** depends on utilization `U = borrowed / (cash + borrowed)`: 5% APR at 0, rising to 20% at 70%, then steeply to 320% at 100%. `borrowRateBps(asset, 0)` shows it now.
- **Risk:** liquidations are designed so that the trader's margin covers the debt, but there is no reserve fund. A bug or an extreme market can leave the pool with a loss, which is shared by all of that asset's shares. A token deposit also carries the token's own price risk.
- **Withdrawal is two steps** with a delay (`WITHDRAW_DELAY()`, read it), and pays only from free (not lent out) liquidity.
- The 20% of graduation funds seeded into the pool belong to the protocol and are never withdrawn.

## Preconditions

- A wallet that signs on Robinhood Chain (chain id 4663) with ETH for gas, and the asset to deposit.
- The pool address: `marketOf(token).lending` on `AtomicMarginTrading`, or `lendingPools` in the indexer GraphQL ([read-data.md](https://atomic.green/agents/read-data.md)). Confirm that `token()` of the pool is your token.

## Functions (lending pool)

```solidity
function deposit(uint8 asset, uint256 amount, address receiver) payable returns (uint256 shares)  // ETH: value = amount
function requestWithdraw(uint8 asset, uint256 shares) returns (uint256 requestId)
function cancelWithdraw(uint256 requestId)
function executeWithdraw(uint256 requestId) returns (uint256 assets)   // after readyAt
function withdrawRequest(uint256 requestId) view returns (address owner, uint8 asset, uint256 shares, uint256 assetsAtRequest, uint64 readyAt)
function sharesOf(address user, uint8 asset) view returns (uint256)
function convertToAssets(uint8 asset, uint256 shares) view returns (uint256)
function totalAssets(uint8 asset) view returns (uint256)     // cash + borrowed
function totalBorrowed(uint8 asset) view returns (uint256)
function freeLiquidity(uint8 asset) view returns (uint256)
function utilizationBps(uint8 asset) view returns (uint256)
function borrowRateBps(uint8 asset, uint256 extraBorrow) view returns (uint256 aprBps)
function WITHDRAW_DELAY() view returns (uint256)
function token() view returns (address)
function quote() view returns (address)
```

## Deposit

1. Choose the asset: 0 (quote) or 1 (token).
2. ETH: `value = amount`. USDG or the token: `approve(pool, amount)` on that ERC-20 (exactly `amount`), then `value = 0`.
3. Simulate `deposit(asset, amount, yourAddress)` from your address; the result is the shares you will receive (zero shares reverts).
4. Send. Your position: `sharesOf(you, asset)` and its value `convertToAssets(asset, shares)`.

## Withdraw

1. Shares to redeem: all of `sharesOf(you, asset)`, or `shares × wanted / convertToAssets(asset, shares)` for part.
2. `requestWithdraw(asset, shares)`. The shares leave your balance now and the amount is fixed at that moment (`assetsAtRequest`). Keep the `requestId` (the call's result, or the `WithdrawRequested` event, or `lendingWithdrawals(where:{user:"0x…"})` in GraphQL).
3. After `readyAt` (from `withdrawRequest(requestId)`), call `executeWithdraw(requestId)`. It pays `min(assetsAtRequest, value now)`.
4. `InsufficientLiquidity`: that much is lent out right now. Wait for positions to close, or cancel with `cancelWithdraw(requestId)` (your shares come back) and request less (check `freeLiquidity(asset)`).

## Example (TypeScript, viem)

Deposits 0.001 ETH into the quote side of a graduated token's pool.

```ts
import { createPublicClient, http, parseAbi, parseEther } from "viem";
import { robinhood as chain } from "viem/chains";

const client = createPublicClient({ chain, transport: http("https://rpc.mainnet.chain.robinhood.com") });
const net = (await (await fetch("https://atomic.green/agents/deployments.json")).json()).networks.find((n: any) => n.chainId === 4663);
const TRADING = net.contracts.AtomicMarginTrading;
const token = "0x…a graduated token from /launches, lowercase…";
const me = "0x…your address…";

const tradingAbi = parseAbi([
  "struct Market { bool tokenIsCurrency0; address quote; address lending; bytes32 poolId; uint24 fee; int24 tickSpacing; uint64 enabledAt; }",
  "function marketOf(address token) view returns (bool ok, Market m)",
]);
const poolAbi = parseAbi([
  "function token() view returns (address)",
  "function borrowRateBps(uint8 asset, uint256 extraBorrow) view returns (uint256)",
  "function utilizationBps(uint8 asset) view returns (uint256)",
  "function deposit(uint8 asset, uint256 amount, address receiver) payable returns (uint256 shares)",
]);

const [ok, market] = await client.readContract({ address: TRADING, abi: tradingAbi, functionName: "marketOf", args: [token] });
if (!ok) throw new Error("no lending pool");
const pool = market.lending;
const [poolToken, apr, utilization] = await Promise.all([
  client.readContract({ address: pool, abi: poolAbi, functionName: "token" }),
  client.readContract({ address: pool, abi: poolAbi, functionName: "borrowRateBps", args: [0, 0n] }),
  client.readContract({ address: pool, abi: poolAbi, functionName: "utilizationBps", args: [0] }),
]);
if (poolToken.toLowerCase() !== token) throw new Error("pool does not belong to this token");
console.log({ pool, borrowAprPercent: Number(apr) / 100, utilizationPercent: Number(utilization) / 100 });

const amount = parseEther("0.001");
const { request, result: shares } = await client.simulateContract({
  account: me, address: pool, abi: poolAbi, functionName: "deposit", args: [0, amount, me], value: amount });
console.log("shares if sent now:", shares);
// Send with your wallet client: await walletClient.writeContract(request);
```
