Cross-Chain Lending Protocol
Experience decentralized cross-chain lending with ETH collateral on Ethereum Sepolia and MATIC loans on Kopli Testnet, powered by Reactive Network's smart contracts for seamless automation and transparency.
Introduction
This article introduces a cross-chain lending protocol that allows users to borrow assets across multiple blockchains. Built on Ethereum Sepolia and Kopli Testnet, this protocol leverages a decentralized mechanism to support secure cross-chain communication via the Reactive Network. Users can deposit ETH as collateral on Ethereum Sepolia, request a loan, and receive MATIC on Kopli Tetnet, repaying in MATIC as well.
This implementation is created, based on the code of Harsh Kasana, winner of the Reactive Hackathon Bi-Weekly Challenge. Explore his project here and watch the demo. We also extend special recognition to our talented runners-up; their impressive submissions can be viewed here and here. Thank you to all participants for your outstanding work!
Architecture Components
Lending Token
MATIC.sol is an ERC-20 contract represents MATIC on Kopli Testnet. It includes the `mint()` and `burn()` functions for flexible token issuance during loan funding and repayment, and authorizes `DestinationContract` to mint or burn MATIC as necessary.
Origin Chain
The primary lending contract on Ethereum Sepolia. It initiates loans using ETH collateral, validating loan requests through `requestLoan()` with parameters like interest rate and duration, and `depositCollateral()` to accept ETH collateral, activate loans, and notify Kopli Testnet. Upon full repayment, `releaseCollateral()` returns the collateral, while `liquidateLoan()` seizes it in case of default. Using live price feeds, `calculateRequiredCollateral()` determines necessary collateral based on ETH and MATIC prices, ensuring proper collateralization and supporting cross-chain loan monitoring.
Reactive Network Bridge
The Reactive Network’s `ReactiveContract` manages cross-chain events like `LoanRequested`, `LoanInitiated`, `LoanFullyRepaid`, and `LoanLiquidated` to maintain state consistency across networks. There are two versions of the contract.
`DTOReactive` is active on the Reactive Network. It listens for `LoanFullyRepaid` and `LoanLiquidated` events. Upon detecting `LoanFullyRepaid`, it triggers `releaseCollateral()` on Sepolia; if `LoanLiquidated` occurs, it calls `liquidateLoan()`.
`OTDReactive` runs on Ethereum Sepolia. It monitors loan events from Kopli Testnet. When the contract detects `LoanRequested` and `LoanInitiated`, it triggers `requestLoan()` to initialize the loan and `fundLoan()` to disburse funds.
Destination Chain
Deployed on Kopli Testnet, this contract manages loans in MATIC, handling funding, repayment, and liquidation. `requestLoan()` sets loan parameters, `fundLoan()` mints and disburses MATIC, and `repayLoan()` burns MATIC as repayments are made. Upon full repayment, the `LoanFullyRepaid` event releases collateral on Ethereum Sepolia, while the `liquidateLoan()` function triggers collateral seizure via the `LoanLiquidated` event, notifying `DTOReactive` to handle liquidation on Ethereum Sepolia. The contract also computes the total balance owed with `calculateTotalDue()`.
Lending dApp Flow
The lending flow involves four main stages: user onboarding, borrowing, loan management, and liquidation.
User Onboarding
The dApp’s onboarding process begins with a user connecting their wallet (e.g., MetaMask) and the dApp detecting the connected network. This setup is crucial as it determines where collateral is deposited and where loan proceeds will be transferred.
Borrowing Process
The borrowing process takes place in two stages: collateral deposit on Ethereum Sepolia and loan issuance on Kopli Testnet.
First, the user navigates to the "Borrow" tab, enters the desired ETH collateral amount, and receives various loan details such as collateral value in USD, maximum MATIC loan amount, interest rate, Loan-to-Value (LTV) ratio, and liquidation threshold, using Chainlink’s price feeds for real-time data. After confirming, the `OriginContract` on Ethereum Sepolia executes `depositCollateral()`, locking the collateral in the contract and recording loan specifics. Two events, `CollateralDeposited` and `LoanInitiated`, are emitted to confirm the deposit.
function depositCollateral() external payable nonReentrant {
require(msg.value > 0, "Collateral amount must be greater than 0");
require(loans[msg.sender].loanAmount > 0, "No loan requested");
require(loans[msg.sender].active == false, "Loan already active");
uint256 requiredCollateral = calculateRequiredCollateral(loans[msg.sender].loanAmount);
require(msg.value >= requiredCollateral, "Insufficient collateral");
loans[msg.sender].collateralAmount = msg.value;
loans[msg.sender].active = true;
emit CollateralDeposited(msg.sender, msg.value, loans[msg.sender].destinationChain, loans[msg.sender].loanAmount);
emit LoanInitiated(msg.sender, loans[msg.sender].loanAmount, loans[msg.sender].destinationChain, loans[msg.sender].interestRate, loans[msg.sender].durationInDays);
}
Once the `LoanInitiated` event is detected, the Reactive Contract on Kopli Testnet sends a cross-chain message to execute the `fundLoan()` function in the `DestinationContract`, transferring MATIC to the user’s wallet and emitting a `LoanFunded` event. The frontend updates to confirm loan issuance, completing the borrowing phase.
function fundLoan(address /*sender*/, address _borrower) external nonReentrant {
Loan storage loan = loans[_borrower];
require(loan.active && !loan.funded, "Loan is not active or already funded");
loan.funded = true;
lendingToken.mint(_borrower, loan.amount);
emit LoanFunded(_borrower, loan.amount);
}
Loan Management
Effective loan management involves real-time monitoring and repayment options to facilitate a smooth borrowing experience. The dApp regularly updates the user with critical loan information such as collateral value, amount owed (principal and interest), due date, and current LTV ratio. If the LTV ratio approaches the liquidation threshold, users are alerted, helping prevent liquidation.
To repay, users navigate to the "Repay" tab, select their loan, enter the repayment amount in MATIC, and confirm. The `repayLoan()` function in the `DestinationContract` updates the loan status, and on full repayment, emits a `LoanFullyRepaid` event. A cross-chain message is then triggered, allowing the release of collateral on Ethereum Sepolia.
function repayLoan(uint256 _amount) external nonReentrant {
Loan storage loan = loans[msg.sender];
require(loan.active && loan.funded, "No active funded loan found");
require(_amount > 0, "Repayment amount must be greater than 0");
uint256 totalDue = calculateTotalDue(msg.sender);
require(_amount <= totalDue, "Repayment amount exceeds total due");
lendingToken.burn(msg.sender, _amount);
loan.repaidAmount += _amount;
emit LoanRepaid(msg.sender, _amount);
if (loan.repaidAmount >= totalDue) {
loan.active = false;
emit LoanFullyRepaid(msg.sender);
uint256 overpayment = loan.repaidAmount - totalDue;
if (overpayment > 0) {
lendingToken.mint(msg.sender, overpayment);
}
}
}
Once notified of full repayment, the `OriginContract` on Ethereum Sepolia calls `releaseCollateral()`, unlocking the ETH collateral and transferring it back to the user. The `CollateralReleased` event confirms this release, and the frontend reflects the updated balance.
function releaseCollateral(address /*sender*/,address _user) external {
require(loans[_user].active, "No active loan found");
uint256 collateralAmount = loans[_user].collateralAmount;
delete loans[_user];
(bool sent, ) = _user.call{value: collateralAmount}("");
require(sent, "Failed to send ETH");
emit CollateralReleased(_user, collateralAmount);
}
Liquidation Process
Liquidation ensures that loans exceeding the acceptable risk threshold are promptly addressed. An off-chain bot or the dApp monitors all loans, triggering the `liquidateLoan()` function in the `DestinationContract` if a loan’s LTV ratio surpasses the liquidation threshold.
function liquidateLoan(address _borrower) external onlyOwner {
Loan storage loan = loans[_borrower];
require(loan.active && loan.funded, "No active funded loan found");
uint256 totalDue = calculateTotalDue(_borrower);
uint256 liquidationValue = totalDue * liquidationThreshold / 100;
require(loan.repaidAmount < liquidationValue, "Liquidation threshold not met");
uint256 liquidationAmount = totalDue - loan.repaidAmount;
loan.active = false;
emit LoanLiquidated(_borrower, liquidationAmount);
}
In the liquidation process, the `DestinationContract` on Kopli Testnet marks the loan as liquidated, transferring funds to an insurance account or administrator if needed. A cross-chain message notifies Ethereum Sepolia, where the `OriginContract` verifies the loan status, initiating `liquidateLoan()` to distribute the collateral. Both contracts emit a `LoanLiquidated` event for complete transparency.
Conclusion
This cross-chain lending protocol is a decentralized approach to asset-backed lending across Ethereum Sepolia and Kopli Testnet. By allowing users to deposit ETH as collateral and receive MATIC loans, the protocol utilizes the Reactive Network for secure cross-chain communication, ensuring data consistency and transparency across networks. With features like real-time monitoring, automated liquidation, and secure repayment, it offers an effortless borrowing experience while safeguarding assets.
The protocol includes security measures to protect assets and maintain cross-chain data integrity. Key features include collateral validation, cross-chain message verification, integration with an interest rate oracle, liquidation threshold monitoring, emergency pause capability, and access control for administrative functions. These mechanisms ensure that funds are managed securely, assets are backed by valid collateral, and protocol operations remain stable under adverse conditions.
About Reactive Network
The Reactive Network, pioneered by PARSIQ, ushers in a new wave of blockchain innovation through its Reactive Smart Contracts (RSCs). These advanced contracts can autonomously execute based on specific on-chain events, eliminating the need for off-chain computation and heralding a seamless cross-chain ecosystem vital for Web3’s growth.
Central to this breakthrough is the Inversion of Control (IoC) framework, which redefines smart contracts and decentralized applications (DApps) by imbuing them with unparalleled autonomy, efficiency, and interactivity. By marrying RSCs with IoC, Reactive Network is setting the stage for a transformative blockchain era, characterized by enhanced interoperability and the robust, user-friendly foundation Web3 demands.