A Simple Crypto-Backed Lending System (Built with Solidity, Foundry, Viem & Anvil)
MiniLend is a decentralized lending application where users can:
✅ Stake ETH as collateral ✅ Borrow a mock USD token (MockUSDT) based on collateral value ✅ Repay borrowed tokens ✅ Withdraw their collateral
This project is designed with learning and experimentation in mind, especially for beginners entering the Web3 space.
Before you begin, make sure you have the following installed:
Foundry is used for:
- Compiling smart contracts
- Running the local blockchain (Anvil)
- Deploying contracts using deployment scripts
Install Foundry:
curl -L https://foundry.paradigm.xyz | bashReload your terminal:
source ~/.bashrcInstall components:
foundryupVerify:
forge --version
anvil --version❗❗❗ If forge is showing error, it might be using zoe forge library and that is not what we want run
export PATH="$HOME/.foundry/bin:$PATH"to change the path and confirm the forge with
which forgeit should show
/.foundry/bin/forgeAnvil simulates a local Ethereum network with funded accounts.
Run:
anvilYou should see something like:
Listening on 127.0.0.1:8545
and a list of 10 private keys + addresses funded with 10,000 ETH.
✅ Keep this terminal running ❗ Do NOT close it
From the Anvil output, copy the first private key:
Example:
0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
Create a .env file:
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
✅ No quotes ✅ No spaces
This project contains two contracts:
MockUSDT.sol– a mintable ERC20 tokenMiniLend.sol– the lending logic
Deployment is done using a Foundry deploy script.
Run:
source .env
forge script script/Deploy.s.sol --rpc-url http://127.0.0.1:8545 --broadcast --private-key $PRIVATE_KEYIf successful, the output will show something like:
Deployed MockUSDT at: 0x....
Deployed MiniLend at: 0x....
✅ COPY both contract addresses You will need them in the DApp
Open MetaMask → top network dropdown → Add Network
Click:
Add network manually
Enter:
Network Name: Anvil
RPC URL: http://127.0.0.1:8545
Chain ID: 31337
Currency Symbol: ETH
Save. (Chrome browser preferable)
Click:
MetaMask → Account → Import Account
Paste the same private key from .env
Now MetaMask shows:
✅ Local network ✅ 10,000 ETH balance
If your frontend is static:
Open index.html in a browser
OR run a simple server:
npx serve .or
python3 -m http.serverYour dApp must connect to MetaMask BEFORE loading contracts
If you load contracts first:
❌ publicClient will not attach properly ❌ walletClient will have no account ❌ calls will fail
So:
- Open the DApp
- Click Connect Wallet
- MetaMask will pop up
- Accept connection
You should now see something like:
Connected: 0x643...345
Paste:
✅ MiniLend contract address ✅ MockUSDT token address
Then click:
👉 Load Contracts
If successful:
Contracts loaded
Now you can interact:
Enter an amount (e.g. 1)
Click:
🟩 Stake
Expected:
- Your staked balance increases
- Contract ETH balance increases
Enter amount within LTV limit
Click:
🟨 Borrow
Expected:
- Your mock USDT balance increases
- Contract USDT decreases or mints
Before repaying, you must approve MiniLend to spend your USDT
Click:
🟦 Approve
Enter amount to repay
Click:
🟥 Repay
Only works when:
✅ You have fully repaid ✅ You have staked ETH
| Problem | Cause | Fix |
|---|---|---|
| No MetaMask popup | Not served with HTTP / module import error | Use local server |
| Cannot load contract | Wallet not connected first | Connect wallet before load |
| Balance shows 0 | Wrong address or wrong chain | Check Anvil + MetaMask network |
| ABI invalid | Importing wrong field | Use abi: MiniLendAbi.abi |
contracts/
MiniLend.sol
MockUSDT.sol
script/
Deploy.s.sol
frontend/
index.html
script.js
abi/
By following this guide, you learned:
✅ How to run a local blockchain (Anvil) ✅ How deployment scripts work in Foundry ✅ How to connect MetaMask to a local chain ✅ How to connect a DApp to MetaMask using Viem ✅ How to interact with deployed contracts
This is the exact journey every Web3 developer goes through, and now you have a full working workflow.
This project exists because:
"I was once a newbie who couldn't do anything without detailed steps."
If this README helps even one developer avoid frustration, then it has achieved its purpose.
Keep building. Keep learning. Your progress is inspiring. 🚀🔥