What is Lending? - Earn interest by depositing tokens into the pool. Borrow against available liquidity.
This Guide Covers:
- How deposits & withdrawals work
- How borrowing & repayment works
- Scheduled payouts from lending balance
- Health factor & liquidation (future)
- Risk management & best practices
┌─────────────────────────────────────────┐
│ LENDING POOL (Smart Contract) │
├─────────────────────────────────────────┤
│ │
│ 💰 DEPOSITS (User Funds) │
│ ├─ USDC: $1,000 (5 users) │
│ ├─ ETH: 2.5 ETH (3 users) │
│ └─ WBTC: 0.1 BTC (2 users) │
│ │
│ 🏦 LENDERS (Earn Interest) │
│ ├─ Alice deposited $500 USDC │
│ ├─ Bob deposited 1.0 ETH │
│ └─ Charlie deposited 0.05 WBTC │
│ │
│ 🔒 BORROWED TOKENS (Loans) │
│ ├─ Dave borrowed $300 USDC │
│ ├─ Eve borrowed 0.5 ETH │
│ └─ Frank borrowed 0.02 WBTC │
│ │
└─────────────────────────────────────────┘
POOL HEALTH:
Total Supplied: $1,000 USDC + 2.5 ETH + 0.1 BTC
Total Borrowed: $300 USDC + 0.5 ETH + 0.02 BTC
Available: $700 USDC + 2.0 ETH + 0.08 BTC
Utilization: 30% (healthy)
| Metric | Formula | Current | Status |
|---|---|---|---|
| Supplied | ∑ user deposits | $1,000 | Base liquidity |
| Borrowed | ∑ user loans | $300 | Active loans |
| Available | Supplied - Borrowed | $700 | Can withdraw/borrow |
| Utilization | Borrowed / Supplied | 30% | Healthy (< 95%) |
| Interest Rate | v0.2 feature | 0% | Coming soon |
Step 1: Approve Token Spending
// In your wallet
User → MetaMask: "I approve LendingPool to use my tokens"
MetaMask: Shows "Approval required" popup
User: Clicks Confirm
Result: ✅ Approval grantedStep 2: Deposit Tokens
// User deposits USDC into pool
function deposit(address token, uint256 amount) external nonReentrant {
require(amount > 0, "amount > 0");
// Transfer tokens from user to pool
IERC20(token).transferFrom(msg.sender, address(this), amount);
// Record the deposit
scaledBalances[token][msg.sender] += amount;
totalSupplied[token] += amount;
// Emit event (visible in transaction history)
emit Deposited(token, msg.sender, amount);
}Before Deposit:
Alice's Wallet: 5000 USDC
Pool Total: 0 USDC
Alice's Balance in Pool: 0 USDC
Transaction: deposit(USDC, 1000)
✓ Approval already granted
✓ 1000 USDC transferred Alice → Pool
✓ Pool records Alice's 1000 USDC
After Deposit:
Alice's Wallet: 4000 USDC (1000 moved to pool)
Pool Total: 1000 USDC
Alice's Balance in Pool: 1000 USDC
Status: ✅ Deposit successful
Interest earned: 0% (v0.1 MVP)
Can withdraw: Yes, anytime
Can borrow against: Coming in v0.2
| Aspect | Status | Details |
|---|---|---|
| Loss of Funds | ✅ Safe | Smart contract is audited (testnet) |
| Emergency Withdrawal | ⏳ v0.2 | Can withdraw anytime (no lock period) |
| Interest Earned | ⏳ v0.2 | 0% in MVP (planned for v0.2) |
| Liquidation Risk | 🟢 None | Only matters if you borrow (future) |
| Network Risk | ✅ Low | Testnet only, test tokens |
- No collateral checking
- No liquidation mechanism
- No interest accrual
- Pool can go underwater
See Smart Contract Audit for details.
Borrow Requirements:
150% Collateral Ratio (You must have collateral)
Example:
You deposit: $1,000 USDC
Max borrow: $666.67 USDC (66% of deposit)
Reason: 150% collateral ratio = safety buffer
Formula:
max_borrow = collateral_value × 0.66
// Step 1: Deposit collateral first
user.deposit(USDC, 1000); // I'll loan against this
// Step 2: Borrow up to 66% of collateral
user.borrow(USDC, 600); // Borrow up to 600 (66% of 1000)
// Step 3: Use borrowed funds
// Transfer borrowed USDC to DeFi protocol, earn yield, etc.
// Step 4: Repay when done
user.repay(USDC, 600); // Return borrowed amount
// Step 5: Withdraw collateral if needed
user.withdraw(USDC, 1000); // Get original deposit backScenario: Alice borrows against USDC deposit
1. Alice deposits 1000 USDC
Collateral: 1000 USDC
Max Borrow: 666.67 USDC
2. Alice borrows 500 USDC
Borrowed: 500 USDC
Remaining Capacity: 166.67 USDC
Health Factor: 2.0 (very safe)
3. Alice repays 250 USDC
Borrowed: 250 USDC
Remaining Capacity: 416.67 USDC
Health Factor: 4.0 (very safe)
4. Alice repays remaining 250 USDC
Borrowed: 0 USDC
Remaining Capacity: 666.67 USDC
Health Factor: ∞ (all clear)
Use Case: You want to send someone a payment from your lending balance on a specific date.
Example:
Charlie deposits 1000 USDC on Oct 1
Charlie schedules a payout:
• Recipient: alice@example.com
• Amount: 300 USDC
• Date: Nov 1, 2024
• Executor Fee: 1 USDC (paid to relayer)
On Nov 1, a relayer executes:
• 300 USDC → Alice
• 1 USDC → Relayer (fee)
• Charlie's balance: 699 USDC
function schedulePayout(
address token, // USDC
address recipient, // Alice's address
uint256 amount, // 300
uint256 releaseTimestamp, // Nov 1 timestamp
uint256 executorFee // 1 (for relayer)
) external nonReentrant returns (uint256) {
// Lock the funds from Charlie's balance
pool.lockForScheduleOnBehalf(token, msg.sender, amount);
// Create schedule record
schedules[nextId] = Scheduled({
id: nextId,
owner: msg.sender, // Charlie
token: token, // USDC
recipient: recipient, // Alice
scaledAmount: amount, // 300
releaseTimestamp: releaseTimestamp, // Nov 1
executorFee: executorFee, // 1
executed: false,
cancelled: false
});
return nextId;
}function executeScheduled(uint256 id) external nonReentrant {
Scheduled storage s = schedules[id];
// Can only execute after release time
require(block.timestamp >= s.releaseTimestamp, "too early");
// Anyone can execute (relayer infrastructure)
// Mark as executed to prevent double-execution
s.executed = true;
// Transfer to recipient minus executor fee
pool.withdrawForScheduled(
s.token,
s.owner, // Charlie (funds come from here)
s.recipient, // Alice (funds go here)
s.scaledAmount, // 300 USDC
s.executorFee // 1 USDC to executor
);
}TIME BEFORE → Oct 1 Nov 1 Nov 2 onwards
Schedule Created Release Time Can Execute
↓ ↓ ↓
Phase 1 Charlie deposits 1000 USDC
(Setup) Charlie schedules: 300 USDC → Alice on Nov 1
Status: LOCKED (funds reserved, can't be withdrawn)
Phase 2 Relayer checks: Is Nov 1 here? NO
(Waiting) Keeps checking...
Nov 1 arrives ✓
Phase 3 Relayer executes payout:
(Execution) • Alice receives 300 USDC
• Relayer receives 1 USDC fee
• Charlie's balance: 699 USDC
Status: EXECUTED
Result: ✅ Automatic payment processed
✅ Relayer incentivized (gets fee)
✅ No manual intervention needed
Oct 1: Charlie schedules: 300 USDC → Alice on Nov 1, fee 1 USDC
Oct 15: Relayer checks but time hasn't passed, skips
Nov 1: Relayer detects release time, executes
Alice: +300 USDC
Relayer: +1 USDC
Charlie: 699 USDC remaining
Result: ✅ Success
Oct 1: Charlie schedules: 300 USDC → Alice on Nov 1
Oct 20: Charlie changes mind, cancels
Locked funds: 300 USDC → Charlie
Charlie's balance: 1000 USDC again
Oct 30: Relayer tries to execute but schedule is cancelled
Transaction reverts
Result: ✅ Charlie got funds back
Oct 1: Charlie schedules: 300 USDC → Alice on Nov 1
Nov 2: Nobody executed the schedule yet
Nov 30: Relayer finally executes
Works! Alice gets 300, relayer gets 1
Result: ✅ Still works (no expiration time limit)
Oct 1: Charlie deposits 1000 USDC, schedules 300 → Alice
Oct 15: Charlie withdraws 800 USDC
Remaining: 200 USDC (not enough for 300 payout!)
Nov 1: Relayer tries to execute
Check: 300 locked but only 200 available
Transaction reverts ❌
Result: ❌ Payment fails (insufficient balance)
| Use Case | Benefit | Example |
|---|---|---|
| Salary Payments | Automate recurring payments | Company pays employees monthly |
| Loan Installments | Scheduled repayment | Borrow today, auto-repay monthly |
| DCA (Dollar Cost Average) | Automatic investing | Invest $100/month automatically |
| Vesting Schedules | Gradual token release | Employee stock vesting |
| Bill Payments | Scheduled bills | Rent, subscriptions, insurance |
Available Liquidity:
┌─ USDC ────────────────────┐
│ Supplied: $50,000 │
│ Borrowed: $15,000 │
│ Available: $35,000 │
│ Utilization: 30% │
└───────────────────────────┘
┌─ ETH ─────────────────────┐
│ Supplied: 10 ETH │
│ Borrowed: 2.5 ETH │
│ Available: 7.5 ETH │
│ Utilization: 25% │
└───────────────────────────┘
┌─ WBTC ────────────────────┐
│ Supplied: 0.5 BTC │
│ Borrowed: 0.1 BTC │
│ Available: 0.4 BTC │
│ Utilization: 20% │
└───────────────────────────┘
DEPOSITS (Earning Interest):
USDC: 1000 [Status: Deposited]
ETH: 0.5 [Status: Deposited]
WBTC: 0.01 [Status: Deposited]
BORROWED:
USDC: 0 [Status: No Loans]
SCHEDULED PAYOUTS:
ID#1: 300 USDC → Alice on Nov 1 [Status: Locked]
ID#2: 0.1 ETH → Bob on Dec 1 [Status: Locked]
HEALTH FACTOR: ∞ (No borrowing = infinite safety)
AVAILABLE TO BORROW: $666.67 (66% of $1000 collateral)
| Risk | Severity | Details | Mitigation |
|---|---|---|---|
| No Interest | 🟡 Medium | Deposits earn 0% | Waiting for v0.2 |
| No Collateral Check | 🔴 Critical | Anyone can borrow | Don't borrow yet |
| No Liquidation | 🔴 Critical | No way to close bad loans | Don't borrow yet |
| Testnet Only | 🟢 Low | All test tokens, no real value | Use main-net when ready |
| No Fee Collection | 🟡 Medium | Protocol doesn't earn fees | Future revenue model |
Scenario:
Pool has 1000 USDC supplied
Pool has 900 USDC borrowed
Dave borrows remaining 100 USDC
Pool now 100% utilization (all tokens out)
What if Dave doesn't repay?
• Alice wants to withdraw 500 USDC
• Pool only has 100 USDC left
• Transaction reverts: "insufficient liquidity"
• Alice is locked in!
Prevention (v0.2):
• Collateral requirements
• Liquidation mechanism
• Interest rates to incentivize repayment
Scenario:
Charlie deposits 1000 USDC
Schedules 500 USDC payout for Nov 1
Tries to withdraw: 500 USDC
Transaction reverts: "insufficient balance"
Why?
Locked funds aren't withdrawable
Only 500 USDC available (1000 - 500 locked)
Solution:
Cancel the schedule first
Then withdraw
Scenario:
Oct 1: Charlie schedules payout
Nov 1: Relayer executes
If balance too low:
Transaction reverts
Alice never receives payment
Relayer wasted gas
No notification system yet
Future Fix:
Fallback mechanism
Notification system
Emergency withdrawal
Start with MINIMUM to test approval flow:
USDC: 0.01 (1 cent)
ETH: 0.0001 (fraction of cent)
WBTC: 0.00001 (tiny amount)
ARC: 0.01 (test token)
| Test | Amount | Purpose | Expectation |
|---|---|---|---|
| Deposit Test | 0.01 USDC | Verify deposit works | ✅ Approve → Deposit → Confirm |
| Withdraw Test | 0.005 USDC | Verify withdrawal | ✅ Partial withdrawal works |
| Schedule Test | 0.005 USDC | Verify scheduling | ✅ Can schedule future payment |
| Multi-Token | Mix above | Multiple tokens | ✅ Pool tracks each token |
| Balance Check | View → Dashboard | Verify state | ✅ UI matches chain state |
❌ DON'T TEST:
• Borrowing (no collateral checking yet)
• Large amounts (unnecessary risk)
• Interest accrual (not implemented)
• Liquidations (not implemented)
• Complex scenarios (wait for v0.2)
⏳ WAIT FOR v0.2:
• Interest earning
• Collateral ratios
• Liquidation testing
• Complex loan scenarios
┌─────────────────────────────────────────────────────────┐
│ COMPLETE LENDING FLOW │
└─────────────────────────────────────────────────────────┘
STEP 1: APPROVE (Day 1)
Alice: "I approve LendingPool to use my USDC"
MetaMask: Shows "Approval" popup
Alice: Clicks Confirm
Chain: ✅ Approval recorded
STEP 2: DEPOSIT (Day 1, after approval)
Alice: Deposits 1000 USDC
UI: Shows "Depositing..."
MetaMask: Shows "Deposit" transaction
Alice: Clicks Confirm
Chain: 1000 USDC transferred Alice → LendingPool
Dashboard: Shows 1000 USDC in "Deposits"
STEP 3: SCHEDULE (Day 1, any time after deposit)
Alice: "Send 300 USDC to Bob on Jan 1"
UI: Shows "Schedule Payout" form
Alice: Enters Bob's address, amount, date, fee
MetaMask: Shows "Schedule" transaction
Alice: Clicks Confirm
Chain: 300 USDC locked, schedule created
Dashboard: Shows "300 USDC scheduled for Jan 1"
STEP 4: WAIT (Days 2-31)
Alice: Can view locked funds anytime
Relayer: Monitors for release time
Jan 1 approaches...
STEP 5: EXECUTE (Jan 1)
Relayer: Detects release time is here
Relayer: Calls executeScheduled(id)
MetaMask: Shows "Execute" transaction
Relayer: Confirms (pays gas)
Chain:
• 300 USDC transferred Alice → Bob
• 1 USDC fee to relayer
• 699 USDC remains with Alice
FINAL STATE (After Execution):
Alice's Pool Balance: 699 USDC
Bob's Wallet: +300 USDC
Relayer's Wallet: +1 USDC (fee)
Status: ✅ Complete
-
MetaMask Connected
- Check: "Arc Testnet" network selected
- Action: Connect wallet
-
Test Tokens Available
- Check: Have 0.01+ USDC in wallet
- Action: Use faucet if needed
-
Approval Granted
- Check: Read approval explanation (WBTC_ARC_APPROVAL_EXPLAINED.md)
- Action: Click "Approve" when prompted
-
Amount is Small
- Check: Depositing < $1 test value
- Check: Using testnet tokens
- Action: Start with 0.01 USDC
-
Understand Limitations
- Read: "Risks & Limitations" section above
- Know: No interest yet (v0.1)
- Know: Borrowing disabled (design issue)
-
Documentation Reviewed
- Read: This guide
- Read: QUICK_REFERENCE_RED_ALERT.md (if seeing alerts)
- Read: INDEX.md (navigation)
-
Verify in Dashboard
- Check: Deposit shows in "My Deposits"
- Check: Balance matches transaction
-
Check Transaction History
- Click: "View on Explorer"
- Verify: Amount and recipient correct
-
Test Withdrawal
- Amount: Withdraw 50% of deposit
- Check: Balance updates instantly
-
Ready for Next Step
- Option 1: Try scheduling payout
- Option 2: Try different token
- Option 3: Report any issues
What: Deposits will earn interest based on utilization rate
How:
Interest Index updates every block
New_Index = Old_Index × (1 + APY × timeDelta)
Your_Earnings = Deposit × (New_Index / Old_Index)
Example:
Alice deposits 1000 USDC at 5% APY
After 1 year: 1050 USDC (50 USDC interest)
After 2 years: 1102.50 USDC (102.50 USDC interest)
What: Borrowing will require collateral
How:
Borrow_Limit = Collateral × 0.66
Max_Borrow = 66% of collateral value
Liquidation if health factor < 1.0
Example:
Alice deposits 1000 USDC
Max borrow: 660 USDC (66% of collateral)
Can borrow freely up to 660
Can't borrow more than 660
What: If loan goes bad, liquidators can close it
How:
If Health Factor < 1.0:
Liquidator can repay loan
Liquidator gets penalty reward
User's collateral is seized
Interest is distributed to lenders
- ROADMAP_V0.2_INTEREST_ACCRUAL.md - Detailed v0.2 plans
- SMART_CONTRACT_AUDIT.md - Current limitations
A: v0.2 (coming soon). See ROADMAP_V0.2_INTEREST_ACCRUAL.md for timeline.
A: On testnet: No (test tokens). On mainnet: Only if protocol has bugs (unlikely after audit).
A: It's MetaMask's generic template. See WBTC_ARC_APPROVAL_EXPLAINED.md for full explanation.
A: Technically yes but NOT RECOMMENDED. No collateral checking. See audit for details.
A: Withdrawals and borrowing will fail. Need more deposits to restore liquidity.
A: Yes! Call cancelScheduled(id) anytime before execution. Funds unlock instantly.
A: Transaction fails with "insufficient balance". Cancel the schedule first.
A: You set the executor fee (1 USDC typical). That's paid from your withdrawal, not separate.
Issues with deposits/withdrawals?
- Check: QUICK_REFERENCE_RED_ALERT.md
- Check: This guide's FAQ section
- Check: SMART_CONTRACT_AUDIT.md
Questions about approvals?
- Read: WBTC_ARC_APPROVAL_EXPLAINED.md
- Section: "🧪 Testnet Safety Rules"
- Section: "Quick Checklist Before Swapping"
Developer implementing?
- See: ENHANCED_METAMASK_ALERT_IMPLEMENTATION.md
- Reference: Lending Pool interface in contracts
Questions about v0.2?
- See: ROADMAP_V0.2_INTEREST_ACCRUAL.md
- See: Interest accrual mechanism details
Documentation:
- INDEX.md - Full documentation hub
- SMART_CONTRACT_AUDIT.md - Security audit & issues
- ROADMAP_V0.2_INTEREST_ACCRUAL.md - Future features
Technical:
- LendingPool.sol - Smart contract source code
- ScheduledPayoutManager.sol - Scheduled payout contract
- GenericAMMPair.sol - For understanding interest calculation (v0.2)
Standards:
- ERC20 Token Standard
- AAVE Protocol Documentation - Reference for v0.2
- Compound Protocol - Alternative design
Last Updated: October 31, 2025
Status: v0.1 MVP Complete
Next Update: v0.2 Implementation