CrediTrust
Your Crypto. Your Credit. Your Control.
Created on 26th June 2025
•
CrediTrust
Your Crypto. Your Credit. Your Control.
The problem CrediTrust solves
📢 Disclosure
This project was developed during the parallel timelines of the Coinbase Agents in Action Hackathon and Chromion: A Chainlink Hackathon.
The Chainlink-powered decentralized lending protocol was enhanced with Coinbase technologies such as:
- 🛡️ CDP Wallet – for secure, programmable wallet integration
- 💸 x402pay – for monetization of on-chain credit-scoring agents
The project satisfies the unique requirements of both hackathons, and all development occurred within their official timeframes.
📊 Chainlink Data Feeds: Dynamic Risk Pricing
- Real-time Asset Pricing: ETH/USD feeds ensure accurate collateral valuations
- Market-driven Rates: Interest rates adjust based on live market conditions
- Automated Liquidations: Chainlink price feeds trigger automatic liquidations when needed
- Cross-asset Support: Support for any asset with Chainlink price feeds
⚡ Chainlink Automation: Self-Managing Loans
- Automatic Interest Calculations: No manual intervention required
- Scheduled Payments: Automated monthly payment processing
- Health Monitoring: Continuous monitoring of loan-to-value ratios
- Emergency Liquidations: Instant liquidation when thresholds are breached
What People Can Use It For
🌍 Global Financial Inclusion
For the Unbanked (2B+ People)
Maria in rural Guatemala has no credit history but owns a small coffee farm.
She can:
- Stake her farm equipment as collateral (tokenized)
- Get matched with global lenders via Chainlink VRF
- Receive USDC loans for seed purchases
- Build on-chain credit history for better future rates
For Cross-Border Business
Ahmed, a textile exporter in Bangladesh needs working capital:
- Uses local assets as collateral
- Gets matched with US/EU lenders automatically
- Receives payments in stablecoins instantly
- Pays competitive rates based on real-time Chainlink data
💰 Superior Investment Opportunities
For Yield Seekers
- Higher Returns: Earn 8-15% APR vs 1-3% in traditional savings
- Automated Portfolio: Chainlink VRF distributes your capital across multiple borrowers
- Risk-Adjusted Pricing: Chainlink data feeds ensure fair compensation for risk
- Global Diversification: Lend to borrowers across multiple countries and sectors
🚀 DeFi Innovation
Leverage Trading
DeFi Trader Scenario:
- Stake 100 ETH as collateral (valued via Chainlink ETH/USD)
- Borrow 80 ETH worth of stablecoins
- Use borrowed funds for yield farming
- Chainlink Automation monitors position health
- Automatic liquidation prevents total loss
Cross-Chain Arbitrage
- Multi-Chain Lending: Deploy on Ethereum, Polygon, Arbitrum simultaneously
- Unified Pricing: Chainlink price feeds ensure consistent rates across chains
- Automated Opportunities: Borrow on cheap chains, lend on expensive chains
How It Makes Things Safer & Easier
🛡️ Safety Through Chainlink Integration
Eliminates Human Error & Bias
- ✅ VRF Randomness: Mathematically provable fair lender selection
- ✅ Automated Pricing: No human manipulation of interest rates
- ✅ Real-time Monitoring: Chainlink Automation prevents manual oversight failures
- ✅ Transparent Liquidations: All actions triggered by verifiable price data
Prevents Market Manipulation
// Example: Chainlink-protected liquidation
function checkLiquidation(address borrower) external {
int256 ethPrice = chainlinkPriceFeed.latestAnswer();
uint256 collateralValue = (collateralAmount * uint256(ethPrice)) / 1e8;
uint256 debtValue = getDebtWithInterest(borrower);
if (collateralValue * 100 < debtValue * LIQUIDATION_THRESHOLD) {
_liquidate(borrower); // Automatic, no human intervention
}
}
Cross-Chain Security
- Unified Risk Models: Same Chainlink data across all supported chains
- Consistent Liquidation: Identical protection mechanisms everywhere
- Atomic Cross-Chain Operations: Use Chainlink CCIP for secure cross-chain lending
⚡ Easier User Experience
One-Click Global Lending
- Connect Wallet → Platform detects all your assets across chains
- Set Preferences → Choose risk level, loan duration, geographic preferences
- Stake Assets → Chainlink VRF automatically matches you with borrowers
- Earn Passively → Chainlink Automation handles everything else
Intelligent Loan Management
- Smart Notifications: Get alerted before liquidation thresholds
- Automated Payments: Set up recurring payments that execute via Chainlink Automation
- Dynamic Rates: Your rate improves automatically as your credit score increases
Challenges I ran into
🚨 Major Technical Hurdles
1. Chainlink VRF Integration on Local Networks
Problem: Chainlink VRF requires a subscription and coordinator that doesn't exist on local Hardhat networks.
Error Encountered:
// This would fail on localhost
function requestRandomLender() internal {
uint256 requestId = COORDINATOR.requestRandomWords(
keyHash,
s_subscriptionId,
requestConfirmations,
callbackGasLimit,
numWords
);
}
Solution Implemented:
// Smart fallback for local testing
function openCDP(uint256 _collateralAmount, uint256 _creditScore) external {
if (address(COORDINATOR) == address(0)) {
// Local testing: direct assignment
_assignFirstAvailableLender(msg.sender);
} else {
// Production: use Chainlink VRF
_requestRandomLender(msg.sender);
}
}
function fulfillRandomWords(uint256, uint256[] memory randomWords) internal override {
address borrower = s_requests[requestId];
address[] memory availableLenders = getAvailableLenders();
uint256 selectedIndex = randomWords[0] % availableLenders.length;
_assignLender(borrower, availableLenders[selectedIndex]);
}
Key Learning: Always design smart contracts with testnet/mainnet differences in mind.
2. Chainlink Price Feed Integration Complexity
Problem: Managing multiple price feeds for different collateral types while handling feed failures gracefully.
Challenge: Price feeds can become stale or fail, which could freeze all liquidations.
Solution:
contract ChainlinkPriceManager {
mapping(address => AggregatorV3Interface) public priceFeeds;
mapping(address => uint256) public heartbeats; // Max staleness allowed
function getPrice(address asset) external view returns (uint256) {
AggregatorV3Interface feed = priceFeeds[asset];
(uint80 roundId, int256 price, , uint256 updatedAt, ) = feed.latestRoundData();
require(price > 0, "Invalid price");
require(block.timestamp - updatedAt <= heartbeats[asset], "Stale price");
require(roundId > 0, "Round not complete");
return uint256(price);
}
// Fallback to backup feeds if primary fails
function getPriceWithFallback(address asset) external view returns (uint256) {
try this.getPrice(asset) returns (uint256 price) {
return price;
} catch {
return getBackupPrice(asset);
}
}
}
3. Cross-Chain State Synchronization
Problem: Keeping lending pools and borrower data synchronized across multiple chains.
Challenge: A borrower could potentially double-spend collateral across chains.
Solution Using Chainlink CCIP:
// Cross-chain borrower registry
contract CrossChainBorrowerRegistry is CCIPReceiver {
mapping(address => uint256) public globalDebt;
mapping(uint64 => bool) public trustedChains;
function notifyLoanCreated(
uint64 destinationChain,
address borrower,
uint256 amount
) external {
bytes memory data = abi.encode(borrower, amount, "LOAN_CREATED");
Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({
receiver: abi.encode(crossChainRegistries[destinationChain]),
data: data,
tokenAmounts: new Client.EVMTokenAmount[](0),
extraArgs: "",
feeToken: address(0)
});
router.ccipSend(destinationChain, message);
}
function _ccipReceive(Client.Any2EVMMessage memory message) internal override {
(address borrower, uint256 amount, string memory action) =
abi.decode(message.data, (address, uint256, string));
if (keccak256(bytes(action)) == keccak256("LOAN_CREATED")) {
globalDebt[borrower] += amount;
emit CrossChainLoanRegistered(borrower, amount);
}
}
}
4. Chainlink Automation Gas Optimization
Problem: Chainlink Automation costs gas for every execution, making frequent health checks expensive.
Challenge: Balance between safety (frequent checks) and cost (gas fees).
Solution - Smart Trigger Logic:
contract OptimizedAutomation {
uint256 private lastCheckBlock;
uint256 private constant CHECK_INTERVAL = 100; // blocks
function checkUpkeep(bytes calldata) external view override returns (
bool upkeepNeeded,
bytes memory performData
) {
// Only check if enough blocks have passed
if (block.number - lastCheckBlock < CHECK_INTERVAL) {
return (false, "");
}
// Batch check multiple loans
address[] memory loansToLiquidate = new address[](0);
uint256 count = 0;
for (uint i = 0; i < activeBorrowers.length && count < 10; i++) {
address borrower = acti
Tracks Applied (2)
