" MicromOne: Building a Complete Collateralized Lending DApp on Ethereum Sepolia: From Smart Contract to Verified Deployment

Pagine

Building a Complete Collateralized Lending DApp on Ethereum Sepolia: From Smart Contract to Verified Deployment

Developing a blockchain application is not just about writing a Solidity contract. A production-ready decentralized application requires a complete lifecycle that includes smart contract engineering, automated testing, network deployment, frontend integration, wallet connectivity, contract verification, and operational troubleshooting.

This article describes the entire development process of a collateralized lending protocol deployed on Ethereum Sepolia and explains the technical decisions, common pitfalls, debugging methods, and deployment practices required to recreate the project from scratch.

System Architecture

The application is composed of three main layers:

Frontend
   │
   ▼
MetaMask Wallet
   │
   ▼
Ethers.js
   │
   ▼
CollateralizedLoan Smart Contract
   │
   ▼
Ethereum Sepolia Testnet

The frontend executes in the browser.

MetaMask manages private keys and transaction signing.

Ethers.js acts as the communication layer between the user interface and the blockchain.

The Solidity smart contract stores loan data and enforces all business rules.

The Business Model

The protocol implements a collateralized peer-to-peer lending mechanism.

There are two actors:

Borrower

The borrower deposits collateral and requests a loan.

The borrower is required to lock cryptocurrency inside the smart contract before receiving any funds.

Lender

The lender funds a loan request.

The lender receives interest when the borrower repays.

If the borrower fails to repay before the deadline, the lender can claim the collateral.

Smart Contract Design

The core data structure is a loan object:

struct Loan {
    address payable borrower;
    address payable lender;
    uint256 collateralAmount;
    uint256 loanAmount;
    uint256 interestRate;
    uint256 dueDate;
    bool isFunded;
    bool isRepaid;
}

The loan structure contains:

  • borrower address
  • lender address
  • collateral amount
  • loan amount
  • interest rate
  • due date
  • funding status
  • repayment status

These values are stored in:

mapping(uint256 => Loan) public loans;

Every loan receives a unique identifier:

uint256 public nextLoanId;

Creating Loans

A borrower creates a loan using:

depositCollateralAndRequestLoan()

The process includes:

  1. Sending collateral
  2. Defining interest rate
  3. Defining loan duration
  4. Generating loan record

Typical validation rules include:

require(
    msg.value > 0,
    "Collateral must be greater than zero"
);
require(
    duration > 0,
    "Duration must be greater than zero"
);

Funding Loans

Funding is performed through:

fundLoan()

Important protections:

Borrower cannot fund own loan

and

Loan is already funded

The lender transfers the exact loan amount.

Once funded:

loan.isFunded = true;

and the loan principal is released to the borrower.

Repayment

Borrowers repay using:

repayLoan()

The repayment amount is calculated through:

getRepaymentAmount()

Formula:

Repayment = Principal + Interest

Example:

Loan Amount = 1 ETH
Interest Rate = 500

where

500 = 5%

Results:

Repayment = 1.05 ETH

The lender automatically receives the repayment.

The collateral is returned to the borrower.

Default and Collateral Liquidation

If a borrower fails to repay before:

dueDate

the lender may execute:

claimCollateral()

This transfers the collateral to the lender.

The protocol therefore protects the lender against default risk.

Automated Testing

Hardhat test automation is critical.

The project was validated using:

Mocha
Chai
Hardhat Toolbox

Tests included:

Deployment

nextLoanId()

verification

Loan Creation

Successful loan generation

Funding

Correct funding amount validation

Repayment

Interest calculations

Liquidation

Collateral claim after expiration

Error Handling

Validation of all:

require()

conditions

including:

Loan is not funded
Only borrower can repay
Only lender can claim collateral
Loan is already funded
Collateral must be greater than zero

Deploying to Sepolia

Deployment uses Hardhat.

Example:

npx hardhat clean
npx hardhat compile

followed by

npx hardhat run scripts/deploy.js --network sepolia-testnet

A successful deployment outputs:

CollateralizedLoan deployed successfully

and returns the contract address.

Example:

0x574483ba69EaE314988cC0eDBFbfea17B53759fE

Frontend Integration

The frontend uses:

loaded directly via CDN.

Connection process:

provider =
    new ethers.BrowserProvider(
        window.ethereum
    );

Wallet connection:

await provider.send(
    "eth_requestAccounts",
    []
);

Contract binding:

contract =
    new ethers.Contract(
        CONTRACT_ADDRESS,
        ABI,
        signer
    );

Common Problem: Wrong Network

One of the most frequent mistakes is confusing:

Ethereum Mainnet

with:

Sepolia Testnet

Chain IDs:

1          = Ethereum Mainnet
11155111   = Sepolia

The frontend should enforce:

wallet_switchEthereumChain

to guarantee the correct network.

Common Problem: OutOfFunds

A transaction can fail with:

OutOfFunds

for two reasons:

  1. Insufficient balance

or

  1. Wrong network selected

A user may own:

4 ETH on Sepolia

and simultaneously:

0 ETH on Mainnet

because balances are network-specific.

Understanding Smart Contract Errors

Smart contract reverts are useful diagnostic tools.

Example:

Loan is not funded

indicates that a repayment is attempted before funding.

Example:

Only lender can claim collateral

indicates that an unauthorized account attempted liquidation.

Proper interpretation of these errors significantly accelerates debugging.

Etherscan Contract Verification

Deployment alone stores bytecode on-chain.

Verification publishes the source code.

Verified contracts provide:

Read Contract
Write Contract
Contract Source Code
ABI
Events

To verify correctly:

  • use the exact Solidity version
  • use the same optimization settings
  • use the original deployment source

A very common failure is:

Unable to find matching Contract Bytecode and ABI

which indicates that the uploaded source generates a different bytecode than the deployed contract.

Optimizer Settings

A critical lesson is understanding compiler optimization.

Two compilations of the same Solidity file can generate different bytecode:

Optimizer OFF

versus

Optimizer ON

Although functionality remains identical, Etherscan compares deployed bytecode bit-for-bit.

If deployment used:

Optimizer = ON
Runs = 200

then verification must use exactly:

Optimizer = ON
Runs = 200

Otherwise verification fails.

Operational Workflow

The complete lifecycle of a collateralized loan is:

Borrower
    ↓
Create Loan
    ↓
Lender
    ↓
Fund Loan
    ↓
Borrower
    ↓
Repay Loan
OR
Borrower
    ↓
Default
    ↓
Lender
    ↓
Claim Collateral

This lifecycle demonstrates a complete decentralized financial workflow implemented through immutable smart contract logic rather than traditional server-side software.

Building a lending DApp is far more than writing Solidity. The real engineering effort lies in connecting multiple domains:

  • smart contracts
  • blockchain security
  • automated testing
  • wallet integration
  • frontend development
  • network deployment
  • verification pipelines
  • debugging infrastructure

By combining Hardhat, Solidity, MetaMask, Ethers.js, Sepolia, and Etherscan, it is possible to create a full-stack decentralized application that mirrors real-world financial workflows while maintaining transparency, auditability, and trustless execution.